Как установить разрешение на чтение для файла закрытого ключа сертификата X.509 из .NET

StackOverflow https://stackoverflow.com/questions/425688

  •  06-07-2019
  •  | 
  •  

Вопрос

Вот код для добавления pfx в хранилище сертификатов.

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

    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 {

    Если это кому-нибудь поможет, я написал ответ Джима Флуда в Powershell

    <*>

    Обратите внимание, что параметр учетной записи может иметь вид " DOMAIN \ USER " а также (не только встроенные имена) - я протестировал это в своей среде, и он автоматически преобразовал его в соответствующий SID

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

    Обратите внимание, что параметр учетной записи может иметь вид " DOMAIN \ USER " а также (не только встроенные имена) - я протестировал это в своей среде, и он автоматически преобразовал его в соответствующий SID

    Вы можете использовать WinHttpCertCfg.exe инструмент который поставляется как часть Инструменты Набора ресурсов Windows Server 2003.

    Пример:

    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. Работает как шарм.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top