如何从.NET设置X.509证书的私钥文件的读取权限
以下是将pfx添加到Cert商店的代码。
X509Store store = new X509Store( StoreName.My, StoreLocation.LocalMachine ); store.Open( OpenFlags.ReadWrite ); X509Certificate2 cert = new X509Certificate2( "test.pfx", "password" ); store.Add( cert ); store.Close();
但是,我找不到为NetworkService设置访问私钥的权限的方法。
任何人都能解释一下吗? 提前致谢。
要以编程方式执行此操作,您必须执行以下三项操作:
-
获取私钥文件夹的路径。
-
获取该文件夹中私钥的文件名。
-
将权限添加到该文件。
有关完成所有这三项操作的示例代码,请参阅此文章 (特别是查看“AddAccessToCertificate”方法)。
这个答案很晚,但我想把它发布给在这里搜索的其他人:
我在这里发现了一篇MSDN博客文章,该文章使用了CryptoKeySecurity,这里有一个C#解决方案示例:
var rsa = certificate.PrivateKey as RSACryptoServiceProvider; if (rsa != null) { // Modifying the CryptoKeySecurity of a new CspParameters and then instantiating // a new RSACryptoServiceProvider seems to be the trick to persist the access rule. // cf. http://blogs.msdn.com/b/cagatay/archive/2009/02/08/removing-acls-from-csp-key-containers.aspx var cspParams = new CspParameters(rsa.CspKeyContainerInfo.ProviderType, rsa.CspKeyContainerInfo.ProviderName, rsa.CspKeyContainerInfo.KeyContainerName) { Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore, CryptoKeySecurity = rsa.CspKeyContainerInfo.CryptoKeySecurity }; cspParams.CryptoKeySecurity.AddAccessRule(new CryptoKeyAccessRule(sid, CryptoKeyRights.GenericRead, AccessControlType.Allow)); using (var rsa2 = new RSACryptoServiceProvider(cspParams)) { // Only created to persist the rule change in the CryptoKeySecurity } }
我正在使用SecurityIdentifier来识别帐户,但NTAccount也可以正常工作。
如果这有助于其他任何人,我在Powershell写了Jim Flood的答案
function Set-PrivateKeyPermissions { param( [Parameter(Mandatory=$true)][string]$thumbprint, [Parameter(Mandatory=$false)][string]$account = "NT AUTHORITY\NETWORK SERVICE" ) #Open Certificate store and locate certificate based on provided thumbprint $store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine") $store.Open("ReadWrite") $cert = $store.Certificates | where {$_.Thumbprint -eq $thumbprint} #Create new CSP object based on existing certificate provider and key name $csp = New-Object System.Security.Cryptography.CspParameters($cert.PrivateKey.CspKeyContainerInfo.ProviderType, $cert.PrivateKey.CspKeyContainerInfo.ProviderName, $cert.PrivateKey.CspKeyContainerInfo.KeyContainerName) # Set flags and key security based on existing cert $csp.Flags = "UseExistingKey","UseMachineKeyStore" $csp.CryptoKeySecurity = $cert.PrivateKey.CspKeyContainerInfo.CryptoKeySecurity $csp.KeyNumber = $cert.PrivateKey.CspKeyContainerInfo.KeyNumber # Create new access rule - could use parameters for permissions, but I only needed GenericRead $access = New-Object System.Security.AccessControl.CryptoKeyAccessRule($account,"GenericRead","Allow") # Add access rule to CSP object $csp.CryptoKeySecurity.AddAccessRule($access) #Create new CryptoServiceProvider object which updates Key with CSP information created/modified above $rsa2 = New-Object System.Security.Cryptography.RSACryptoServiceProvider($csp) #Close certificate store $store.Close() }
请注意,account参数也可以采用“DOMAIN \ USER”的forms(不仅仅是内置名称) – 我在我的环境中对此进行了测试,并自动将其转换为相应的SID
您可以使用作为Windows Server 2003 Resource Kit工具的一部分提供的WinHttpCertCfg.exe 工具 。
例:
winhttpcertcfg -g -c LOCAL_MACHINE\My -s test -a NetworkService
或者,您可以使用WCF SDK附带的“ 查找私钥”工具来查找证书私钥文件的磁盘位置。 然后,您只需使用ACL即可为文件设置正确的权限。
例:
FindPrivateKey My LocalMachine -n "CN=test"
这是我在Windows Server 2008上找到的解决方案,如果有人感兴趣的话: http : //technet.microsoft.com/en-us/library/ee662329.aspx
基本上,我必须使用MMC工具向需要访问证书的服务授予权限。 奇迹般有效。