estoy tratando de construir un X509Certificate2
de una burbuja PKCS # 12 en una matriz de bytes y conseguir un error bastante desconcertante. Este código se ejecuta en una aplicación de escritorio con derechos de administrador en Windows XP.¿Cómo se puede construir un X509Certificate2 a partir de una matriz de bytes PKCS # 12 CryptographicException tirar ("el sistema no puede encontrar el archivo especificado.")?
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)
EDIT: La gota es una verdadera PKCS # 12 generada por BouncyCastle for C# que contiene una clave privada RSA y un certificado (ya sea auto-firmado o recientemente inscrito con un CA) - lo que estoy tratando de hacer es convertir la clave privada y el certificado de la biblioteca BouncyCastle a la biblioteca System.Security.Cryptography exportando de uno e importando 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 fallida.
Dado que usted pidió, sin embargo, aquí es el fragmento en cuestión. El código toma una clave privada y el certificado en representación BouncyCastle, se borran todos los certificados anteriores para el mismo nombre completo del almacén de claves personales, e importa la nueva clave privada y el certificado al almacén de claves personales a través de una mancha intermedia PKCS # 12.
// 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();
Adición X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable para el constructor al cargar desde byte [] funcionó para mí. – Muxa
Encontré este mismo error en Windows Server 2012, donde el mismo código no tenía problemas en Windows 7 o en la nube de Azure. Cambiar el indicador a MachineKeySet solucionó el problema. – RMD
Tenga cuidado con el indicador PersistKetSet en este ejemplo: deja archivos clave en el disco que nunca se limpian. Si realiza esta llamada con mucha frecuencia, terminará con una gran tarea de limpieza. (Pregúnteme cómo lo sé). Si está utilizando el certificado solo en la memoria, simplemente especifique MachineKeySet. Si ha terminado con el certificado en memoria en el código, llame al método Restablecer para eliminar inmediatamente el archivo de clave. Sin embargo, es mejor agregar una vez en la tienda y volver a cargar. Para eso es para eso. –