Comment la construction d’un X509Certificate2 à partir d’un tableau d’octets PKCS # 12 peut-elle générer une exception CryptographicException («Le système ne peut pas trouver le fichier spécifié.»)?

J’essaie de construire un X509Certificate2 partir d’un blob PKCS # 12 dans un tableau d’octets et d’obtenir une erreur plutôt déroutante. Ce code s’exécute dans une application de bureau avec des droits d’administrateur sur Windows XP.

La trace de la stack est la suivante, mais je me suis perdue en essayant de résoudre le problème, car _LoadCertFromBlob est marqué [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, Ssortingng password, X509KeyStorageFlags keyStorageFlags) 

EDIT: le blob est un véritable PKCS # 12 généré par BouncyCastle pour C # contenant une clé privée et un certificate RSA (auto-signé ou récemment inscrit à une autorité de certificateion). Ce que j’essaie de faire, c’est de convertir la clé privée et le certificate. de la bibliothèque BouncyCastle à la bibliothèque System.Security.Cryptography en les exportant et en les important. Ce code fonctionne sur la grande majorité des systèmes sur lesquels il a été testé. Je n’ai jamais vu cette erreur particulière émise par ce constructeur. Ce peut être une sorte de bizarrerie environnementale sur cette boîte.

EDIT 2: L’erreur se produit dans un environnement différent, dans une ville différente, et j’est incapable de la reproduire localement. Il est donc possible que je sois obligé de la relier à une installation XP défectueuse.

Depuis que vous avez demandé, cependant, voici le fragment en question. Le code prend une clé privée et un certificate dans la représentation BouncyCastle, supprime tous les certificates précédents du même nom distinctif du magasin de clés personnelles et importe la nouvelle clé privée et le nouveau certificate dans le magasin de clés personnelles via un blob intermédiaire 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() .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 certificatee var pkcs12store = new Pkcs12StoreBuilder().Build(); pkcs12store.SetKeyEntry(_Pkcs12KeyName, new AsymmesortingcKeyEntry(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(); 

Avez-vous le fichier PKCS # 12 ou juste le fichier PFX? Dans le monde Microsoft, c’est la même chose, mais d’autres en pensent une autre (voir http://www.drh-consultancy.demon.co.uk/pkcs12faq-old.html#PFX ).

Vous pouvez essayer juste de suivre

 X509Certificate2 cert = X509Certificate2(byte[] rawData, "password"); X509Certificate2 cert2 = X509Certificate2(byte[] rawData, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); 

(voir http://msdn.microsoft.com/en-us/library/ms148418.aspx ) ou

 X509Certificate2 cert = X509Certificate2("C:\Path\my.pfx", "password"); 

(voir http://msdn.microsoft.com/en-us/library/ms148420.aspx et http://msdn.microsoft.com/en-us/library/ms148442.aspx si vous avez besoin d’utiliser des drapeaux)

MISE À JOUR : Il serait utile d’insérer un fragment de code et pas seulement la trace de stack d’exceptions.

Quels X509KeyStorageFlags utilisez-vous? Vous pouvez utiliser Process Monitor pour savoir quel fichier n’a pas pu trouver le constructeur X509Certificate2 . Il se peut par exemple qu’il n’y ait pas de conteneur de clé par défaut pour l’utilisateur actuel sur Windows XP ayant le problème. Vous pouvez le créer et réessayer l’importation.

J’ai rencontré le même problème.

Selon cet article de kb, le problème était que le constructeur essayait de charger le certificate dans le profil de l’utilisateur actuel, mais que le code .Net empruntait l’identité de l’utilisateur et qu’il n’avait donc pas chargé le profil de l’utilisateur. Le constructeur nécessite que le profil utilisateur chargé fonctionne correctement.

De l’article:

Les constructeurs de classe X509Certificate2 tentent d’importer le certificate dans le profil utilisateur du compte d’utilisateur dans lequel l’application est exécutée. Souvent, les applications ASP.NET et COM + empruntent l’identité de clients. Lorsqu’ils le font, ils ne chargent pas les profils utilisateur de l’utilisateur emprunté par emprunt d’identité pour des raisons de performances. Ils ne peuvent donc pas accéder au magasin de certificates “Utilisateur” de l’utilisateur emprunté.

Le chargement du profil de l’utilisateur a corrigé l’erreur.

En cours d’exécution dans une application Web sous Windows 2012, la définition de l’option Load User Profile sur true du pool d’applications l’a fait fonctionner.

Pour ce faire, exécutez inetmgr.exe , accédez à Advanced Settings pour le pool d’applications inetmgr.exe , puis inetmgr.exe Load User Profile sous Process Model sur true.

J’ai eu le même problème.

  1. Ouvrez IIS sur le serveur hébergeant le site.
  2. Recherchez le pool d’applications du site.
  3. Cliquez sur Paramètres avancés.
  4. Changez “Load User Profile” en true. (peut nécessiter un redémarrage ou un redémarrage)

Cela permet au sous-système de cryptage de fonctionner.

entrez la description de l'image ici

J’ai eu exactement le même problème. Le même code et les mêmes données / certificates ont fonctionné correctement sous Windows 2003 x86 lors de l’exécution sous un utilisateur spécifique, mais ont échoué sous un autre compte (utilisé également pour l’exécution de pools d’applications IIS).

Apparemment, quelque chose d’autre a épuisé les ressources de Windows, de sorte que l’utilisateur défaillant ne pouvait pas vraiment charger le profil de l’utilisateur (son bureau était bizarre), bien qu’il n’y ait aucun événement lié dans Event Viewer .

Un redémarrage a résolu le problème temporairement. Bien qu’il ne s’agisse pas d’une solution permanente au problème, cela montre qu’il y a autre chose (par exemple, composants COM +, services de code natif, etc.) consommant des ressources qui doivent être examinées. Il montre également l’instabilité des plates-formes Windows …