Problemy z certyfikatami X509Store.Find FindByThumbprint


84

Mam problem, kiedy używam tej metody X509Store.Certificates.Find

public static X509Certificate2 FromStore(StoreName storeName, 
          StoreLocation storeLocation, X509FindType findType, string findValue)
{
    X509Store store = new X509Store(storeName, storeLocation);
    store.Open(OpenFlags.ReadOnly);
    try
    {
        //findValue = "7a6fa503ab57b81d6318a51ca265e739a51ce660"
        var results = store.Certificates.Find(findType, findValue, true);

        return results[0];                
    }
    finally
    {
        store.Close();
    }
}

W tym przypadku metoda Find zwraca 0 wyników ( results.Count == 0), ale jeśli ustawię findValue jako stałą, metoda znajdzie certyfikat.

public static X509Certificate2 FromStore(StoreName storeName, 
           StoreLocation storeLocation, X509FindType findType, string findValue)
{
    X509Store store = new X509Store(storeName, storeLocation);
    store.Open(OpenFlags.ReadOnly);
    try
    {         
        //findValue= "7a6fa503ab57b81d6318a51ca265e739a51ce660"
        var results = store.Certificates.Find(findType, 
                              "7a6fa503ab57b81d6318a51ca265e739a51ce660", true);
        return results[0];
    }
    finally
    {
        store.Close();
    }
}

Odpowiedzi:


135

Przypuszczam, że skopiowałeś i wkleiłeś odcisk palca z okna dialogowego informacji o certyfikacie systemu Windows do swojego kodu (lub do pliku konfiguracyjnego, jeśli jest to uproszczony przykład). Irytująco, pierwszy znak w polu tekstowym odcisku palca to niewidoczny znak kontrolny Unicode „znak od lewej do prawej” . Spróbuj wybrać otwierający cytat w postaci ciągu znaków i pierwszy znak odcisku palca, usuwając je (co również usunie niewidoczny znak znajdujący się pomiędzy) i przepisz je ręcznie.


Sam byłem dzisiaj poddany temu dziwnemu zachowaniu i zajęło mi ponad godzinę, zanim to rozgryzłem. Sposób, w jaki w końcu to zobaczyłem, polegał na użyciu debugera do sprawdzenia długości i kodów skrótu findValuei Thumbprintobiektu certyfikatu, który okazał się inny. Doprowadziło mnie to do sprawdzenia tablic znaków tych ciągów w debugerze, gdzie pojawił się niewidoczny znak.


4
Łatwiejszym sposobem niż ponowne wpisywanie jest skopiowanie odcisku palca z okna dialogowego konsoli zarządzania certyfikatami i wklejenie go do edytora tekstu (takiego jak Notepad ++), w którym to momencie niewidoczny znak Unicode pojawi się jako „?” lub jakaś inna wyraźnie dziwna postać. Następnie możesz usunąć ten znak i skopiować „zaktualizowany” ciąg do swojego kodu / config / textbox.
nateirvin,

2
@nateirvin: Prawda (moja sugestia, aby przepisać ręcznie to trochę przesada i zainspirowała mnie to, jak bardzo byłem sfrustrowany) - lub wklej go w trybie UTF-8 i włącz wyświetlanie ukrytych postaci (co jest jeszcze bardziej interesujące ponieważ pokazuje dokładnie, jaki to znak).
Aasmund Eldhuset

1
@James Wierzę, że zostanie usunięty, jeśli usuniesz również otaczające cudzysłowy (jak napisałem), ale rzeczywiście, usunięcie całej linii powinno zdecydowanie się go pozbyć.
Aasmund Eldhuset

1
Błąd udokumentowany tutaj support.microsoft.com/en-us/kb/2023835 lekcja nie kopiuj i wklejaj z MMC
Darryl Braaten,

3
dla protokołu odcisk palca nie rozróżnia wielkości liter. również w VS2015 i notatniku udało mi się po prostu nacisnąć przycisk delete, aby usunąć niewidzialną postać - i sprawdzić, czy był tam w pierwszej kolejności za pomocą klawiszy kursora
Simon_Weaver

49

Wziąłem tutaj niektóre odpowiedzi i połączyłem je w statyczną metodę, która zajmuje się usuwaniem znaków specjalnych i wielkich liter. Miejmy nadzieję, że ktoś inny może go użyć.

    public static X509Certificate2 GetCertificate(string thumbprint)
    {
        // strip any non-hexadecimal values and make uppercase
        thumbprint = Regex.Replace(thumbprint, @"[^\da-fA-F]", string.Empty).ToUpper();
        var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

        try
        {
            store.Open(OpenFlags.ReadOnly);

            var certCollection = store.Certificates;
            var signingCert = certCollection.Find(X509FindType.FindByThumbprint, thumbprint, false);
            if (signingCert.Count == 0)
            {
                throw new FileNotFoundException(string.Format("Cert with thumbprint: '{0}' not found in local machine cert store.", thumbprint));
            }

            return signingCert[0];
        }
        finally
        {
            store.Close();
        }
    }

2
Należy to przyjąć jako odpowiedź. Działa świetnie!!
Aster Veigas

6
Regex.Replace powinno mieć wartość „[^ \ da-fA-F]” - odciski palców to ciągi szesnastkowe.
Ross Patterson

Dzięki, że Regex właśnie rozwiązał problem, który miałem po półgodzinnym przeklinaniu kodu.
Frans,

Niezłe wyrażenie regularne do radzenia sobie z tym irytującym voodoo z ukrytymi postaciami ...
granadaCoder

23

Miałem ten sam problem i rozwiązałem go:

  1. Skopiowałem odcisk palca z mmc bezpośrednio do VS. Porównałem struny i nie znalazłem żadnej różnicy.

  2. Sprawdzając długość z hash.length, była różnica 41 w porównaniu z 40.

Istnieje niewidoczny znak Char dodawany do ciągu przez skopiowanie go z mmc.


Rozwiązywanie:

  1. skopiuj odcisk palca z mmc do Notepad.exe
  2. skopiuj ten ciąg ponownie
  3. wklej do swojego kodu

To działa.


10

To też mnie zaskoczyło, napisałem tę funkcję, aby wyczyścić odcisk palca po skopiowaniu i wklejeniu z MMC:

public string CleanThumbprint(string mmcThumbprint)
    {
        //replace spaces, non word chars and convert to uppercase
        return Regex.Replace(mmcThumbprint, @"\s|\W", "").ToUpper();
    }

...
        var myThumbprint = CleanThumbprint("‎b3 ab 84 e5 1e e5 e4 75 e7 a5 3e 27 8c 87 9d 2f 05 02 27 56");
        var myCertificate = certificates.Find(X509FindType.FindByThumbprint, myThumbprint, true)[0];

9

Padłem tego ofiarą. Nie tylko znajdował się znak Unicode „od lewej do prawej” na wyświetlaniu odcisku palca w konsoli systemu Windows, ale także zawierał małe litery szesnastkowe ze spacjami między każdymi dwoma znakami. Dane wyjściowe CertUtil zawierały również małe litery i spacje. Aby uzyskać dopasowanie, musiałem określić findValue jako ciąg, który został przekształcony do

  1. Usuń wiodący znak specjalny,
  2. Usuń spacje między grupami znaków,
  3. Zmień wszystkie znaki na wielkie litery .

3

Ten kod powinien działać.

Przypuszczam, że skopiowałeś ten odcisk palca z konsoli zarządzania certyfikatami. A ta skopiowana wartość zawiera nieczytelny symbol Unicode, który jest niewidoczny w programie Visual Studio. Spróbuj usunąć pierwszy niewidoczny symbol i jeśli o tym myślę, to powinno działać.


2

Wpadłem na to samo. Nigdzie nie mogłem znaleźć tej odpowiedzi, więc ją opublikuję. Wydaje mi się, że funkcja wyszukiwania X509Store po prostu nie działała. Sprawdziłem to, wykonując prostą pętlę for i ręcznie pobierając certyfikat.

  X509Store store = new X509Store(StoreName.Root,StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        X509Certificate cert = new X509Certificate();
        for (int i = 0; i < store.Certificates.Count; i++)
        {
            if (store.Certificates[i].SerialNumber == "XXXX")
            {
                cert = store.Certificates[i];
            }
        }

1

Zastąp kod, aby znaleźć swój certyfikat w sklepie, jak poniżej:

var results = store.Certificates.Find(findType, findValue, true); 

Również trzeci parametr, którym są certyfikaty zwrotu bool tylko wtedy, gdy certyfikat jest ważny. Dlatego upewnij się, że Twój certyfikat jest ważny. Jeśli masz certyfikat z podpisem własnym, po prostu przekaż trzeci parametr, aby był „fałszywy”


Certyfikat jest ważny, ponieważ gdy metoda put zakodowana na stałe, metoda zwraca 1 wartość var ​​results = store.Certificates.Find (findType, "7a6fa503ab57b81d6318a51ca265e739a51ce660", true); //result.Count = 1 :)
nunofamel

Czy możesz sprawdzić, jaki identyfikator odcisku palca jest przekazywany w czasie wykonywania do metody?
Rajesh,

ma rację, umieściłem je na oknach Imediate i ma tę samą wartość :(
nunofamel

Czy zmieniłeś składnię na taką, jak pokazano powyżej w swoim kodzie?
Rajesh

Teraz w języku angielskim :) Oryginalny kod w mojej aplikacji jest taki jak powyżej, to był tylko błąd kopiuj + wklej :)
nunofamel

1

Oto prosta wersja kodu dla powyższych sugestii - oczywiście, która działa dla mnie

 private X509Certificate2 GetCertificate()
    {
        var certStore = new X509Store("my");
        certStore.Open(OpenFlags.ReadOnly);
        try
        {
            const string thumbprint = "18 33 fe 3a 67 d1 9e 0d f6 1e e5 d5 58 aa 8a 97 8c c4 d8 c3";
            var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint,
            Regex.Replace(thumbprint, @"\s+", "").ToUpper(), false);
            if (certCollection.Count > 0)
                return certCollection[0];
        }
        finally
        {
            certStore.Close();
        }
        return null;
    }

1

Napotykam również ten niewidoczny znak Unicode. Próba korzystania z Notatnika (Windows 10) też nie działała dobrze. Na koniec używam PowerShell, aby uzyskać czysty odciski palców:

PS C:\> $tp= (Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -match "mycert"}).Thumbprint;
PS C:\> $tp

Tyle dla znaków Unicode.


0
var results = store.Certificates.Find(findType, findType, true);

Myślę, że masz na myśli, że drugim parametrem jest „findValue”.


2. parametr to tak naprawdę findValue,
nunofamel

Jeśli tak jest, problem tkwi gdzie indziej. Dosłowny ciąg a parametr zmiennej łańcuchowej nie zepsuje się w ten sposób, chyba że rzeczywista zawartość jest inna (białe znaki? Końcowa nowa linia?)
Joe

0

Żeby ci powiedzieć, czym jest niewidzialna postać, widzę odcisk kciuka w mmc: 75 3a ...

Następnie kopiuję i wklejam go w swoim vimie, widzę:

<200e> 75 3a ...

Więc po pozbyciu się pierwszego znaku „<200e>” i dodatkowych spacji wszystko będzie dobrze.


0

+1 za odpowiedź Aasmunda Eldhuseta (i inne odpowiedzi).

Irytująco, pierwszy znak w polu tekstowym odcisku palca to niewidoczny znak kontrolny Unicode „znak od lewej do prawej”.

Sprawdzenie, czy jest obecny, może być trudne. Na przykład skopiowanie odcisku palca z mojego pliku konfiguracyjnego do edytora binarnego VS czasami powoduje uzyskanie niewidocznego znaku, a czasami nie.

Również ten kod nie pokazał problemu. Przeszedłem przez kod i najechałem myszką na x509Store, aby znaleźć certyfikat, którego szukałem.

                X509Certificate2 cert2 = null;
                string storeName = StoreName.My.ToString();
                var x509Store = new X509Store(storeName, StoreLocation.LocalMachine);
                x509Store.Open(OpenFlags.ReadOnly);

                var cert3 = x509Store.Certificates[4];
                var thumbprint3 = cert3.Thumbprint;
                int gotIt = thumbprint3.CompareTo(clientCert);

0

Po długiej analizie, oto co zadziałało dla mnie.

  1. Skopiuj odcisk kciuka z certyfikatu do notatnika.
  2. Skopiuj odcisk kciuka z notatnika do programu Visual Studio.
  3. Uruchom Visual Studio jako administrator.

To działa jak urok.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.