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();
    }
}
nunofamel
źródło

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.

Aasmund Eldhuset
źródło
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();
        }
    }
jhilden
źródło
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.

Tomasz
źródło
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];
Rob C
źródło
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 .
Greg
źródło
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ć.

Dmitry Dyachkov
źródło
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];
            }
        }
vikingben
źródło
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”

Rajesh
źródło
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;
    }
Sójka
źródło
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.

Riza Marhaban
źródło
0
var results = store.Certificates.Find(findType, findType, true);

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

Joe
źródło
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.

iefgnoix
źródło
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);
mmesser314
źródło
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.

palce 10
źródło