"Wystąpił błąd wewnętrzny." podczas ładowania pliku pfx z X509Certificate2

79

Próbuję użyć certyfikatu z podpisem własnym (C #):

X509Certificate2 cert = new X509Certificate2(
    Server.MapPath("~/App_Data/myhost.pfx"), "pass");

na udostępnionym serwerze hostingowym i wyskoczył mi błąd:

System.Security.Cryptography.CryptographicException: An internal error occurred.

ślad stosu kończy się na

System.Security.Cryptography.CryptographicException.
    ThrowCryptogaphicException(Int32 hr) +33
System.Security.Cryptography.X509Certificates.X509Utils.
    _LoadCertFromFile(String fileName, IntPtr password, UInt32 dwFlags, 
        Boolean persistKeySet, SafeCertContextHandle& pCertCtx) +0
System.Security.Cryptography.X509Certificates.X509Certificate.
    LoadCertificateFromFile(String fileName, Object password, 
        X509KeyStorageFlags keyStorageFlags) +237
System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(
    String fileName, String password) +131

Na mojej maszynie deweloperskiej ładuje się dobrze. Powód, dla którego ładuję * .pfx, a nie plik * .cer, ponieważ potrzebuję dostępu do klucza prywatnego (plik cer ładuje się OK). Zrobiłem PFX na mojej Dev Mochine w ten sposób:

makecert -r -n "CN=myhost.com, [email protected]" -sky exchange -b 01/01/2009
    -pe -sv myhost.pvk myhost.cer
<b>pvk2pfx</b> -pvk myhost.pvk -spc myhost.cer -pfx myhost.pfx -po pass</code>

Używam wersji v5.131.3790.0 programu makecert

casperOne
źródło
Być może ten artykuł pomoże: codeproject.com/KB/WCF/wcfcertificates.aspx
Emmanuel
Otrzymałem komunikat o błędzie the system cannot find the file specified. Odpowiedź @Randy Levy zadziałała dla mnie!
Jess

Odpowiedzi:

145

Użyj lokalnego magazynu komputera dla klucza prywatnego:

X509Certificate2 cert = new X509Certificate2("myhost.pfx", "pass",
    X509KeyStorageFlags.MachineKeySet);

MachineKeySetjest opisana jako „klucze prywatne są przechowywane w lokalnym magazynie komputera, a nie w bieżącym magazynie użytkownika”. Domyślnie bez flag jest umieszczana w magazynie użytkowników.

Mimo że odczytujesz certyfikat z dysku i przechowujesz go w obiekcie, klucze prywatne są nadal przechowywane w bazie danych kluczy Microsoft Cryptographic API Cryptographic Service Provider. Na serwerze hostującym proces ASP.NET nie ma uprawnień dostępu do magazynu użytkowników.

Innym podejściem (zgodnie z niektórymi komentarzami poniżej) jest zmodyfikowanie tożsamości konfiguracji usług IIS lub puli aplikacji - które działają. Jednak zakłada się, że istnieje dostęp do tych elementów konfiguracji, co może nie mieć miejsca (np. We współdzielonym środowisku hostingu).

Randy wspiera Monikę
źródło
3
tak, to pomaga, dzięki. czy mógłbyś wyjaśnić dlaczego? docs nie mówi nic pomocnego.
2
Uratowałeś mój dzień. Co dziwne, działało na moim komputerze przed aktualizacją rozwiązania do .NET 4.0
Marc Climent
1
Rzeczywiście, wszystko co trzeba było zrobić to ustawić parametr X509KeyStorageFlags.MachineKeySet. To naprawdę smutne, że zgłoszony wyjątek po prostu stwierdza: „Wystąpił błąd wewnętrzny”. Niezbyt pomocne.
Nicholi,
2
Możesz również dodać więcej uprawnień do klucza prywatnego do konta przypisanego do puli aplikacji. Lub zmień tożsamość puli aplikacji na „Usługa lokalna”.
guzart
1
A dla szybszej naprawy / obejścia problemu: stackoverflow.com/questions/9951729/…
Ciprian Teiosanu
13

Wypróbowałem rozwiązanie Randy'ego polegające na zmianie go na MachineKeySet, ale wtedy otrzymałem komunikat o błędzie:

„klucz nie może być używany w określonym stanie”

Więc po krótkim googlowaniu znalazłem post, który sugerował zmianę go na:

var certificate = new X509Certificate2(certKeyFilePath, passCode, 
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet |       
X509KeyStorageFlags.PersistKeySet );

i to rozwiązało moje problemy.

Nie wypróbowałem jeszcze sugestii zmiany ustawienia puli aplikacji w konfiguracji usług IIS. Aby to zrobić, przejdź do ustawień zaawansowanych puli aplikacji w Twojej witrynie, a następnie ustaw „load user profile” na true. Gdy to ustawienie ma wartość false, kontenery kluczy są pozornie niedostępne.

Myke Black
źródło
Otrzymałem wyżej wymieniony błąd, a Twoje rozwiązanie pomogło go rozwiązać. Dziękuję Ci.
dotcoder
Nie lubię komentarzy, które nie pomagają (jak ten), ale powiem ci, że oszczędzasz mi dzień. Dzięki!
rasputino