c# - read - ¿Cómo se puede construir un X509Certificate2 desde una matriz de bytes PKCS#12 lanzar CryptographicException("El sistema no puede encontrar el archivo especificado")?
x509certificate2 pfx (5)
X509Certificate2
construir un X509Certificate2
desde un blob PKCS # 12 en una matriz de bytes y obtener un error bastante desconcertante. Este código se ejecuta en una aplicación de escritorio con derechos de administrador en Windows XP.
El seguimiento de la pila es el siguiente, pero me perdí tratando de solucionarlo porque _LoadCertFromBlob
está marcado [MethodImpl(MethodImplOptions.InternalCall)]
.
System.Security.Cryptography.CryptographicException: The system cannot find the file specified.
at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx)
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags)
EDITAR: El blob es un PKCS # 12 verdadero generado por BouncyCastle para C # que contiene una clave privada RSA y un certificado (ya sea autofirmado o inscrito recientemente con una CA): lo que intento hacer es convertir la clave privada y el certificado de la biblioteca BouncyCastle a la biblioteca System.Security.Cryptography al exportar desde uno e importar al otro. Este código funciona en la gran mayoría de los sistemas en los que se ha probado; Nunca he visto ese error en particular arrojado por ese constructor. Puede ser algún tipo de rareza ambiental en esa única caja.
EDIT 2: El error se produce en un entorno diferente en una ciudad diferente, y no puedo reproducirlo localmente, por lo que puede terminar teniendo que atribuirlo a una instalación de XP rota.
Sin embargo, como usted pidió, aquí está el fragmento en cuestión. El código toma una clave privada y un certificado en representación de BouncyCastle, elimina los certificados previos para el mismo nombre distinguido del almacén de claves personales e importa la nueva clave privada y el certificado en el almacén de claves personales a través de un blob PKCS # 12 intermedio.
// open the personal keystore
var msMyStore = new X509Store(StoreName.My);
msMyStore.Open(OpenFlags.MaxAllowed);
// remove any certs previously issued for the same DN
var oldCerts =
msMyStore.Certificates.Cast<X509Certificate2>()
.Where(c => X509Name
.GetInstance(Asn1Object.FromByteArray(c.SubjectName.RawData))
.Equivalent(CurrentCertificate.SubjectDN))
.ToArray();
if (oldCerts.Length > 0) msMyStore.RemoveRange(new X509Certificate2Collection(oldCerts));
// build a PKCS#12 blob from the private key and certificate
var pkcs12store = new Pkcs12StoreBuilder().Build();
pkcs12store.SetKeyEntry(_Pkcs12KeyName,
new AsymmetricKeyEntry(KeyPair.Private),
new[] {new X509CertificateEntry(CurrentCertificate)});
var pkcs12data = new MemoryStream();
pkcs12store.Save(pkcs12data, _Pkcs12Password.ToCharArray(), Random);
// and import it. this constructor call blows up
_MyCertificate2 = new X509Certificate2(pkcs12data.ToArray(),
_Pkcs12Password,
X509KeyStorageFlags.Exportable);
msMyStore.Add(_MyCertificate2);
msMyStore.Close();
¿Tiene PKCS n. ° 12 o solo archivo PFX? En el mundo de Microsoft, es lo mismo, pero otros piensan en otro (ver http://www.drh-consultancy.demon.co.uk/pkcs12faq-old.html#PFX ).
Puedes intentar simplemente seguir
X509Certificate2 cert = X509Certificate2(byte[] rawData, "password");
X509Certificate2 cert2 = X509Certificate2(byte[] rawData, "password",
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable);
(vea http://msdn.microsoft.com/en-us/library/ms148418.aspx ) o
X509Certificate2 cert = X509Certificate2("C:/Path/my.pfx", "password");
(vea http://msdn.microsoft.com/en-us/library/ms148420.aspx y http://msdn.microsoft.com/en-us/library/ms148442.aspx si necesita usar algunas banderas)
ACTUALIZADO : Sería útil si inserta un fragmento de código y no solo el seguimiento de la pila de excepción.
¿Qué X509KeyStorageFlags
usas? Puede usar Process Monitor para descubrir qué archivo no pudo encontrar el constructor X509Certificate2
. Puede ser, por ejemplo, que no hay un contenedor de clave predeterminado para el usuario actual en Windows XP que tiene el problema. Puede crearlo y reintentar la importación.
Al ejecutar esto en una aplicación web en Windows 2012, establecer la opción del grupo de aplicaciones Load User Profile
en verdadero lo hizo funcionar.
Para hacerlo, ejecute inetmgr.exe
, vaya a Advanced Settings
para el grupo de aplicaciones correcto, cambie Load User Profile
en Process Model
a verdadero.
Me encontré con el mismo problema.
De acuerdo con este artículo de kb, el problema era que el constructor intenta cargar el certificado en el perfil del usuario actual, pero el código .Net estaba imitando al usuario y, por lo tanto, no había cargado el perfil del usuario. El constructor requiere que el perfil de usuario cargado funcione correctamente.
Del artículo:
Los constructores de clase X509Certificate2 intentan importar el certificado en el perfil de usuario de la cuenta de usuario en la que se ejecuta la aplicación. Muchas veces, las aplicaciones ASP.NET y COM + suplantan a los clientes. Cuando lo hacen, no cargan los perfiles de usuario para el usuario suplantado por motivos de rendimiento. Por lo tanto, no pueden acceder al almacén de certificados "Usuario" para el usuario suplantado.
La carga del perfil de usuario corrigió el error.
Tuve exactamente el mismo problema. El mismo código y los mismos datos / cert se ejecutaron correctamente en Windows 2003 x86 cuando se ejecutaban bajo un usuario específico, pero fallaban en otra cuenta (que también se usaba para ejecutar pools de aplicaciones IIS).
Aparentemente, otra cosa agotaba los recursos en Windows, de modo que el usuario que fallaba no podía realmente cargar el perfil del usuario (su escritorio era raro), aunque no había eventos relacionados en el Visor de eventos .
Un reinicio resolvió el problema temporalmente. Aunque esta no es una solución permanente al problema, muestra que hay algo más (por ejemplo, componentes COM +, servicios de código nativo, etc.) que consume recursos que deben investigarse. También muestra la inestabilidad de las plataformas de Windows ...
Yo tuve el mísmo problema.
- Abra IIS en el servidor que aloja el sitio.
- Encuentra el grupo de aplicaciones para el sitio.
- Haz clic en Configuración avanzada.
- Cambie "Cargar perfil de usuario" a verdadero. (puede requerir reiniciar o reiniciar)
Esto permite que el subsistema crypto funcione.