CryptographicException 'Keyset no existe', pero solo a través de WCF


157

Tengo un código que hace una llamada a un servicio web de terceros que está protegido con la certificación X.509.

Si llamo al código directamente (usando una prueba unitaria) funciona sin ningún problema.

Cuando se implementa, este código se llamará a través de un servicio WCF. He agregado una segunda prueba de unidad que llama al Servicio WCF, sin embargo, esto falla con un CryptographicExceptionmensaje "Keyset does not exist"cuando llamo a un método en el servicio web de terceros.

Supongo que esto se debe a que mi servicio WCF intentará llamar al servicio web de terceros utilizando un usuario diferente para mí.

¿Alguien puede arrojar alguna luz adicional sobre este tema?

Respuestas:


168

Probablemente será un problema de permisos en el certificado.

Al ejecutar una prueba unitaria, las ejecutará en su propio contexto de usuario, que (según la tienda en la que se encuentre el certificado del cliente ) tendrá acceso a la clave privada de ese certificado.

Sin embargo, si su servicio WCF está alojado en IIS, o como un Servicio de Windows, es probable que se ejecute con una cuenta de servicio (Servicio de red, Servicio local u otra cuenta restringida).

Deberá establecer los permisos apropiados en la clave privada para permitir que el servicio de la cuenta acceda a ella. MSDN tiene los detalles


Ejecutar calcs me ayudó por un problema completamente diferente, gracias
John

3
Ejecuto mi aplicación como administrador, el problema desapareció.
Derek

1
+1 para la documentación de MSDN y los pasos enumerados se aplican incluso a una aplicación web
Naren

Agregar "SERVICIO DE RED" a los permisos de seguridad del certificado resolvió esto por mí, ¡gracias!
OpMt

276

Esto es muy probable porque el usuario de IIS no tiene acceso a la clave privada para su certificado. Puede configurar esto siguiendo estos pasos ...

  1. Inicio -> Ejecutar -> MMC
  2. Archivo -> Agregar / Eliminar Snapin
  3. Agregue los complementos de certificados
  4. Seleccione Cuenta de computadora, luego presione Siguiente
  5. Seleccione Equipo local (predeterminado), luego haga clic en Finalizar
  6. En el panel izquierdo de Rooteo de consola, navegue hasta Certificados (computadora local) -> Personal -> Certificados
  7. Su certificado probablemente estará aquí.
  8. Haga clic derecho en su certificado -> Todas las tareas -> Administrar claves privadas
  9. Establezca su configuración de clave privada aquí.

1
Vale la pena señalar que esta no es una opción en Server 2003, a menos que mi entorno esté configurado como loco. Sin embargo, puedo hacer esto en Windows 7.
Shawn Hubbard

¿Qué quieres decir con establecer clave privada aquí? Me refiero a que solo puedes agregar al usuario con derecho de acceso.
mastervv

10
Gracias, solo quería señalar que si usa iis7.5 y el grupo de aplicaciones se ejecuta como applicationpoolidentity, tendrá que otorgar permisos de usuario IIS AppPool \ DefaultAppPool al archivo. Esto solucionó el problema para mí.
Ronen Festinger

25
Tuve que dar permiso a IIS_IUSRS para que funcione para mí.
TrueEddie

1
si recibe esto mientras ejecuta IIS express, debe otorgar sus propios permisos de inicio de sesión.
Jez

38

Tuve un problema idéntico anoche. Los permisos en la clave privada se configuraron correctamente, aparentemente todo estaba bien, excepto el error Keyset no existe. Al final resultó que el certificado se importó primero al almacén del usuario actual y luego se trasladó al almacén de máquinas local. Sin embargo, eso no movió la clave privada, que todavía estaba en el

C: \ Documents and settngs \ Administrator ...

en vez de

C: \ Documents and settngs \ Todos los usuarios ...

Aunque los permisos sobre la clave se configuraron correctamente, ASPNET no pudo acceder a ella. Cuando volvimos a importar el certificado para que la clave privada se coloque en la rama Todos los usuarios, el problema desapareció.


El mismo problema. Microsoft debe dejar de permitir que los bozos de seguridad ejecuten el asilo.
Paul Stovell

2
Después de 3 horas perdidas, esto resuelve mi problema. Gracias. He utilizado el FindPrivateKey muestra, y estaba confundido por lo que parecía ser en almacén de claves de mi usuario, incluso cuando apareció en LocalMachine a través del complemento MMC.
Rob Potter

Te compraría una cerveza por las horas desperdiciadas jugando con los permisos como cualquier otra respuesta me dijo.
Scott Scowden

¡Gracias, gracias, gracias! Perdí alrededor de 2.5 horas de mi vida gracias a este horrible problema y estoy seguro de que habría perdido 2.5 días si no hubiera visto esto.
Frank Tzanabetis

Tuve el mismo problema a la inversa. Primero instalado en la máquina local, luego en el usuario actual. La eliminación de todos los certificados de ambas tiendas y la reinstalación en el usuario actual lo repararon.
Bart Verkoeijen

24

Para resolver el "conjunto de claves no existe" al navegar desde IIS: puede ser por el permiso privado

Para ver y dar el permiso:

  1. Ejecutar> mmc> sí
  2. haga clic en el archivo
  3. Haga clic en Agregar / quitar complemento ...
  4. Haga doble clic en el certificado.
  5. Cuenta de computadora
  6. próximo
  7. Terminar
  8. Okay
  9. Haga clic en Certificados (computadora local)
  10. Haga clic en personal
  11. Haga clic en certificados

Para dar el permiso:

  1. Haga clic derecho en el nombre del certificado
  2. Todas las tareas> Administrar claves privadas ...
  3. Agregar y otorgar el privilegio (agregar IIS_IUSRS y otorgarle el privilegio funciona para mí)

1
Si está ejecutando bajo un grupo de aplicaciones, agregue este usuario en su lugar "IIS AppPool \ DefaultAppPool"
Sameer Alibhai

Esto también me ha ayudado. Tan pronto como le di a IIS_IUSRS los permisos, comenzó a funcionar.
Andrej Mohar

18

Tuve el mismo problema al intentar ejecutar la aplicación WCF desde Visual Studio. Lo resolvió ejecutando Visual Studio como administrador.


11

Me he enfrentado a este problema, mis certificados tenían clave privada pero recibía este error ( "El conjunto de claves no existe" )

Causa: su sitio web se ejecuta bajo la cuenta "Servicios de red" o tiene menos privilegios.

Solución : cambie la identidad del grupo de aplicaciones a "Sistema local", reinicie IIS y verifique nuevamente. Si comienza a funcionar es un problema de permiso / Menos privilegios, puede suplantar y luego usar otras cuentas también.


8

Totalmente frustrante, tuve el mismo problema y probé la mayoría de los anteriores. El certificado exportado correctamente tenía permisos para leer el archivo C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys, pero resulta que no tenía permiso en la carpeta. Lo agregó y funcionó


Intenté muchas cosas para resolver este problema, ¡pero este fue el truco!
Gyum Fox el

wow - NO esperaba que eso funcionara, pero lo hizo. Añadí IISAPPPool\www.mywebsite.comque es el nombre de usuario Windows para mi appool y funcionó :-)
Simon_Weaver

Alguien sabe por qué esto funciona? es algo corrupto porque esto es bastante oscuro
Simon_Weaver

¡No hagas esto! El servidor entra en el "mal estado" donde se importan los certificados y se muestra con el tipo de proveedor "Microsoft Software KSP" cuando la carpeta ..RSA \ MachineKeys tiene sus permisos básicos cambiados. Más detalles reddit.com/r/sysadmin/comments/339ogk/… .
Dhanuka777

3

Tengo exactamente un problema similar también. He usado el comando

findprivatekey root localmachine -n "CN="CertName" 

el resultado muestra que la clave privada está en la carpeta c: \ ProgramData en lugar de C: \ Documents and settngs \ All users ..

Cuando elimino la clave de la carpeta c: \ ProgramData, nuevamente ejecuto el comando findPrivatekey no funciona. es decir. No encuentra la llave.

Pero si busco la misma clave devuelta por un comando anterior, aún puedo encontrar la clave en

C: \ Documents and settngs \ Todos los usuarios.

Entonces, según tengo entendido, IIS o el WCF alojado no encuentra la clave privada de C: \ Documents and settngs \ All users ..


2
Hola, esta liga te dirá cómo resolver este problema y también localizar el findprivatekey herramienta: blogs.msdn.microsoft.com/dsnotes/2015/08/13/...
Tahir Khalid

3

Recibí el error: CryptographicException 'Keyset no existe' cuando ejecuto la aplicación MVC.

La solución fue: dar acceso a los certificados personales a la cuenta con la que se ejecuta el grupo de aplicaciones. En mi caso, fue agregar IIS_IUSRS y elegir la ubicación correcta resolvió este problema.

RC on the Certificate - > All tasks -> Manage Private Keys -> Add->  
For the From this location : Click on Locations and make sure to select the Server name. 
In the Enter the object names to select : IIS_IUSRS and click ok. 

2

La respuesta de Steve Sheldon me solucionó el problema, sin embargo, dado que estoy creando scripts de permisos de certificados sin una interfaz gráfica de usuario, necesitaba una solución con secuencias de comandos. Luché por encontrar dónde estaba almacenada mi clave privada. La clave privada no estaba dentro -C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys, eventualmente descubrí que realmente estaba dentro C:\ProgramData\Microsoft\Crypto\Keys. A continuación describo cómo lo descubrí:

Lo intenté FindPrivateKeypero no pude encontrar la clave privada, y usando powershell el$cert.privatekey.cspkeycontainerinfo.uniquekeycontainername estaba nulo / vacío.

Afortunadamente, certutil -store myenumeré el certificado y me dio los detalles que necesitaba para escribir la solución.

================ Certificate 1 ================ Serial Number: 162f1b54fe78c7c8fa9df09 Issuer: CN=*.internal.xxxxxxx.net NotBefore: 23/08/2019 14:04 NotAfter: 23/02/2020 14:24 Subject: CN=*.xxxxxxxnet Signature matches Public Key Root Certificate: Subject matches Issuer Cert Hash(sha1): xxxxa5f0e9f0ac8b7dd634xx Key Container = {407EC7EF-8701-42BF-993F-CDEF8328DD} Unique container name: 8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a ##* ^-- filename for private key*## Provider = Microsoft Software Key Storage Provider Private key is NOT plain text exportable Encryption test passed CertUtil: -store command completed successfully.

Luego escaneéc\ProgramData\Microsoft\Crypto\ la carpeta y encontré el archivo 8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a en C: \ ProgramData \ Microsoft \ Crypto \ Keys .

Darle a mi cuenta de servicio acceso de lectura a este archivo solucionó los problemas para mí


1
Usar "certutil -store my" fue la clave para resolver mi problema. Utilicé el "Nombre de contenedor único" para localizar el archivo y el Monitor de proceso Sysinternals para solucionar un error de "Acceso denegado" en el archivo del certificado. En mi caso, tuve que proporcionar acceso de lectura al archivo de certificado para el usuario NT Authority \ IUSR.
hsop

1

Encontré información faltante que me ayudó a obtener mi servicio WCF con seguridad de nivel de mensaje más allá del "conjunto de claves no existe" con el que me encontré a pesar de otorgar permisos a todas las claves generadas a partir de los ejemplos en Internet.

Finalmente importé la clave privada en la tienda de personas de confianza en la máquina local y luego le otorgué a la clave privada los permisos correctos.

Esto llenó los espacios en blanco para mí y finalmente me permitió implementar el servicio WCF con seguridad de nivel de mensaje. Estoy construyendo un WCF que debe cumplir con HIPPA.


1

Acabo de reinstalar mi certificado en la máquina local y luego funciona bien


0

Si utiliza ApplicationPoolIdentity para su grupo de aplicaciones, puede tener problemas para especificar el permiso para ese usuario "virtual" en el editor de registro (no existe dicho usuario en el sistema).

Por lo tanto, use subinacl : herramienta de línea de comandos que permite establecer ACL de registro, o algo así.


0

Solo quería agregar una respuesta de verificación de cordura. Recibía exactamente el mismo error incluso después de instalar los certificados en las tiendas correctas en mis máquinas y tener todos los privilegios de seguridad correctos para el cliente. Resulta que mezclé mi certificado de cliente y mi certificado de servicio. Si ha intentado todo lo anterior, volvería a verificar que tenga esos dos seguidos. Una vez que hice eso, mi aplicación llamó con éxito al servicio web. De nuevo, solo un corrector de cordura.


0

Recibió este error al usar el Fedlet de openAM en IIS7

Cambiar la cuenta de usuario para el sitio web predeterminado resolvió el problema. Lo ideal sería que se tratara de una cuenta de servicio. Quizás incluso la cuenta IUSR. Sugiera buscar métodos para el endurecimiento de IIS para clavarlo por completo.


0

Llegué a esto en mi proyecto de estructura de servicio después de que el certificado utilizado para autenticar contra nuestra bóveda de claves expiró y se rotó, lo que cambió la huella digital. Recibí este error porque me había perdido la actualización de la huella digital en el archivo applicationManifest.xml en este bloque que hace exactamente lo que otras respuestas han sugerido: a los permisos de SERVICIO DE RED (que todos mis ex ejecutan, configuración estándar para el clúster de tela azul de servicio) acceder a la ubicación de la tienda LOCALMACHINE \ MY cert.

Tenga en cuenta el valor del atributo "X509FindValue".

<!-- this block added to allow low priv processes (such as service fabric processes) that run as NETWORK SERVICE to read certificates from the store -->
  <Principals>
    <Users>
      <User Name="NetworkService" AccountType="NetworkService" />
    </Users>
  </Principals>
  <Policies>
    <SecurityAccessPolicies>
      <SecurityAccessPolicy ResourceRef="AzureKeyvaultClientCertificate" PrincipalRef="NetworkService" GrantRights="Full" ResourceType="Certificate" />
    </SecurityAccessPolicies>
  </Policies>
  <Certificates>
    <SecretsCertificate X509FindValue="[[THIS KEY ALSO NEEDS TO BE UPDATED]]" Name="AzureKeyvaultClientCertificate" />
  </Certificates>
  <!-- end block -->


0

Esta es la única solución que me funcionó.

    // creates the CspParameters object and sets the key container name used to store the RSA key pair
    CspParameters cp = new CspParameters();
    cp.KeyContainerName = "MyKeyContainerName"; //Eg: Friendly name

    // instantiates the rsa instance accessing the key container MyKeyContainerName
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);
    // add the below line to delete the key entry in MyKeyContainerName
    // rsa.PersistKeyInCsp = false;

    //writes out the current key pair used in the rsa instance
    Console.WriteLine("Key is : \n" + rsa.ToXmlString(true));

Referencia 1

Referencia 2


0
This issue is got resolved after adding network service role.

CERTIFICATE ISSUES 
Error :Keyset does not exist means System might not have access to private key
Error :Enveloped data  
Step 1:Install certificate in local machine not in current user store
Step 2:Run certificate manager
Step 3:Find your certificate in the local machine tab and right click manage privatekey and check in allowed personnel following have been added:
a>Administrators
b>yourself
c>'Network service'
And then provide respective permissions.

## You need to add 'Network Service' and then it will start working.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.