2009-01-08 64 views
26

以下是将证书添加到Cert证书的代码。如何设置.NET的X.509证书的私钥文件的读取权限

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访问私钥的权限。

任何人都可以点亮一下吗?提前致谢。

回答

16

要做到这一点编程,你必须做三两件事:

  1. 获取私钥文件夹的路径。

  2. 获取该文件夹中私钥的文件名。

  3. 将权限添加到该文件。

用于执行所有3(具体地看一下“AddAccessToCertificate”方法)一些示例代码参见this post

+0

谢谢,我喜欢codeproject之一。 – 2009-01-12 09:54:19

+0

使用远程桌面时,您是否已经使用了该功能?当我访问它时,我可以看到关键字,但第二个程序完成后它会消失。 – 2013-06-25 21:22:25

11

您可以使用作为Windows Server 2003 Resource Kit Tools的一部分发货的WinHttpCertCfg.exe tool

例子:

winhttpcertcfg -g -c LOCAL_MACHINE\My -s test -a NetworkService 


或者,你可以使用Find Private Key tool附带的WCF SDK,找上了证书的私钥文件的磁盘上的位置。然后,您可以简单地使用ACL在文件上设置正确的权限。

例子:

FindPrivateKey My LocalMachine -n "CN=test" 
+0

谢谢,winhttpcertcfg是完成此任务的好方法。 – 2009-01-12 09:55:14

40

这个答案是晚了,但我想它张贴位置给其他人已来这里寻找:

我发现了使用CryptoKeySecurity here解决方案的MSDN博客文章,这里是一个解决方案的例子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也可以正常工作。

11

如果这可以帮助别人的时候,我写了吉姆洪水的回答在PowerShell中

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() 

} 

注意该帐户参数可以在“域\用户”,以及(不只是建在名称形式) - 我在我的环境中测试了它,并自动将它转换为相应的SID