Problèmes avec les certificats X509Store.Find FindByThumbprint


84

J'ai un problème lorsque j'utilise la méthode 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();
    }
}

Dans ce cas, la méthode de recherche renvoie 0 résultats ( results.Count == 0), mais si je mets la valeur de recherche comme constante, la méthode trouve le certificat.

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

Réponses:


135

Je suppose que vous avez copié-collé l'empreinte numérique de la boîte de dialogue des informations de certificat Windows dans votre code (ou dans un fichier de configuration s'il s'agit d'un exemple simplifié). Malheureusement, le premier caractère de la zone de texte de l'empreinte numérique est le caractère de contrôle invisible Unicode "marque de gauche à droite" . Essayez de sélectionner la chaîne d'ouverture et le premier caractère de l'empreinte numérique, supprimez-les (ce qui éliminera également le caractère invisible entre les deux) et retapez-les à la main.


J'ai moi-même été soumis à ce comportement étrange aujourd'hui, et il m'a fallu plus d'une heure pour le comprendre. La façon dont je l'ai finalement vu a été d'utiliser le débogueur pour vérifier les longueurs et les codes de hachage de findValueet de l' Thumbprintobjet de certificat, ce qui s'est avéré être différent. Cela m'a conduit à inspecter les tableaux de caractères de ces chaînes dans le débogueur, où le caractère invisible est apparu.


4
Un moyen plus simple que de retaper est de copier l'empreinte numérique de la boîte de dialogue de la console de gestion des certificats et de la coller dans un éditeur de texte (comme Notepad ++), à quel point le caractère Unicode invisible apparaîtra sous la forme d'un "?" ou un autre personnage évidemment étrange. Vous pouvez ensuite supprimer ce caractère et copier la chaîne «mise à jour» dans votre code / config / zone de texte.
nateirvin

2
@nateirvin: Vrai (ma suggestion de retaper à la main est un peu exagérée, et a été inspirée par ma frustration à ce moment-là) - ou collez-la en mode UTF-8 et activez l'affichage des caractères cachés (ce qui est encore plus intéressant car il vous montre exactement de quel personnage il s'agit).
Aasmund Eldhuset

1
@James Je crois que cela sera supprimé si vous supprimez également les citations environnantes (comme je l'ai écrit), mais en effet, la suppression de la ligne entière devrait certainement s'en débarrasser.
Aasmund Eldhuset

1
Bogue documenté ici support.microsoft.com/en-us/kb/2023835 la leçon ne consiste pas à copier et coller à partir de MMC
Darryl Braaten

3
pour l'enregistrement, l'empreinte numérique est insensible à la casse. également dans VS2015 et le bloc-notes, j'ai pu simplement appuyer sur Supprimer pour supprimer le caractère invisible - et vérifier qu'il était là en premier lieu avec les touches du curseur
Simon_Weaver

49

J'ai pris certaines des réponses ici et les ai combinées dans une méthode statique qui prend soin de supprimer tout les caractères spéciaux et les majuscules. J'espère que quelqu'un d'autre pourra l'utiliser.

    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
Cela devrait être accepté comme la réponse. Fonctionne parfaitement!!
Aster Veigas

6
Ce Regex.Replace doit être "[^ \ da-fA-F]" - les empreintes sont des chaînes hexadécimales.
Ross Patterson

Merci, que Regex vient de résoudre le problème que j'avais après avoir juré au code pendant une demi-heure.
Frans

Belle regex pour faire face à ce vaudou ennuyeux de personnages secrets cachés ...
GrenadeCoder

23

J'ai eu le même problème et je l'ai résolu:

  1. J'ai copié l'empreinte digitale de mmc directement vers VS. J'ai comparé les cordes et je n'ai trouvé aucune différence.

  2. En vérifiant la longueur avec hash.length, il y avait une différence, 41 contre 40.

Un caractère invisible est ajouté à la chaîne en le copiant hors de mmc.


Résolution:

  1. copier l'empreinte digitale de mmc vers Notepad.exe
  2. recopiez cette chaîne
  3. coller à votre code

Ça marche.


10

Cela m'a fait trébucher aussi, j'ai écrit cette fonction pour nettoyer l'empreinte numérique lorsqu'elle est copiée et collée à partir de 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

J'en ai été victime. Non seulement il y avait un caractère Unicode "de gauche à droite" dans l'affichage du composant logiciel enfichable de la console Windows de l'empreinte numérique, mais il avait également des caractères hexadécimaux minuscules, avec des espaces entre tous les deux caractères. La sortie de CertUtil contenait également des caractères minuscules et des espaces. Pour obtenir une correspondance, j'ai dû spécifier la findValue comme une chaîne qui a été transformée en

  1. Supprimez le premier caractère spécial,
  2. Supprimez les espaces entre les groupes de caractères,
  3. Changez tous les caractères en majuscules .

3

Ce code devrait fonctionner.

Je suppose que vous avez copié cette empreinte numérique à partir de la console de gestion des certificats. Et cette valeur copiée contient un symbole non lisible Unicode qui est invisible dans Visual Studio. Essayez de supprimer le premier symbole invisible et si c'est ce à quoi je pense, cela devrait fonctionner.


2

J'ai rencontré la même chose. Je n'ai trouvé cette réponse nulle part ici, alors je la posterai. Il me semble que la fonction de recherche X509Store ne fonctionnait tout simplement pas. J'ai vérifié cela par une simple boucle for et en récupérant le certificat manuellement.

  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

Remplacez le code pour trouver votre certificat dans le magasin comme ci-dessous:

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

Aussi le 3ème paramètre qui est bool ne renvoie les certificats que si le certificat est valide. Assurez-vous donc que votre certificat est valide. Si vous avez un certificat auto-signé ou plus, passez simplement le 3ème paramètre pour être "faux"


Le certificat est valide, car quand une méthode codée en dur renvoie 1 valeur var results = store.Certificates.Find (findType, "7a6fa503ab57b81d6318a51ca265e739a51ce660", true); //result.Count = 1 :)
nunofamel

Pouvez-vous vérifier quel est l'ID de l'empreinte numérique qui est transmis à l'exécution à la méthode?
Rajesh

est correct je les mets sur des fenêtres immédiates, et il a la même valeur :(
nunofamel

Avez-vous changé la syntaxe pour celle indiquée ci-dessus dans votre code?
Rajesh

Maintenant en anglais :) Le code original dans mon application est comme ci-dessus, c'était juste une erreur de copier-coller :)
nunofamel

1

Voici la version simple du code pour les suggestions ci-dessus - bien sûr, qui fonctionne pour moi

 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

Je rencontre également ce caractère Unicode invisible. Essayer d'utiliser Notepad (Windows 10) ne fonctionnait pas non plus pour moi. Enfin, j'utilise PowerShell pour obtenir l'hexagone propre de l'empreinte numérique:

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

TELLEMENT pour le caractère Unicode.


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

Je pense que vous voulez dire que le 2ème paramètre est "findValue".


le 2ème paramètre est vraiment findValue,
nunofamel

Si tel est le cas, le problème est ailleurs. Une chaîne littérale par rapport à un paramètre de variable de chaîne ne se cassera pas comme ça à moins que le contenu réel ne soit différent (espace blanc? Retour à la ligne de fin?)
Joe

0

Juste pour vous faire savoir ce qu'est le caractère invisible, je vois l'empreinte du pouce dans le mmc être: 75 3a ...

Ensuite, je le copie et le colle dans mon vim, je vois ce qui suit:

<200e> 75 3a ...

Donc, après vous être débarrassé du premier caractère "<200e>" et des espaces supplémentaires, tout ira bien.


0

+1 pour la réponse d'Aasmund Eldhuset (et autres réponses).

Malheureusement, le premier caractère de la zone de texte de l'empreinte numérique est le caractère de contrôle invisible Unicode "marque de gauche à droite".

Il peut être difficile de vérifier sa présence. Par exemple, la copie de l'empreinte numérique de mon fichier de configuration vers l'éditeur binaire VS obtient parfois le caractère invisible et parfois non.

De plus, ce code n'a pas montré de problème. J'ai parcouru le code et passé la souris sur le x509Store pour trouver le certificat que je voulais.

                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

Après une longue analyse, voici ce qui a fonctionné pour moi.

  1. Copiez l'empreinte numérique du certificat dans le bloc-notes.
  2. Copiez l'empreinte du pouce du bloc-notes dans Visual Studio.
  3. Exécutez Visual Studio en tant qu'administrateur.

Cela fonctionne comme un charme.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.