2015-02-27 49 views
7

Wobec naprawdę dziwnego problemu X509Certificate2.Verify() zwraca false dla ważnego certyfikatu. Być może niektórzy już wcześniej mieli do czynienia z tym dziwnym scenariuszem i mogą oświetlić go nieco.X509Certificate2.Verify() zwraca false zawsze

Używam openssl do generowania certyfikatów klienta do celów testowych. Tworzę główny urząd certyfikacji i generuję certyfikat klienta na podstawie głównego urzędu certyfikacji i dodam główny urząd certyfikacji do jego łańcucha.

Załaduję główny urząd certyfikacji i certyfikat klienta do lokalnego magazynu certyfikatów i wydaje się, że jest w porządku, ale kiedy ładuję go z mojego kodu NUnit, aby przetestować X509Certificate2.Verify() zawsze zwraca wartość false.

enter image description here

Oto kod, aby załadować Cert ze sklepu:

 X509Store store = new X509Store(StoreName.My); 
     string thumbprint = "60 d1 38 95 ee 3a 73 1e 7e 0d 70 68 0f 2d d0 69 1e 9a eb 72"; 
     store.Open(OpenFlags.ReadOnly); 
     var mCert = store.Certificates.Find(
           X509FindType.FindByThumbprint, 
           thumbprint, 
           true 
          ).OfType<System.Security.Cryptography.X509Certificates.X509Certificate>().FirstOrDefault(); 
     if(mCert != null) 
     { 
      var testClientCert = new X509Certificate2(mCert); 
     } 

Oto Client Cert które właśnie generowane: (URL CRL jest dostępna z moim komputerze lokalnym poprawnie)

-----BEGIN CERTIFICATE----- 
MIIC7jCCAlegAwIBAgIBATANBgkqhkiG9w0BAQUFADBtMR0wGwYDVQQKExRWaXRh 
bEhlYWx0aCBTb2Z0d2FyZTElMCMGA1UECxMcVml0YWxIZWFsdGggU29mdHdhcmUg 
Um9vdCBDQTElMCMGA1UEAxMcVml0YWxIZWFsdGggU29mdHdhcmUgUm9vdCBDQTAe 
Fw0xNTAyMjcwODQ2MzNaFw0xNjAyMjcwODQ2MzNaMEUxHTAbBgNVBAoTFFZpdGFs 
SGVhbHRoIFNvZnR3YXJlMREwDwYDVQQLEwhQbGF0Zm9ybTERMA8GA1UEAxMIVGVz 
dFVzZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOkfyjX0PSnRYrBbCC8u 
rw7IiFdAUj6frPKEmt0TLAR/4g+NazKdGjRRqxE9mNwX/2zGhIcucfGDVwPtOtiV 
opicQEzGiSQkvAc+473MN5D6j3XtBYblALMeMyEYoh3LnHO4K+6kV6XE4BXV/2lV 
mAVgXGkZzaayd40DLvg48vPlAgMBAAGjgcUwgcIwCQYDVR0TBAIwADARBglghkgB 
hvhCAQEEBAMCB4AwCwYDVR0PBAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMDEG 
CWCGSAGG+EIBDQQkFiJPcGVuU1NMIENlcnRpZmljYXRlIGZvciBTU0wgQ2xpZW50 
ME0GA1UdHwRGMEQwQqBAoD6GPGh0dHA6Ly9wbGF0Zm9ybWRhc2hib2FyZC5ubC52 
aXRhbGhlYWx0aC5sb2NhbC9wb3J0YWwvY3JsLmNybDANBgkqhkiG9w0BAQUFAAOB 
gQBXYSmZaVu6vnyl94SO4qpNOutsUm4p7fQHehljhZ+aRrXE10rivWCt4g0k961E 
PDsp4J0DR6uth6et42pBp8v2gFIGSQY/F7NhmOAsOJvM7z0oIBxMLcclIDTygbRp 
KjZZpNjvf+YJasbidosiL4VSeRiCZ+HPzvKDb3wNeafoZA== 
-----END CERTIFICATE----- 

A oto plik CRL, który dostaje do pobrania, kiedy do niego dostęp z poziomu przeglądarki:

-----BEGIN X509 CRL----- 
MIIBMjCBnDANBgkqhkiG9w0BAQUFADBtMR0wGwYDVQQKExRWaXRhbEhlYWx0aCBT 
b2Z0d2FyZTElMCMGA1UECxMcVml0YWxIZWFsdGggU29mdHdhcmUgUm9vdCBDQTEl 
MCMGA1UEAxMcVml0YWxIZWFsdGggU29mdHdhcmUgUm9vdCBDQRcNMTQwODA3MTQz 
OTIyWhcNMTQwOTA2MTQzOTIyWjANBgkqhkiG9w0BAQUFAAOBgQA8MSxAorbxpdDm 
1IA2Aqjb/OkZydua1Tm5k5KtHknI4zyYPZb3GzO0eRygpKBSAqtYkxDI6eCv6xgf 
+anXT56md+cPGZ+2YvSicxqwP2GL2kymc9mVMTiQieioS1/7apjCIjZEgWxqf3Up 
zvy/kNQRg3lII8hYu0idGs9byKZJFQ== 
-----END X509 CRL----- 
+0

Istnieje kilka pytań odnośnie tego, jak ten: http://stackoverflow.com/questions/1277791/x509certificate2-validation-on-web- service Czy wypróbowałeś któryś z nich jeszcze? – weston

+0

@weston Tak, rzeczywiście. Sprawdziłem poniższy link, który wydaje się być podobny do mojego, http://stackoverflow.com/questions/10137208/x509certificate2-verify-method-always-return-false-for-the-valid-certyfikat?rq=1 ale mogę uzyskać dostęp do URL CRL w moim kliencie po prostu dobrze z przeglądarki i używam testów Nunits, które działają pod lokalnym kontem użytkownika Windows, które użyłem do zainstalowania Cert i jego RootCA do bieżącego magazynu Cert dla tego użytkownika Windows . – Deb

+0

, wyeksportuj ten certyfikat do pliku i pokaż nam wynik polecenia certutil: 'certutil -verify -urlfetch \ file.cer'. – Crypt32

Odpowiedz

13

Zgodnie z dokumentacją X509Certificate2.Verify

Metoda ta tworzy prosty łańcuch do certyfikatu i stosuje politykę bazową do tego łańcucha. Jeśli potrzebujesz więcej informacji o niepowodzeniu, sprawdź certyfikat bezpośrednio za pomocą obiektu X509Chain.

Dlatego chciałbym spróbować zbudować łańcuch przy użyciu tego kodu (zastąpić metodę Log z własnej realizacji, byłem przy użyciu Console.WriteLine)

X509Chain chain = new X509Chain(); 

try 
{ 
    var chainBuilt = chain.Build(testClientCert); 
    Log(string.Format("Chain building status: {0}", chainBuilt)); 

    if (chainBuilt == false) 
     foreach (X509ChainStatus chainStatus in chain.ChainStatus) 
      Log(string.Format("Chain error: {0} {1}", chainStatus.Status, chainStatus.StatusInformation)); 
} 
catch (Exception ex) 
{ 
    Log(ex.ToString()); 
} 

Ten kod powie dlaczego certyfikat może nie można zweryfikować. Jeśli trzeba dostosować politykę łańcucha następnie ustawić chain.ChainPolicy własności tj

chain.ChainPolicy = new X509ChainPolicy() 
{ 
    RevocationMode = X509RevocationMode.NoCheck, 
    VerificationFlags = X509VerificationFlags.IgnoreNotTimeValid, 
    UrlRetrievalTimeout = new TimeSpan(0, 1, 0) 
}; 
+0

Tak, prawda. Ale najpierw chcę po prostu wykonać podstawowe sprawdzenie, czy certyfikat jest ważny, a następnie przejść do sprawdzania całego łańcucha.Nie chcę tracić czasu na sprawdzanie całego łańcucha (który przy okazji może być bardzo duży w moim przypadku) zanim podstawowa weryfikacja przejdzie na certyfikat, który moim zdaniem jest dość prosty i prawidłowy. – Deb

+1

Ten kod pomógł mi dowiedzieć się, dlaczego funkcja Verify() zwracała wartość false. Metoda chainStatus.StatusInformation zwróciła następujące informacje: "Funkcja odwołania nie mogła sprawdzić odwołania certyfikatu." W twoim przypadku stan może być inny, ale uważam, że powyższy kod jest przydatny podczas rozwiązywania problemów. – user3308241

+1

@Deb Verify buduje cały łańcuch, ale go wyrzuca. Możesz równie dobrze zbudować go samodzielnie (pod warunkiem, że go wyrzucisz (4.6) lub zadzwonisz na Reset (inne) po zakończeniu). – bartonjs