Pregunta

Estoy tratando de validar un certificado X.509 usando C # y .NetCF. Tengo el certificado de CA, y si he entendido bien, necesito usar la clave pública de este certificado de CA para descifrar la firma del certificado no es de confianza. Esto me debe dar el valor hash calculado del certificado no es de confianza. Debería entonces calcular el hash del certificado de mí mismo y asegurarse de que los dos valores coinciden.

He estado jugando con esto durante unos días y ahora no recibo muy lejos. He estado usando las clases X509Certificate y RSACryptoServiceProvider. En primer lugar, he tratado de obtener la clave pública y la firma de la clase X509Certificate. Yo era capaz de obtener la clave pública, pero no la firma. A continuación, he intentado analizar los datos binarios que componen el certificado, lo que me permitió obtener la firma (y cualquier otro dato que quería), pero fue incapaz de descifrar la firma utilizando la RSACryptoServiceProvider. He intentado cosas como esta, pero cuidado para conseguir excepciones diciendo "Bad clave" cuando trataba de descifrar:

RSAParameters rsaParams = new RSAParameters();
rsaParams.Exponent = exp;
rsaParams.Modulus = mod;
RSACryptoServiceProvider rsaServ = new RSACryptoServiceProvider();
rsaServ.ImportParameters(rsaParams);
byte[] decryptedSig = rsaServ.Decrypt(encryptedSig, false);

Cualquier consejo sería muy apreciada.

Editar: Probé algo que parece ser mejor, pero se vuelve un resultado extraño. Estoy trabajando con la clase X509Certificate2 aquí porque es un poco más fácil para probar, pero necesitaré para cambiar a X509Certificate para .NetCF más tarde. Creo que RSACryptoServiceProvider.VerifyData podría ser lo que necesito. He probado el siguiente código.

X509Certificate2 cert = new X509Certificate2(certBytes);
X509Certificate2 certCA1 = new X509Certificate2(@"C:\certs\certCA1.cer");

byte[] encryptedSig = new byte[256];
Array.Copy(certBytes, certBytes.Length - 256, encryptedSig, 0, 256);

RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certA1.PublicKey.Key;
bool good = rsa.VerifyData(cert.RawData, "1.3.14.3.2.26", encryptedSig);

Como ya he dicho, soy capaz de decodificar de forma manual e interpretar los datos binarios del certificado, así que estoy bastante seguro de que el cert.RawData es datos firmados del certificado y los últimos 256 bytes son la firma cifrada. La cadena es el OID del algoritmo de hash, que obtuve de certificado, pero no estoy 100% seguro de que es correcta. Verifydata devuelve falso, pero no estoy seguro de por qué todavía.

Los pensamientos?

¿Fue útil?

Solución

Aquí está mi código.

RSACryptoServiceProvider rsa = signingCertificate_GetPublicKey();
return rsa.VerifyData( SignedValue(), CryptoConfig.MapNameToOID( "SHA1" ), Signature() );

RSACryptoServiceProvider signingCertificate_GetPublicKey()
{
    RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();

    RSAParameters publicKeyParams = new RSAParameters();
    publicKeyParams.Modulus = GetPublicKeyModulus();
    publicKeyParams.Exponent = GetPublicKeyExponent();

    publicKey.ImportParameters( publicKeyParams );

    return publicKey;
}

byte[] GetPublicKeyExponent()
{
    // The value of the second TLV in your Public Key
}

byte[] GetPublicKeyModulus()
{
    // The value of the first TLV in your Public Key
}

byte[] SignedValue()
{
    // The first TLV in your Ceritificate
}

byte[] Signature()
{
    // The value of the third TLV in your Certificate
}

Espero que ayuda a cualquier persona que está trabajando en este problema.

Otros consejos

¿El apoyo WinCE algo compatible con el Win32 MSCrypto.dll? Si es así, miren el .NET clase X509Certificate2 y también la biblioteca CLR Seguridad en CodePlex. contiene una gran cantidad de rutinas útiles para NET que se sientan en la parte superior de la biblioteca del sistema operativo central de cifrado. Puede descargar el código fuente y ver cómo se compila para .NetCF

Para cargar y validar un certificado X509, hacer algo como esto (no probado):

var cert = new X509Certificate2("mycert.cer");  
if (!cert.Verify())
{
    <fail>
}

Hay cerca de una docena de constructores para X509Certificate2 para la construcción de una amplia variedad de fuentes -. Archivo en el disco, matriz de bytes en la memoria, la carga de la tienda de cert local, etc.

La CA raíz utilizada para firmar el certificado tendrá que ser instalado en la tienda local de cert. Si el certificado no incluye las CA intermedias en la cadena de confianza, aquellos intermedios tendrán que estar en el equipo local también, todo el camino hasta una CA raíz que se encuentra en el almacén confiado cert en la máquina local.

Por desgracia, no puedo decir de la documentación de MSDN si X509Certificate2 está disponible en .NetCF.

A mí me funciona en Win32, pero en el marco compacto que estoy enfrentando el mismo problema, no hay X509Certificate2 así que estoy realmente bloqueado, con win32 que podemos hacer:

X509Certificate2 l__PublicKeyCertificate = new X509Certificate2("cert.cer");

RSACryptoServiceProvider l__rsaCspPublic = (RSACryptoServiceProvider)l__PublicKeyCertificate .PublicKey.Key;

//...

l__isVerified = l__rsaCspPublic.VerifyData(l__fileData, CryptoConfig.MapNameToOID("SHA1"), l__fileSignature);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top