代码之家  ›  专栏  ›  技术社区  ›  Ray Lu

如何从.NET设置X.509证书的私钥文件的读取权限

  •  27
  • Ray Lu  · 技术社区  · 16 年前

    X509Store store = new X509Store( StoreName.My, StoreLocation.LocalMachine );
    store.Open( OpenFlags.ReadWrite );
    X509Certificate2 cert = new X509Certificate2( "test.pfx", "password" );
    store.Add( cert );
    store.Close();
    

    有人能解释一下吗?提前谢谢。

    5 回复  |  直到 16 年前
        1
  •  44
  •   Jim Flood    14 年前

    这个答案已经很晚了,但我想把它发布给其他来这里搜索的人:

    我发现了一篇MSDN博客文章,其中给出了使用CryptoKeySecurity的解决方案 here

    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
        }
    }
    

        2
  •  18
  •   Russ    9 年前

    为了防止这对其他人有所帮助,我在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”的形式(不仅仅是内置名称)——我在我的环境中测试了这个参数,它自动将其转换为适当的SID

        3
  •  17
  •   Eric Rosenberger    16 年前

    要以编程方式执行此操作,您必须做三件事:

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

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

    3. 向该文件添加权限。

    看见 this post

        4
  •  11
  •   Enrico Campidoglio    16 年前

    你可以使用 WinHttpCertCfg.exe tool Windows Server 2003 Resource Kit Tools .

    例子:

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


    Find Private Key tool


    FindPrivateKey My LocalMachine -n "CN=test"
    
        5
  •  3
  •   S.L. Barth is on codidact.com Monika Restecka    12 年前

    如果有人感兴趣,这就是我为windows server 2008找到的解决方案: http://technet.microsoft.com/en-us/library/ee662329.aspx

        6
  •  3
  •   eddiewould    5 年前

    根据@russ的回答,

    function Set-PrivateKeyPermissions {
        param(
            [Parameter(Mandatory=$true)]
            [string]$thumbprint,
            [Parameter(Mandatory=$true)]
            [string]$account
        )
    
        #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}
    
        if ($cert.PrivateKey -Eq $null) {
            # Probably using Key Storage Provider rather than crypto service provider
            $rsaCert = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
            if ($rsaCert -Eq $null) {
                throw "Private key on certificate $($cert.Subject) not available"
            }
    
            $fileName = $rsaCert.key.UniqueName
            $path = "$env:ALLUSERSPROFILE\Microsoft\Crypto\Keys\$fileName"
            $permissions = Get-Acl -Path $path
    
            $access_rule = New-Object System.Security.AccessControl.FileSystemAccessRule($account, "FullControl", "Allow")
            $permissions.AddAccessRule($access_rule)
            Set-Acl -Path $path -AclObject $permissions
        } else {
            #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()
    }