2011-12-20 27 views
5

I wygenerowany certyfikat X509 z użyciem klucza prywatnego MakeCert narzędziaOpenSSL i MS CryptoAPI: różne podpisy cyfrowe

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 

Potem przeliczona RootCATest.pvk do RootCATest.pem z OpenSSL. I wyodrębniłem klucz publiczny: pubRootCATest.pem

Mam mały plik o nazwie "msg". I podpisuję ten plik przy użyciu SHA1.

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

Następnie chcę uzyskać ten sam podpis cyfrowy za pomocą MS CryptoAPI.

Oto mój kod (Uwaga: jest to kod do zrozumienia pojęć, więc nie wolnego przydzieloną pamięć)

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

jako wyjście uzyskać podpis absolutnie inny od podpisem wykonane przez OpenSSL. Jak mogę uzyskać ten sam podpis?

Ponieważ uważam istnieje kilka chwil, aby zwrócić uwagę:

  • Moja msg_size jest taki sam jak rozmiar pliku. Tak więc jest to liczba bajtów do znaku . Na niektórych stronach widziałem zalecenia, aby dodać bajt zerowy do tablicy bajtu. Czy naprawdę tego potrzebuję w takim przypadku?
  • Flaga CRYPT_NOHASHOID. Bez niego otrzymam sygnaturę o rozmiarze 130 bajtów, gdy podpis wykonany przez OpenSSL ma 128 bajtów. Myślę więc, że powinien tam być CRYPT_NOHASHOID.
  • SwapBytes (...) Próbowałem z nim i bez niego. I w obu przypadkach I mają podpisy zupełnie inne niż podpis OpenSSL.
+0

Istnieje wiele różnych formatów zarówno danych wprowadzanych do podpisu, jak i samego podpisu. To jest ta część, którą musisz poprawić. –

+0

Teraz użyj RSA_verify, aby zweryfikować tę sygnaturę i jeśli jest ona weryfikowalna, to jest taka sama. – doptimusprime

Odpowiedz

-1

Jak mogę uzyskać ten sam podpis?

Większość algorytmów podpisu cyfrowego - w tym RSA, który, jak przypuszczam, użyliśmy tutaj, jest niedeterministyczna. Spróbuj dwukrotnie podpisać ten sam plik w tym samym programie, a otrzymasz różne wyniki.

Oznacza to, że dwukrotne uruchomienie tego samego algorytmu z tymi samymi danymi wejściowymi da różne sygnatury. Nie stanowi to problemu, o ile algorytm weryfikacji nadal akceptuje wszystkie sygnatury wygenerowane przez algorytm podpisywania (za pomocą klucza dopasowania).

Ten niedeterminizm jest często niezbędny do zapewnienia bezpieczeństwa systemu podpisów.

Aby sprawdzić, czy oba algorytmy podpisu są zgodne, spróbuj zweryfikować podpis OpenSSL za pomocą MS Crypto API i zweryfikować podpis MS Crypto za pomocą OpenSSL. (Następnie zmodyfikuj plik o jeden bajt i sprawdź, czy nie są już weryfikowane.)

+0

Paulo, udało mi się uzyskać ten sam podpis. Ale zmieniłem to zadanie. – Stanislav

+2

Generowałem klucz i podpis za pomocą MS CryptoAPI i sprawdzałem poprawność za pomocą OpenSSL. I wzajemnie. A podpisy były wyjątkowe!Więc przypuszczam, że mam do czynienia z deterministycznym RSA w moim przypadku. – Stanislav

+0

Jeśli te same dane są podpisane przez ten sam klucz prywatny, podpis będzie zawsze taki sam, jak wypełnienie nie jest przypadkowe. – doptimusprime