2012-03-30 20 views
57
//cert is an EF Entity and 
// cert.CertificatePKCS12 is a byte[] with the certificate. 

var certificate = new X509Certificate(cert.CertificatePKCS12, "SomePassword"); 

Quando si carica un certificato dal nostro database, sul nostro server di gestione temporanea (Windows 2008 R2/IIS7.5) si ottiene questa eccezione:X509Certificate Constructor Eccezione

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) 

NOTA: Questo problema non lo fa si verificano localmente (Windows 7/Casini).

Qualsiasi intuizione è molto apprezzata.

+1

Ho lo stesso problema, per favore fatemi sapere se avete capito. –

+0

Controlla http://stackoverflow.com/questions/1345262/an-internal-error-occurred-when-loading-pfx-file-with-x509certificate2 e http://stackoverflow.com/questions/6097380/asp-net -mvc-an-internal-error-happened-when-load-certificate-bytes-with-x – alan

+1

Suppongo che l'origine del problema sia nel 'byte []' * data * che in 'cert.CertificatePKCS12'. Senza avere i dati si può solo intuire il motivo dell'eccezione "Si è verificato un errore interno". Quindi il mio suggerimento è di creare il certificato di test che può essere utilizzato nel proprio ambiente per riprodurre il problema, salvarlo nel file e fornire il link e la password (come "SomePassword") per la decodifica del certificato. Dopo aver esaminato * i dati * si avranno molte più possibilità di trovare il reson e di suggerire una soluzione del problema. – Oleg

risposta

104

Si è verificata un'impostazione nella configurazione del pool di applicazioni IIS (Pool di applicazioni> Impostazioni avanzate) per caricare il profilo utente per l'utente di identità del pool di applicazioni. Se impostato su false, i contenitori di chiavi non sono accessibili.

Quindi, solo impostare Load User Profile opzione come True

App Pool-> Advanced Settings Screen

+4

Wow. Grande scoperta! Fa schifo quando non è mai nemmeno un problema di codice, in primo luogo. Sono sorpreso che le cose chiave della macchina non abbiano funzionato. –

+0

Solo una nota che questo è per IIS7; in IIS6, non penso che ci sia un'opzione per caricare il profilo utente. –

+1

wow hai salvato la mia giornata! – TheVillageIdiot

49

Più che probabile, quando si esegue da Visual Studio/Cassini, accede all'archivio certificati utente dell'utente, anche se lo si sta caricando da byte. La prego di provare questo e vedere se si risolve il problema:

var certificate = new X509Certificate(
    cert.CertificatePKCS12, "SomePassword", X509KeyStorageFlags.MachineKeySet); 

Questo farà sì che IIS (che viene eseguito come l'utente ASP.NET che probabilmente non ha accesso a un archivio utenti) per utilizzare l'archivio macchina .

This page spiega il costruttore in modo più dettagliato e this page spiega l'enumerazione X509KeyStorageFlags.

Edit: Sulla base del second link da cyphr, sembra che potrebbe essere una buona idea (se la soluzione precedente non funziona), per combinare alcuni dei valori di enumerazione FlagsAttribute in questo modo:

var certificate = new X509Certificate(
    cert.CertificatePKCS12, "SomePassword", 
    X509KeyStorageFlags.MachineKeySet 
    | X509KeyStorageFlags.PersistKeySet 
    | X509KeyStorageFlags.Exportable); 

Inoltre, se si ha accesso, è possibile provare a modificare l'impostazione del pool di applicazioni per utilizzare LocalService (e quindi riavviare AppPool). Ciò può elevare le autorizzazioni a un livello appropriato se questo è il problema.

Infine, è possibile utilizzare File.WriteAllBytes per scrivere il contenuto di CertificatePKCS12 in un file pfx e vedere se è possibile importarlo manualmente utilizzando la console dei certificati in MMC (è possibile eliminare dopo l'importazione riuscita, questo è solo per testare). Potrebbe essere che i tuoi dati vengano riprodotti male o che la password non sia corretta.

+0

Grazie per la risposta, sebbene stia ancora lanciando la stessa eccezione dopo aver aggiunto solo il flag 'X509KeyStorageFlags.MachineKeySet', così come quando ha aggiunto tutti e tre i simboli' MachineKeySet', 'PersistKeySet' e' Esportabile'. – lukiffer

+1

È possibile modificare l'identità di AppPool in LocalService? –

+0

Inoltre, utilizzare ['File.WriteAllBytes'] (http://msdn.microsoft.com/en-us/library/system.io.file.writeallbytes.aspx) per scrivere il contenuto di' CertificatePKCS12' in un file pfx e vedere se è possibile importarlo manualmente utilizzando la console dei certificati in MMC (è possibile eliminare dopo l'importazione riuscita, questo è solo per testare). Potrebbe essere che i tuoi dati vengano riprodotti male o che la password non sia corretta. –

1

Per poter realmente risolvere il problema e non solo per indovinare, cosa può essere, è necessario essere in grado di riprodurre il problema . Se non puoi fornire un file PFX di prova che abbia lo stesso problema, devi esaminare tu stesso il problema. La prima domanda importante è: l'origine dell'eccezione "Si è verificato un errore interno" nella parte della chiave privata di PKCS12 o nella parte pubblica del certificato stesso?

Quindi ti consiglierei di provare a ripetere lo stesso esperimento con lo stesso certificato, esportato senza chiave (come file CER) privato:

var certificate = new X509Certificate(cert.CertificateCER); 

o

var certificate = new X509Certificate.CreateFromCertFile("My.cer"); 

E ' potrebbe aiutare a verificare se l'origine del problema è la chiave privata o alcune proprietà del certificato.

Se si riscontrano problemi con il file CER, è possibile pubblicare in sicurezza il collegamento al file perché contiene solo informazioni pubbliche.In alternativa si può almeno eseguire

CertUtil.exe -dump -v "My.cer" 

o

CertUtil.exe -dump -v -privatekey -p SomePassword "My.pfx" 

(è possibile utilizzare alcune altre opzioni troppo) e inviare alcune parti dell'uscita (ad esempio le proprietà della chiave privata senza la PRIVATEKEYBLOB si).

28

di questo codice:

certificate = new X509Certificate2(System.IO.File.ReadAllBytes(p12File) 
            , p12FilePassword 
            , X509KeyStorageFlags.MachineKeySet | 
            X509KeyStorageFlags.PersistKeySet | 
            X509KeyStorageFlags.Exportable); 
+6

+1 Questo ha funzionato per me .. Grazie! – hriziya

+1

Basta aggiungere l'ultimo bit con il 3 o le istruzioni per far funzionare le mie cose. Buon codice che è ancora rilevante. – Jobokai

+1

Ha funzionato per me quando provavo a caricare un certificato come risorsa incorporata su IIS. –

0

È necessario importare un certificato cer al vostro chiavi macchina locale. Non è necessario importare il tuo certificato .p12, ma usa il secondo certificato rilasciato dal tuo account da Apple. Penso che debba essere una coppia valida di certificati (uno nel filesystem, il secondo nel keystore). Dovrai impostare tutte e 3 le bandiere in DLL ovviamente.

3

Ho avuto problemi su Windows 2012 Server R2 dove la mia domanda non è riuscito a caricare i certificati per un PFX su disco. Le cose funzionerebbero bene eseguendo la mia app come amministratore, e l'eccezione ha detto Accesso negato quindi doveva essere un problema di autorizzazioni. Ho provato alcuni dei consigli sopra, ma ho ancora avuto il problema. Ho trovato che la specificazione dei seguenti flag come terzo parametro del costruttore cert ha fatto il trucco per me:

X509KeyStorageFlags.UserKeySet | 
X509KeyStorageFlags.PersistKeySet | 
X509KeyStorageFlags.Exportable