2013-04-25 22 views
5

Próbuję napisać kod, aby zweryfikować niektóre podpisy RSA. Podpisy zostały wykonane przy użyciu narzędzia OpenSSL wiersza poleceń, używając równowartość tej linii poleceń:Weryfikacja podpisu RSA OpenSSL: skrót i dopełnienie?

openssl dgst -sha1 -sign private_key_file.pem <binary_data_file> sig 

próbuję użyć libtomcrypt zrobić to zweryfikować:

http://www.libtom.org/

Oto wzywając podpis funkcji weryfikacyjnej RSA w libtomcrypt:

int rsa_verify_hash_ex(
    const unsigned char *sig, unsigned long siglen, // signature to verify 
    const unsigned char *hash, unsigned long hashlen, // hash value to check against sig 
    int padding, // defined constant value, see below 
    int hash_idx, // identifies which hash algorithm, see below 
    unsigned long saltlen, // specify salt length, see below 
    int *stat, // output parameter, returns whether verify succeeded or not 
    rsa_key *key); // RSA public key to use for verify 

funkcja zwraca 0, jeśli działa bez błędu, w przeciwnym razie zwraca kod błędu. Jeśli działa bez błędu, parametr wyjściowy stat wskazuje, czy podpis został zweryfikowany.

Większość argumentów wydaje się prosta: należy podać podpis do sprawdzenia, wartość mieszania użyć do porównania oraz klucz RSA, który ma zostać użyty do kontroli. hash_idx wynika z przykładowego kodu dołączonego do libtomcrypt; jest indeksem do tabeli obsługiwanych algorytmów mieszających, a znajdę poprawną wartość używać z tym fragmencie kodu: hash_idx = find_hash("sha1")

Ale zastanawiam się o wartościach padding i saltlen. padding nie martwi mnie zbyt wiele, ponieważ istnieją tylko dwie możliwe wartości i mogę po prostu wypróbować je oba. Ale co powinienem przekazać dla saltlen?

Dokumentacja OpenSSL dla funkcji OpenSSL dla weryfikacji RSA nie wyświetla parametru saltlen. Strona podręcznika dla openssl dgst (tj. Wynik man dgst) nie omawia soli.

więc moje pytania:

  • Jak mogę określić prawidłową długość sól używać?
  • Czy dgst poleceń OpenSSL wkładać żadnych dodatkowych rzeczy w danych wejściowych, takich jak: (stdin)=

(I okazało się, że (stdin)= rzecz wyszukując StackOverflow: Why are the RSA-SHA256 signatures I generate with OpenSSL and Java different?)

  • libtomcrypt posiada również funkcję o nazwie pkcs_1_pss_decode() który jest udokumentowany w celu "odkodowania bloku podpisu kodowanego PSS". Czy jest jakaś szansa, że ​​jest to funkcja, którą muszę wywołać?

Dzięki za pomoc, jaką możesz mi dać.

EDYCJA: dzięki pomocy poniżej, z @ Jonathan Ben-Avraham, udało mi się uzyskać to działa już dziś. Odpowiedzi na moje pytania są następujące:

  • Użyj długości 0 dla soli, bez soli.
  • Nie, OpenSSL nie wkładać żadnych dodatków takich jak (stdin)=
  • Musiałem zadzwonić rsa_verify_hash_ex(), a ja potrzebowałem określić padding argumentu jako LTC_LTC_PKCS_1_V1_5.

Odpowiedz

7

Nie sól:

Najpierw wygenerować binarny SHA1 hash danych:

openssl dgst -sha1 -binary -out hash1 some_data_file 

To jest hash SHA1 lub strawienia. Nie ma soli dodanej do pliku some_data_file. Samo openssl dgst -sha1 nie dodaje soli. Zauważ, że plik wyjściowy jest tylko 20-bajtowym hash SHA1 bez soli. Jeśli istniała sól, hasz musiałby ją uwzględnić, prawdopodobnie przed ostatnimi 20 bajtami, które zawierają skrót SHA1.

Następnie podpisać plik SHA1 hash hash1 ze swoim kluczem prywatnym:

openssl pkeyutl -sign -in hash1 -inkey privkey.pem -pkeyopt digest:sha1 -out sig1 

teraz podpisać some_data_file z openssl dgst:

openssl dgst -sha1 -sign privkey.pem <some_data_file> sig2 

Wreszcie, porównaj dwa podpisy:

diff sig1 sig2 

i powinieneś zobaczyć, że są podobnie. To mówi nam, że podpisanie surowego sumy SHA1 pliku bez soli jest takie samo jak użycie polecenia openssl dgst -sha1 -sign do podpisania pliku, więc musi być tak, że komenda openssl dgst -sha1 -sign również nie użyła żadnej soli podczas generowania skrótu SHA1 dla sig2.

Należy również zauważyć, że nie można osiągnąć ten sam efekt przy użyciu przestarzałej rsautl:

openssl rsautl -sign -in hash1 -inkey privkey.pem -out sig1 

zamiast openssl pkeyutl, najwyraźniej dlatego openssl rsautl -sign zawiera zaszyfrowany tekst na wyjściu, jak również podpis. Aby uzyskać szczegółowe informacje, patrz this SE post.

+0

Dziękuję za naprawdę doskonałą odpowiedź. Dałeś mi narzędzia, by przekonać się, że nie ma soli. Mam teraz kod 'libtomcrypt', który skutecznie sprawdza podpis! +1 i odpowiedź zaakceptowana. – steveha

+0

@steveha: Dzięki! Możesz również zobaczyć późniejszy wpis dotyczący '' rsautl'': http://stackoverflow.com/questions/9951559/difference-between-openssl-rsautl-and-dgst –

3

Jedna uwaga: należy podać wartość hash zamiast rzeczywistych danych. To mnie odtrąciło na jakiś czas. Oto urywek, który działa (ale użyj sha256):

void 
verify_tomcrypt(unsigned char *keyblob, size_t klen, 
       unsigned char *payload, size_t dlen, 
       unsigned char *signature, size_t slen) 
{ 
    rsa_key key; 
    int stat; 
    unsigned long len; 
    unsigned char digest2[SHA256_DIGEST_LENGTH]; 

    ltc_mp = ltm_desc; 
    register_hash(&sha256_desc); 

    /* try reading the key */ 
    if (rsa_import(keyblob, klen, &key) != CRYPT_OK) { 
     printf("Error reading key\n"); 
     exit(-1); 
    } 

    int hash_idx = find_hash("sha256"); 
    if (hash_idx == -1) { 
     printf("LTC_SHA256 not found...?\n"); 
     exit(-1); 
    } 
    len = sizeof(digest2); 
    if (hash_memory(hash_idx, payload, dlen, digest2, &len) != CRYPT_OK) { 
     printf("sha256 fails...?\n"); 
     exit(-1); 
    } 

    if (rsa_verify_hash_ex(signature, slen, digest2, sizeof(digest2), LTC_LTC_PKCS_1_V1_5, hash_idx, 0, &stat, &key) == CRYPT_OK) { 
     if (stat == 1) 
      printf("Tomcrypt: Signature OK!\n"); 
     else 
      printf("Tomcrypt: Signature NOK?\n"); 
    } else { 
     printf("Tomcrypt: Signature error\n"); 
    } 
} 
+0

Dzięki za przykładowy kod. –

+0

Otrzymuję 'CRYPT_PK_INVALID_SIZE' dla określonego sprawdzenia rsa sig. Czy masz problem? ten błąd jest zwracany przez 'rsa_verify_hash_ex' –

Powiązane problemy