2011年11月11日

找到 X. 509 的憑證私鑰位置並為其加入 ACL 權限

有時候系統在存取 X.509 私鑰時因所使用的服務帳戶權限不足,而導致存取被拒的情況發生,因此一般人可能都會用像是 findprivatekey.exe 這類工具,來找出私鑰的位置並手動加入服務帳戶的權限才能解決這個問題,而這邊將說明如何透過程式來找出 private key 的位置,並且指定 account 自動加入 ACL 的權限。


首先,我們先設計出透過憑證找出私鑰的檔案資訊物件,此物件有此檔案的路徑位置資訊:
private static FileInfo GetPrivateKeyFileInfo(X509Certificate2 cert)
    {
        RSACryptoServiceProvider rsa = cert.PrivateKey as RSACryptoServiceProvider;

        if (rsa != null)
        {
            string keyFileName = rsa.CspKeyContainerInfo.UniqueKeyContainerName;
            string comAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
            string comAppDataForKeyPath = comAppDataPath + @"\Microsoft\Crypto\RSA\MachineKeys";

            if (Directory.GetFiles(comAppDataForKeyPath, keyFileName).Length > 0)
                return  new FileInfo(comAppDataForKeyPath + "\\" + keyFileName);

            string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
            string appDataForKeyPath = appDataPath + @"\Microsoft\Crypto\RSA\";
            string[] dirArray = Directory.GetDirectories(appDataForKeyPath);

            if (Directory.GetDirectories(appDataForKeyPath).Length > 0)
            {
                foreach (string dir in dirArray)
                {
                    if (Directory.GetFiles(dir, keyFileName).Length > 0)
                        return new FileInfo(dir + "\\" + keyFileName);
                }
            }

            throw new Exception("Private key 存在,但找不到它的位置");
        }

        return null;
    }

再來就是設計指定某個帳戶為 private key 的檔案加入 ACL 的權限:
private static void AddAccessToCertificate(X509Certificate2 cert, string user)
    {
        FileInfo keyFile = GetPrivateKeyFileInfo(cert);

        if (keyFile != null)
        {
            FileSecurity fs = keyFile.GetAccessControl();

            NTAccount account = new NTAccount(user);
            fs.AddAccessRule(
                new FileSystemAccessRule(account, FileSystemRights.FullControl, AccessControlType.Allow));

            keyFile.SetAccessControl(fs);
        }
    }

沒有留言:

張貼留言