Problemas con los certificados de X509Store. Busque FindByThumbprint

84

Tengo un problema cuando uso el método. 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();
    }
}

En este caso, el método Find devuelve 0 resultados ( results.Count == 0), pero si pongo findValue como constante, el método encuentra el certificado.

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
fuente

Respuestas:

135

Supongo que ha copiado y pegado la huella digital del cuadro de diálogo de información del certificado de Windows en su código (o en un archivo de configuración si este es un ejemplo simplificado). Es molesto que el primer carácter en el cuadro de texto de la huella digital es el carácter de control invisible Unicode "marca de izquierda a derecha" . Intente seleccionar la cita de la cadena de apertura y el primer carácter de la huella digital, elimínelos (lo que también eliminará el carácter invisible en el medio) y vuelva a escribirlos a mano.


Yo mismo fui sometido a este comportamiento extraño hoy, y me tomó más de una hora entenderlo. La forma finalmente vi que era utilizando el depurador para comprobar las longitudes y los códigos hash de findValuey de la Thumbprintdel objeto del certificado, que resultó ser diferente. Esto me llevó a inspeccionar las matrices de caracteres de esas cadenas en el depurador, donde apareció el carácter invisible.

Aasmund Eldhuset
fuente
4
Una forma más sencilla que volver a escribir es copiar la huella digital del cuadro de diálogo de la consola de administración de certificados y pegarla en un editor de texto (como Notepad ++), momento en el que el carácter Unicode invisible aparecerá como "?" o algún otro personaje obviamente extraño. Luego puede descartar ese carácter y copiar la cadena 'actualizada' a su código / config / textbox.
nateirvin
2
@nateirvin: Verdadero (mi sugerencia de volver a escribir a mano es un poco exagerada y se inspiró en lo frustrado que estaba en ese momento), o péguelo en el modo UTF-8 y active la visualización de caracteres ocultos (lo cual es aún más interesante porque te muestra exactamente qué personaje es).
Aasmund Eldhuset
1
@James Creo que se eliminará si también elimina las comillas circundantes (como escribí), pero de hecho, eliminar toda la línea definitivamente debería deshacerse de ella.
Aasmund Eldhuset
1
Error documentado aquí support.microsoft.com/en-us/kb/2023835 lección es no copiar y pegar desde MMC
Darryl Braaten
3
para el registro, la huella digital no distingue entre mayúsculas y minúsculas. también en VS2015 y el bloc de notas, pude presionar eliminar para eliminar el carácter invisible, y verificar que estaba allí en primer lugar con las teclas del cursor
Simon_Weaver
49

Tomé algunas de las respuestas aquí y las combiné en un método estático que se encarga de eliminar todos los caracteres especiales y mayúsculas. Ojalá alguien más pueda usarlo.

    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
fuente
2
Esto debería aceptarse como la respuesta. ¡¡Funciona perfectamente!!
Aster Veigas
6
Ese Regex.Replace debería ser "[^ \ da-fA-F]" - las huellas digitales son cadenas hexadecimales.
Ross Patterson
Gracias, Regex acaba de resolver el problema que tuve después de maldecir el código durante media hora.
Frans
Niza expresiones regulares para hacer frente a ese secreto oculto caracteres molestas vudú ...
granadaCoder
23

Tuve el mismo problema y lo resolví:

  1. Copié la huella digital de mmc directamente a VS. Comparé las cuerdas y no encontré ninguna diferencia.

  2. Al verificar la longitud con hash.length, hubo una diferencia, 41 frente a 40.

Se agrega un Char invisible a la cadena al copiarlo de mmc.


Resolviendo:

  1. copie la huella digital de mmc a Notepad.exe
  2. copia esta cadena de nuevo
  3. pegar en su código

Esta funcionando.

Thomas
fuente
10

Esto también me hizo tropezar, escribí esta función para limpiar la huella digital cuando se copiaba y pegaba desde 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
fuente
9

Fui víctima de esto. No solo había un carácter Unicode "de izquierda a derecha" en la pantalla de complemento de la consola de Windows de la huella digital, sino que también tenía caracteres hexadecimales en minúsculas, con espacios entre cada dos caracteres. La salida de CertUtil también tenía caracteres en minúscula y espacios. Para obtener una coincidencia, tuve que especificar findValue como una cadena que se ha transformado a

  1. Quite el carácter especial principal,
  2. Quite el espacio en blanco entre los grupos de caracteres,
  3. Cambie todos los caracteres a mayúsculas .
Greg
fuente
3

Este código debería funcionar.

Supongo que ha copiado esta huella digital de la consola de administración de certificados. Y ese valor copiado contiene un símbolo unicode no legible que es invisible en Visual Studio. Intente eliminar el primer símbolo invisible y si esto es lo que pienso, debería funcionar.

Dmitry Dyachkov
fuente
2

Me encontré con lo mismo. No pude encontrar esta respuesta en ningún lugar aquí, así que la publicaré. Me parece que la función de búsqueda de X509Store simplemente no funcionaba. Verifiqué esto con un simple bucle for y recuperando el certificado manualmente.

  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
fuente
1

Reemplace el código para encontrar su certificado en la tienda de la siguiente manera:

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

También el tercer parámetro que es bool devuelve certificados solo si el certificado es válido. Así que asegúrese de que su certificado sea válido. Si tiene un certificado autofirmado o algo así, simplemente pase el tercer parámetro para que sea "falso"

Rajesh
fuente
El certificado es válido, porque cuando una opción codifica el método devuelve 1 valor var results = store.Certificates.Find (findType, "7a6fa503ab57b81d6318a51ca265e739a51ce660", verdadero); //result.Count = 1 :)
nunofamel
¿Puede comprobar cuál es la identificación de la huella digital que se pasa en tiempo de ejecución al método?
Rajesh
es correcto, los puse en ventanas inmediatas, y tiene el mismo valor :(
nunofamel
¿Cambió la sintaxis a la que se muestra arriba en su código?
Rajesh
Ahora en inglés :) El código original en mi aplicación es como el anterior, fue solo un error de copiar + pegar :)
nunofamel
1

Aquí está la versión simple del código para las sugerencias anteriores, por supuesto que me funcionó

 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;
    }
Arrendajo
fuente
1

También encuentro este carácter invisible Unicode. Intentar usar el Bloc de notas (Windows 10) de alguna manera tampoco funcionó bien para mí. Finalmente, uso PowerShell para obtener la huella digital hexadecimal limpia:

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

Demasiado para char Unicode.

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

Creo que quiere decir que el segundo parámetro sea "findValue".

Joe
fuente
el segundo parámetro realmente es findValue,
nunofamel
Si ese es el caso, entonces el problema está en otra parte. Una cadena literal frente a un parámetro de variable de cadena no se romperá así a menos que el contenido real sea diferente (¿espacios en blanco? ¿Nueva línea final?)
Joe
0

Solo para que sepas cuál es el personaje invisible, veo que la huella digital en el mmc es: 75 3a ...

Luego lo copio y lo pego en mi vim, veo lo siguiente:

<200e> 75 3a ...

Entonces, después de deshacerse del primer carácter "<200e>" y los espacios adicionales, estará bien.

iefgnoix
fuente
0

+1 para la respuesta de Aasmund Eldhuset (y otras respuestas).

Es molesto que el primer carácter en el cuadro de texto de la huella digital es el carácter de control invisible Unicode "marca de izquierda a derecha".

Puede ser difícil verificar que esté presente. Por ejemplo, copiar la huella digital de mi archivo de configuración al editor binario VS a veces obtiene el carácter invisible y otras veces no.

Además, este código no mostró un problema. Revisé el código y pasé el mouse sobre x509Store para encontrar el certificado que quería.

                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
fuente
0

Después de un largo análisis, esto es lo que funcionó para mí.

  1. Copie la huella digital del certificado al bloc de notas.
  2. Copie la huella digital del bloc de notas a Visual Studio.
  3. Ejecute Visual Studio como administrador.

Esto funciona a las mil maravillas.

dedos10
fuente