2011-12-20 16 views
5

ho generati certificato X509 con la chiave privata utilizzando l'utility makecertOpenSSL e MS CryptoAPI: diverse firme digitali

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 

Poi ho convertito RootCATest.pvk a RootCATest.pem con OpenSSL. E ho estratto la chiave pubblica: pubRootCATest.pem

Ho un piccolo file chiamato "msg". E firmo questo file usando SHA1.

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

Poi voglio ottenere la stessa firma digitale utilizzando MS CryptoAPI.

Ecco il mio codice (Nota: questo è il codice per capire i concetti in modo da non lo faccio memoria allocata gratuito)

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

Come uscita ottengo la firma assolutamente diverso dalla firma fatta da OpenSSL. Come posso ottenere la stessa firma?

Poiché ritengo ci sono dei momenti di prestare attenzione:

  • mio msg_size è la stessa dimensione del file. Quindi è il numero di byte al segno . In alcuni siti ho visto raccomandazioni per aggiungere un byte null byte alla matrice byte. Ne ho davvero bisogno in questo caso?
  • La bandiera CRYPT_NOHASHOID. Senza di esso ottengo la firma dei byte di dimensione 130, quando la firma fatta da OpenSSL è di 128 byte. Quindi penso che CRYPT_NOHASHOID dovrebbe essere lì.
  • SwapBytes (...) Ho provato con esso e senza di esso. E in entrambi i casi I ha firme assolutamente diverse dalla firma OpenSSL.
+0

Esistono molti formati diversi sia per i dati inseriti nella firma che per la firma stessa. Questa è la parte che dovrai correggere. –

+0

Ora, usa RSA_verify per verificare questa firma e se è verificabile, allora è lo stesso. – doptimusprime

risposta

-1

Come posso ottenere la stessa firma?

maggior parte degli algoritmi di firma digitale - tra cui RSA, che suppongo di aver usato qui, sono non-deterministico. Prova a firmare lo stesso file due volte con lo stesso programma e otterrai diversi output.

Ciò significa che eseguire lo stesso algoritmo due volte con lo stesso input fornirà firme diverse. Questo non è un problema, a patto che l'algoritmo di verifica riesca ancora ad accettare tutte le firme generate dall'algoritmo di firma (con la chiave di adattamento).

Questo non determinismo è spesso effettivamente necessario per la sicurezza dello schema di firma.

Per verificare se i due algoritmi di firma sono effettivamente compatibili, provare a verificare la firma OpenSSL con l'API MS Crypto e verificare la firma di MS Crypto con OpenSSL. (Quindi modifica il file di un byte e verifica che non si verifichi più.)

+0

Paulo, sono riuscito ad ottenere la stessa firma. Ma ho cambiato il compito. – Stanislav

+2

Ho generato la chiave e la firma con MS CryptoAPI e la convalida con OpenSSL. E viceversa. E le firme erano uniche!Quindi suppongo di avere a che fare con un RSA deterministico nel mio caso. – Stanislav

+0

Se gli stessi dati sono firmati dalla stessa chiave privata, la firma sarà sempre la stessa di padding non casuale. – doptimusprime