Cómo configurar el permiso de lectura en el archivo de clave privada del certificado X.509 de .NET

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

  •  06-07-2019
  •  | 
  •  

Pregunta

Aquí está el código para agregar un pfx a la tienda 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();

Sin embargo, no pude encontrar una manera de establecer el permiso para que NetworkService acceda a la clave privada.

¿Alguien puede arrojar algo de luz? Gracias de antemano.

¿Fue útil?

Solución

Para hacerlo mediante programación, debe hacer tres cosas:

  1. Obtenga la ruta de la carpeta de clave privada.

  2. Obtenga el nombre del archivo de la clave privada dentro de esa carpeta.

  3. Agregue el permiso a ese archivo.

Consulte esta publicación para obtener un código de ejemplo que los tres (específicamente mira el método "AddAccessToCertificate").

Otros consejos

Esta respuesta llega tarde pero quería publicarla para cualquier otra persona que venga a buscar aquí:

Encontré un artículo de blog de MSDN que daba una solución usando CryptoKeySecurity aquí , y aquí hay un ejemplo de una solución en 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
    }
}

Estoy usando un SecurityIdentifier para identificar la cuenta, pero una NTAccount funcionaría igual de bien.

En caso de que esto ayude a alguien más, escribí la respuesta de Jim Flood en 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 {

En caso de que esto ayude a alguien más, escribí la respuesta de Jim Flood en Powershell

<*>

Tenga en cuenta que el parámetro de la cuenta puede tener la forma de " DOMAIN \ USER " también (no solo nombres incorporados): probé esto en mi entorno y lo convirtió automáticamente al SID apropiado

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

Tenga en cuenta que el parámetro de la cuenta puede tener la forma de " DOMAIN \ USER " también (no solo nombres incorporados): probé esto en mi entorno y lo convirtió automáticamente al SID apropiado

Puede usar la herramienta WinHttpCertCfg.exe que se envía como parte de las Herramientas del kit de recursos de Windows Server 2003 .

Ejemplo:

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


Alternativamente, puede usar la herramienta Find Private Key que se envía con WCF SDK, para buscar la ubicación en el disco del archivo de clave privada del certificado. Luego, simplemente puede usar ACL para establecer los privilegios correctos en el archivo.

Ejemplo:

FindPrivateKey My LocalMachine -n "CN=test"

Esta es la solución que encontré para Windows Server 2008 si alguien estaba interesado: http : //technet.microsoft.com/en-us/library/ee662329.aspx

Básicamente, tuve que otorgar permisos al servicio que necesita acceder al certificado utilizando la herramienta MMC. Funciona como un encanto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top