2009-02-17 23 views
9

Tengo un servicio web ASP.NET que recibe una matriz de bytes que representa el contenido de un archivo .pfx que contiene un certificado X.509. El código del lado del servidor utiliza el constructor System.Security.Cryptography.X509Certificate2 para cargar el certificado de la bytes:¿Por qué X509Certificate2 a veces no se puede crear desde un blob?

X509Certificate2 native_cert = new X509Certificate2(
       pkcs12_buf /*byte array*/, 
       password, 
       X509KeyStorageFlags.PersistKeySet | 
       X509KeyStorageFlags.Exportable 
      ); 

Dependiendo de quién es mi proceso de servicio se está ejecutando como, esta llamada ya sea éxito o fallar con una excepción "error interno" . La última llamada en la pila de excepción es X509Utils._LoadCertFromBlob, que es código no administrado en mscore.dll.

Este código tiene éxito cuando se ejecuta desde una aplicación de consola en un inicio de sesión interactivo utilizando las credenciales de la cuenta de servicio. No funciona cuando se ejecuta en w3wp.exe en un grupo de aplicaciones que utiliza las credenciales de la cuenta de servicio. Cambiar la identidad del grupo de aplicaciones a un administrador soluciona el problema, por lo que debe ser un problema de privilegio, pero no tengo idea de qué privilegio podría ser necesario para esto. El código no toca ni el sistema de archivos ni los almacenes de certificados de Windows.

[ACTUALIZACIÓN: Más Información]
Este error aparece en el registro de sucesos de Windows:

*Cryptographic Parameters:* 
**Provider Name:** Microsoft Software Key Storage Provider 
**Algorithm Name:** Not Available. 
**Key Name:** {E182E13B-166D-472A-A24A-CBEF0808E9ED} 
    **Key Type:** User key. 

*Cryptographic Operation:* 
**Operation:** Open Key. 
    **Return Code:** 0x2 

¿Alguna idea?

Respuesta

8

solo he encontrado la solución a éste a mí mismo:

X509KeyStorageFlags flags = X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet; 

X509Certificate2 cert = new X509Certificate2(pkcs12_buf, password, flags); 

El truco aquí es utilizar el marcador de tienda de claves local MachineKeySet en lugar del almacén de claves de perfil de usuario, que es el valor predeterminado si no especifica una ubicación alternativa. Debido a que la identidad del proceso ASP.NET no carga el almacén de perfiles de usuario, no puede acceder a la tienda cuando importa un certificado mediante programación, pero puede acceder al almacén de máquinas.

Creo que PersistKeySet solo mantiene cargada la clave privada, pero no estoy seguro de lo que hace exactamente; aunque es necesario si necesita acceder a la clave privada por algún motivo.

+0

¿Por qué el contexto del usuario ASP.Net en el que se ejecuta no tiene acceso a su propia tienda? (Esto resolvió mi problema, era un clásico "¡pero funciona en mi máquina de desarrollo! Simplemente me interesa el razonamiento"). – DFTR

2

Trate concesión de los permisos de cuenta de ASP.NET a la siguiente carpeta: C:\Documents And Settings\All Users\Microsoft\Crypto\RSA\MachineKeys\ (puede variar según el entorno)

+0

Creo que estás en el camino correcto, pero parece que no intenta acceder al sistema de archivos. La cuenta que tiene éxito accede a Microsoft \ Crypto \ RSA bajo el perfil personal del usuario (no a AllUsers). El que falla ni siquiera está tratando de acceder al sistema de archivos, de acuerdo con procmon. – jlew

+0

Este cambio de permiso funcionó para mí en Win2k8. Me salvó un montón de depuración de tiempo. ¡Gracias! – CodingWithSpike

Cuestiones relacionadas