Probleme mit X509Store-Zertifikaten. FindByThumbprint finden


84

Ich habe ein Problem, wenn ich die Methode verwende 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();
    }
}

In diesem Fall gibt die Find-Methode 0 results ( results.Count == 0) zurück, aber wenn ich den findValue als konstant setze, findet die Methode das Zertifikat.

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();
    }
}

Antworten:


134

Ich nehme an, Sie haben den Fingerabdruck aus dem Dialogfeld mit den Windows-Zertifikatinformationen in Ihren Code kopiert (oder in eine Konfigurationsdatei, wenn dies ein vereinfachtes Beispiel ist). Ärgerlicherweise ist das erste Zeichen im Textfeld für den Fingerabdruck das unsichtbare Unicode-Steuerzeichen "Links-Rechts-Markierung" . Versuchen Sie, das Zitat der Eröffnungszeichenfolge und das erste Zeichen des Fingerabdrucks auszuwählen, sie zu löschen (wodurch auch das unsichtbare Zeichen dazwischen entfernt wird) und sie von Hand erneut einzugeben.


Ich war heute selbst diesem seltsamen Verhalten ausgesetzt, und ich brauchte über eine Stunde, um es herauszufinden. So sah ich es schließlich, indem ich mit dem Debugger die Längen und Hash-Codes von findValueund des ThumbprintZertifikatobjekts überprüfte , was sich als unterschiedlich herausstellte. Dies führte mich dazu, die Zeichenarrays dieser Zeichenfolgen im Debugger zu untersuchen, in denen das unsichtbare Zeichen angezeigt wurde.


4
Eine einfachere Möglichkeit als das erneute Eingeben besteht darin, den Fingerabdruck aus dem Dialogfeld der Zertifikatsverwaltungskonsole zu kopieren und in einen Texteditor (wie Notepad ++) einzufügen. An diesem Punkt wird das unsichtbare Unicode-Zeichen als "?" oder ein anderes offensichtlich seltsames Zeichen. Sie können dieses Zeichen dann nixen und die 'aktualisierte' Zeichenfolge in Ihren Code / config / textbox kopieren.
Nateirvin

2
@nateirvin: Richtig (mein Vorschlag, von Hand neu zu tippen, ist etwas übertrieben und wurde davon inspiriert, wie frustriert ich zu diesem Zeitpunkt war) - oder fügen Sie ihn im UTF-8-Modus ein und aktivieren Sie die Anzeige versteckter Zeichen (was noch interessanter ist) weil es dir genau zeigt, um welches Zeichen es sich handelt).
Aasmund Eldhuset

1
@ James Ich glaube, es wird gelöscht, wenn Sie auch die umgebenden Anführungszeichen löschen (wie ich geschrieben habe), aber in der Tat sollte das Löschen der gesamten Zeile es definitiv loswerden.
Aasmund Eldhuset

1
Fehler hier dokumentiert support.microsoft.com/en-us/kb/2023835 Lektion ist nicht kopieren und einfügen von MMC
Darryl Braaten

3
Bei der Aufzeichnung wird der Fingerabdruck nicht zwischen Groß- und Kleinschreibung unterschieden. Auch in VS2015 und im Editor konnte ich einfach auf Löschen
klicken

49

Ich habe einige der Antworten hier genommen und sie zu einer statischen Methode kombiniert, bei der Sonderzeichen und Großbuchstaben entfernt werden. Hoffentlich kann es jemand anderes benutzen.

    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
Dies sollte als Antwort akzeptiert werden. Funktioniert perfekt!!
Aster Veigas

6
Dieser Regex.Replace sollte "[^ \ da-fA-F]" sein - Fingerabdrücke sind hexadezimale Zeichenfolgen.
Ross Patterson

Vielen Dank, dass Regex gerade das Problem gelöst hat, das ich hatte, nachdem ich eine halbe Stunde lang auf Code geschworen hatte.
Frans

Netter Regex, um mit diesem nervigen Voodoo mit versteckten Charakteren
umzugehen

23

Ich hatte das gleiche Problem und löste es:

  1. Ich habe den Fingerabdruck von mmc direkt nach VS kopiert. Ich habe die Saiten verglichen und keinen Unterschied festgestellt.

  2. Bei der Überprüfung der Länge mit Hash-Länge ergab sich ein Unterschied zwischen 41 und 40.

Der Zeichenfolge wird ein unsichtbares Zeichen hinzugefügt, indem Sie es aus mmc kopieren.


Lösen:

  1. Kopieren Sie den Fingerabdruck von mmc nach Notepad.exe
  2. Kopieren Sie diese Zeichenfolge erneut
  3. in Ihren Code einfügen

Es funktioniert.


10

Das hat mich auch gestolpert. Ich habe diese Funktion geschrieben, um den Fingerabdruck beim Kopieren und Einfügen aus MMC zu bereinigen:

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

Ich bin diesem zum Opfer gefallen. In der Windows-Konsolen-Snap-In-Anzeige des Fingerabdrucks befand sich nicht nur ein Unicode-Zeichen "von links nach rechts", sondern auch Hex-Zeichen in Kleinbuchstaben mit Leerzeichen zwischen jeweils zwei Zeichen. Die Ausgabe von CertUtil hatte auch Kleinbuchstaben und Leerzeichen. Um eine Übereinstimmung zu erhalten, musste ich findValue als Zeichenfolge angeben, in die transformiert wurde

  1. Entfernen Sie das führende Sonderzeichen.
  2. Entfernen Sie das Leerzeichen zwischen Zeichenclustern.
  3. Ändern Sie alle Zeichen in Großbuchstaben .

3

Dieser Code sollte funktionieren.

Ich nehme an, Sie haben diesen Fingerabdruck von der Zertifikatsverwaltungskonsole kopiert. Und dieser kopierte Wert enthält ein nicht lesbares Unicode-Symbol, das in Visual Studio nicht sichtbar ist. Versuchen Sie, das erste unsichtbare Symbol zu löschen, und wenn ich daran denke, sollte dies funktionieren.


2

Ich bin auf dasselbe gestoßen. Ich konnte diese Antwort hier nirgendwo finden, also werde ich sie posten. Es scheint für mich, dass die X509Store-Suchfunktion einfach nicht funktioniert hat. Ich habe dies durch eine einfache for-Schleife überprüft und das Zertifikat manuell abgerufen.

  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

Ersetzen Sie den Code, um Ihr Zertifikat im Geschäft wie folgt zu finden:

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

Auch der 3. Parameter, der bool ist, gibt Zertifikate nur zurück, wenn das Zertifikat gültig ist. Stellen Sie also sicher, dass Ihr Zertifikat gültig ist. Wenn Sie ein selbstsigniertes Zertifikat haben, übergeben Sie einfach den 3. Parameter als "falsch".


Das Zertifikat ist gültig, da bei einem fest codierten Put die Methode 1 Wert zurückgibt. Var results = store.Certificates.Find (findType, "7a6fa503ab57b81d6318a51ca265e739a51ce660", true); //result.Count = 1 :)
Nunofamel

Können Sie überprüfen, welche Fingerabdruck-ID zur Laufzeit an die Methode übergeben wird?
Rajesh

ist richtig, ich habe sie auf Sofortfenster gesetzt, und er hat den gleichen Wert :(
Nunofamel

Haben Sie die Syntax in die oben in Ihrem Code gezeigte geändert?
Rajesh

1
O código original na minha aplicação é como o que está acima, foi apenas um erro de copy + past :)
nunofamel

1

Hier ist die einfache Version des Codes für die obigen Vorschläge - natürlich, die für mich funktioniert

 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

Ich stoße auch auf dieses unsichtbare Unicode-Zeichen. Der Versuch, Notepad (Windows 10) zu verwenden, funktionierte auch für mich nicht gut. Schließlich verwende ich PowerShell, um den sauberen Fingerabdruck zu erhalten:

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

Soviel zu Unicode char.


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

Ich denke du meinst den 2. Parameter "findValue".


Der 2. Parameter ist wirklich findValue,
nunofamel

Wenn dies der Fall ist, liegt das Problem woanders. Ein Literal-String im Vergleich zu einem String-Variablen-Parameter wird nicht so unterbrochen, es sei denn, der tatsächliche Inhalt ist anders (Leerzeichen? Nachgestellte Zeilenumbruch?)
Joe

0

Um Sie wissen zu lassen, was das unsichtbare Zeichen ist, sehe ich den Fingerabdruck im mmc wie folgt: 75 3a ...

Dann kopiere ich es und füge es in mein vim ein. Ich sehe Folgendes:

<200e> 75 3a ...

Nachdem Sie das erste Zeichen "<200e>" und die zusätzlichen Leerzeichen entfernt haben, ist alles in Ordnung.


0

+1 für die Antwort von Aasmund Eldhuset (und andere Antworten).

Ärgerlicherweise ist das erste Zeichen im Textfeld für den Fingerabdruck das unsichtbare Unicode-Steuerzeichen "Links-Rechts-Markierung".

Es kann schwierig sein, zu überprüfen, ob es vorhanden ist. Wenn Sie beispielsweise den Fingerabdruck aus meiner Konfigurationsdatei in den VS-Binäreditor kopieren, wird manchmal das unsichtbare Zeichen angezeigt, manchmal nicht.

Auch dieser Code zeigte kein Problem. Ich ging den Code durch und fuhr mit der Maus über den x509Store, um das gewünschte Zertifikat zu finden.

                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

Nach langer Analyse hat Folgendes für mich funktioniert.

  1. Kopieren Sie den Daumenabdruck vom Zertifikat auf den Notizblock.
  2. Kopieren Sie den Daumenabdruck vom Notizblock in das Visual Studio.
  3. Führen Sie Visual Studio als Administrator aus.

Das funktioniert wie ein Zauber.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.