//cert is an EF Entity and
// cert.CertificatePKCS12 is a byte[] with the certificate.
var certificate = new X509Certificate(cert.CertificatePKCS12, "SomePassword");
Lors du chargement d'un certificat depuis notre base de données, nous obtenons cette exception sur notre serveur de transfert (Windows 2008 R2/IIS7.5):
System.Security.Cryptography.CryptographicException: An internal error occurred.
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(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)
REMARQUE: Ce problème ne se produit pas localement (Windows 7/Casini).
Tout conseil est grandement apprécié.
Il s'avère qu'il existe un paramètre dans la configuration du pool d'applications IIS (pools d'applications> Paramètres avancés) pour charger le profil utilisateur de l'utilisateur d'identité du pool d'applications. Lorsqu'il est défini sur false, les conteneurs de clés ne sont pas accessibles.
Il suffit donc de définir l’option Load User Profile
sur True
Plus que probablement, lorsque vous exécutez à partir de Visual Studio/Cassini, il accède à votre magasin de certificats user, même si vous le chargez à partir d'octets. Pourriez-vous s'il vous plaît essayer ceci et voir si cela résout votre problème:
var certificate = new X509Certificate(
cert.CertificatePKCS12, "SomePassword", X509KeyStorageFlags.MachineKeySet);
Cela entraînera IIS (qui s'exécute en tant qu'utilisateur ASP.Net n'ayant probablement pas accès à un magasin d'utilisateurs) d'utiliser le magasin Machine.
Cette page explique le constructeur plus en détail et cette page explique l'énumération X509KeyStorageFlags
.
Edit: Sur la base du second lien from cyphr , il semblerait que ce soit une bonne idée (si la solution précédente ne fonctionne pas) de combiner une partie du FlagsAttribute
énumération valeurs comme suit:
var certificate = new X509Certificate(
cert.CertificatePKCS12, "SomePassword",
X509KeyStorageFlags.MachineKeySet
| X509KeyStorageFlags.PersistKeySet
| X509KeyStorageFlags.Exportable);
En outre, si vous y avez accès, vous pouvez essayer de modifier votre paramètre de pool d'applications pour qu'il utilise LocalService (puis redémarrez le AppPool). Cela peut élever vos autorisations à un niveau approprié si tel est le problème.
Enfin, vous pouvez utiliser File.WriteAllBytes
pour écrire le contenu de CertificatePKCS12
dans un fichier pfx et voir si vous pouvez l’importer manuellement à l’aide de la console du certificat sous MMC (vous pouvez supprimer une importation réussie. tester). Il se peut que vos données soient en cours de constitution ou que le mot de passe soit incorrect.
Utilisez ce code:
certificate = new X509Certificate2(System.IO.File.ReadAllBytes(p12File)
, p12FilePassword
, X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable);
J'ai eu des problèmes sous Windows 2012 Server R2 où mon application n'a pas pu charger de certificat pour un PFX sur le disque. Les choses fonctionneraient bien si mon application était exécutée en tant qu'administrateur. L'exception mentionnée était Access Denied (accès refusé). Il devait donc s'agir d'un problème de permissions. J'ai essayé certains des conseils ci-dessus, mais j'avais toujours le problème. J'ai constaté que la spécification des indicateurs suivants en tant que troisième paramètre du constructeur de cert me convenait parfaitement:
X509KeyStorageFlags.UserKeySet |
X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable
Pour pouvoir vraiment résoudre votre problème et ne pas simplement deviner ce que cela peut être, il faut pouvoir reproduire votre problème Si vous ne pouvez pas fournir le fichier test PFX qui pose le même problème, vous devez l'examiner vous-même. La première question importante est de savoir si l'origine de l'exception "Une erreur interne s'est produite" se trouve-t-elle dans la partie clé privée du PKCS12 ou dans la partie publique du certificat?
Je vous recommande donc d'essayer de répéter la même expérience avec le même certificat, exporté sans clé privée (comme un fichier .CER):
var certificate = new X509Certificate(cert.CertificateCER);
ou
var certificate = new X509Certificate.CreateFromCertFile("My.cer");
Cela pourrait aider à vérifier si l'origine de votre problème est la clé privée ou certaines propriétés du certificat.
Si vous rencontrez des problèmes avec le fichier CER, vous pouvez poster en toute sécurité le lien vers le fichier car il ne contient que des informations publiques. Sinon, vous pouvez au moins exécuter
CertUtil.exe -dump -v "My.cer"
ou
CertUtil.exe -dump -v -privatekey -p SomePassword "My.pfx"
(vous pouvez également utiliser d'autres options) et publiez certaines parties de la sortie (par exemple, les propriétés de la clé privée sans le PRIVATEKEYBLOB lui-même).
Une alternative à la modification du profil utilisateur chargé consiste à obliger le pool d'applications à utiliser l'identité service réseau.
Voir aussi Que se passe-t-il exactement lorsque je configure LoadUserProfile du pool IIS?
Vous devez importer un certificat .cer dans le magasin de clés de votre ordinateur local. Il n'est pas nécessaire d'importer votre certificat .p12 - utilisez plutôt le deuxième certificat délivré par Apple à votre compte. Je pense que cela doit être une paire de certificats valides (un dans le système de fichiers, deuxième dans le magasin de clés). Vous devrez bien sûr définir les 3 drapeaux dans la DLL.