2011-12-20 12 views
5

que generan certificado X509 con la clave privada usando la utilidad makecertOpenSSL y MS CryptoAPI: diferentes firmas digitales

makecert -n "CN=RootCATest" -r -sv RootCATest.pvk RootCATest.cer 
makecert -sk MyKeyName -iv RootCATest.pvk -n "CN=tempCert" -ic RootCATest.cer -sr currentuser -ss my -sky signature —pe 

Entonces convertidos RootCATest.pvk a RootCATest.pem con OpenSSL. Y extraje la clave pública: pubRootCATest.pem

Tengo un archivo pequeño llamado 'msg'. Y firmo este archivo usando SHA1.

openssl dgst -sha1 -sign c:\RootCATest.pem -out c:\openssl c:\msg 

Luego quiero obtener la misma firma digital usando MS CryptoAPI.

Aquí está mi código (Nota: este es el código para entender los conceptos por lo que no hago memoria asignada libre)

void SwapBytes(BYTE *pv, int n) 
{ 
    BYTE *p = pv; 
    int lo, hi; 
    for(lo=0, hi=n-1; hi>lo; lo++, hi--) 
    { 
     BYTE tmp=p[lo]; 
     p[lo] = p[hi]; 
     p[hi] = tmp; 
    } 
} 

void sign() 
{ 
    FILE *file; 
    BYTE *msg; 
    int msg_size; 

    HCRYPTPROV hProv; 
    HCERTSTORE hStore; 
    PCCERT_CONTEXT pCert; 
    DWORD dwKeySpec; 
    BOOL fCallerFreeProv; 
    BYTE *pSignature; 
    DWORD sigLen; 

    // Read message bytes from file 
    file = fopen("c:\\msg", "r"); 
    fseek(file, 0, SEEK_END); 
    msg_size = ftell(file); 
    fseek(file, 0, SEEK_SET); 
    msg = new BYTE[msg_size]; 
    fread(msg, sizeof(BYTE), msg_size, file); 
    fclose(file); 

    hStore = CertOpenSystemStore(NULL, "My"); 
    pCert = CryptUIDlgSelectCertificateFromStore(hStore, NULL, NULL, NULL, 0, 0, NULL); 
    CryptAcquireCertificatePrivateKey(pCert, CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, &hProv, &dwKeySpec, &fCallerFreeProv); 
    PrintCryptoProviderName(hProv); // prints Microsoft Strong Cryptographic Provider 

    ALG_ID hashAlgId = CALG_SHA1; 
    HCRYPTHASH hHash; 
    CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash); 
    CryptHashData(hHash, msg, msg_size, 0); 

    CryptSignHash(hHash, dwKeySpec, NULL, 0, NULL, &sigLen); 
    pSignature = new BYTE[sigLen]; 
    CryptSignHash(hHash, dwKeySpec, NULL, CRYPT_NOHASHOID, pSignature, &sigLen); 

    SwapBytes(pSignature, sigLen); // Here i reverse byte order as I read that MS CryptoAPI uses reversed byte order 

    // Write signature bytes to file 
    file = fopen("c:\\CryptSignHash", "w"); 
    fwrite(pSignature, sizeof(BYTE), sigLen, file); 
    fclose(file); 
} 

medida que la producción llegue la firma absolutamente diferente de la firma hecha por OpenSSL. ¿Cómo puedo obtener la misma firma?

Dado que considero que hay algunos momentos para prestar atención:

  • Mi msg_size es el mismo que el tamaño del archivo. Por lo tanto, es el número de bytes a signo. En algunos sitios, vi recomendaciones para agregar un arreglo de bytes nulos a byte . ¿Realmente lo necesito en tal caso?
  • La bandera CRYPT_NOHASHOID. Sin él obtengo la firma de tamaño 130 bytes, cuando la firma realizada por OpenSSL es de 128 bytes. Así que creo que CRYPT_NOHASHOID debería estar allí.
  • SwapBytes (...) Lo intenté sin él. Y en ambos casos I tienen firmas completamente diferentes a la firma de OpenSSL.
+0

Existen muchos formatos diferentes tanto para los datos que entran en la firma como para la propia firma. Esta es la parte que tendrá que hacer bien. –

+0

Ahora, use RSA_verify para verificar esta firma y si es verificable, entonces es la misma. – doptimusprime

Respuesta

-1

¿Cómo puedo obtener la firma?

La mayoría de los algoritmos de firma digital, incluido RSA, que supongo que ha utilizado aquí, no son deterministas. Intente firmar el mismo archivo dos veces con el mismo programa, y ​​obtendrá diferentes resultados.

Esto significa que ejecutar el mismo algoritmo dos veces con la misma entrada le dará diferentes firmas. Esto no es un problema, siempre que el algoritmo de verificación logre aceptar todas las firmas generadas por el algoritmo de firma (con la clave de adaptación).

Este no determinismo a menudo es realmente necesario para la seguridad del esquema de firma.

Para ver si sus dos algoritmos de firma son realmente compatibles, intente verificar la firma de OpenSSL con la API de MS Crypto y verificar la firma de MS Crypto con OpenSSL. (Luego, modifique el archivo por un byte y verifique que ya no lo verifiquen.)

+0

Paulo, logré obtener la misma firma. Pero cambié la tarea. – Stanislav

+2

Genere clave y firma con MS CryptoAPI y valide con OpenSSL. Y viceversa. ¡Y las firmas fueron únicas!Entonces supongo que tengo un trato con RSA determinista en mi caso. – Stanislav

+0

Si los mismos datos están firmados por la misma clave privada, la firma siempre será la misma ya que el relleno no es aleatorio. – doptimusprime