2008-10-28 13 views
10

Ich versuche, einen grundlegenden Test von HMAC-SHA-256-Hashing einzurichten, aber ich habe Probleme mit dem Engine-Setup. Idealerweise würde ich nur den HMAC-SHA-Algorithmus einrichten, aber bis jetzt habe ich noch nicht einmal den allgemeinen Fall bekommen, in dem alle Algorithmen funktionieren. Momentan bekomme ich in der Zeile, in der ich versuche, die Standard-Digests zu setzen, Segmentfehler.Die Motorinitialisierung in OpenSSL verstehen

Außerdem bin ich regelmäßig ein Java-Typ, also zögere nicht, auf Fehler im Code hinzuweisen.

#include <openssl/hmac.h> 
#include <openssl/evp.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

int main() { 
    unsigned char* key = (unsigned char*) "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"; 
    unsigned char* data = (unsigned char*) "4869205468657265"; 
    unsigned char* expected = (unsigned char*) "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"; 
    unsigned char* result; 
    HMAC_CTX* ctx; 
    ENGINE* e; 

    ENGINE_load_builtin_engines(); 
    ENGINE_register_all_complete(); 
    ENGINE_set_default_digests(e); 

    HMAC_CTX_init(ctx); 
    HMAC_Init_ex(ctx, key, 40, EVP_sha256(), e); 
    result = HMAC(NULL, NULL, 40, data, 16, NULL, NULL); 
    HMAC_CTX_cleanup(ctx); 

    ENGINE_finish(e); 
    ENGINE_free(e); 

    if (strcmp((char*) result, (char*) expected) == 0) { 
    printf("Test ok\n"); 
    } else { 
    printf("Got %s instead of %s\n", result, expected); 
    } 
} 

EDIT: Das Programm nun auf die folgenden entwickelt hat, aber ich bin immer noch auf Speicherzugriffsfehler HMAC_Init_ex:

unsigned char* key = (unsigned char*) "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"; 
unsigned char* data = (unsigned char*) "4869205468657265"; 
unsigned char* expected = (unsigned char*) "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"; 
unsigned char* result; 
unsigned int result_len = 64; 
HMAC_CTX ctx; 
ENGINE* e; 

result = (unsigned char*) malloc(sizeof(char) * result_len); 
e = (ENGINE*) ENGINE_new(); 

ENGINE_load_builtin_engines(); 
ENGINE_register_all_complete(); 
ENGINE_set_default_digests(e); 

HMAC_CTX_init(&ctx); 
HMAC_Init_ex(&ctx, key, 16, EVP_sha256(), e); 
HMAC_Update(&ctx, data, 40); 
HMAC_Final(&ctx, result, &result_len); 
HMAC_CTX_cleanup(&ctx); 

ENGINE_finish(e); 
ENGINE_free(e); 

Antwort

13

Das Problem mit Ihrem ursprünglichen Vorschlag ist, wie Martin sagte, dass Sie den ENGINE initialisieren müssen. Das Problem mit deinem bearbeiteten Code war, dass du ENGINE_new machst, was dir einen völlig neuen MOTOR bringt, den du dann mit Verschlüsselungsmethoden, Digest-Methoden usw. versehen musst. In der Tat, für was du willst (und was? fast jeder will), einfach die MOTOR-Sachen völlig zu ignorieren ist die richtige Wahl.

Einige Tochterunternehmen Probleme:

  • Saiten waren hex, aber man benötigt pro Zeichen ein \ x tatsächlich an dieser Position in der Zeichenfolge, die Hex-Byte zu bekommen, was ich vermute, was Sie wollten.
  • Sie haben versucht, 40 Bytes von "Daten" zu Hash, die nicht so lange war (tatsächlicher Effekt: Sie würden teilweise Hashing Ihre Ergebniszeichenfolge)
  • Ihr erwartetes Ergebnis war (soweit ich das beurteilen kann) Inkorrekt
  • Sie würden zufällige Zeichen auf dem Terminal ausdrucken, da die HMAC-Funktion 32 Bytes zufällige Binärdaten, nicht druckbare Sachen produzieren wird.

Der folgende Code kompiliert, funktioniert und besteht den Test. Es ist ein bisschen anders als den Beispielcode Sie gefunden (da es immer noch die einzelnen HMAC_ verwendet * Funktionen - nützlich, wenn Sie Ihre Hashing bitweise mit HMAC_Update tun wollen):

#include <openssl/engine.h> 
#include <openssl/hmac.h> 
#include <openssl/evp.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 


int main(void) 
{ 
     unsigned char* key = (unsigned char*) "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; 
     unsigned char* data = (unsigned char*) "\x48\x69\x20\x54\x68\x65\x72\x65"; 
     unsigned char* expected = (unsigned char*) "\x49\x2c\xe0\x20\xfe\x25\x34\xa5\x78\x9d\xc3\x84\x88\x06\xc7\x8f\x4f\x67\x11\x39\x7f\x08\xe7\xe7\xa1\x2c\xa5\xa4\x48\x3c\x8a\xa6"; 
     unsigned char* result; 
     unsigned int result_len = 32; 
     int i; 
     HMAC_CTX ctx; 

     result = (unsigned char*) malloc(sizeof(char) * result_len); 

     ENGINE_load_builtin_engines(); 
     ENGINE_register_all_complete(); 

     HMAC_CTX_init(&ctx); 
     HMAC_Init_ex(&ctx, key, 16, EVP_sha256(), NULL); 
     HMAC_Update(&ctx, data, 8); 
     HMAC_Final(&ctx, result, &result_len); 
     HMAC_CTX_cleanup(&ctx); 

     for (i=0; i!=result_len; i++) 
     { 
       if (expected[i]!=result[i]) 
       { 
         printf("Got %02X instead of %02X at byte %d!\n", result[i], expected[i], i); 
         break; 
       } 
     } 
     if (i==result_len) 
     { 
       printf("Test ok!\n"); 
     } 
     return 0; 
} 

Natürlich ist es nicht Beantworten Sie Ihre ursprüngliche Frage, wie man MOTOREN initialisiert, aber es gibt wirklich keine richtige Antwort, ohne mehr Kontext zu haben, der Kontext stellt sich in Ihrer Situation als nicht relevant heraus ...

0

Es sieht aus, als ob nichts ein Motor zuteilt, so dass der erste Einsatz von e ist segfauling. Ich denke du musst zuerst ENGINE *ENGINE_new(void) anrufen.

(Beachten Sie, dass ich OpenSSL benutzt habe, aber ich habe die ENGINE Funktionen vor nicht verwendet.)

aktualisieren: Ich bin nicht wirklich zufrieden mit meiner eigenen Antwort (ich musste losstürzen zu Tee, vorher). Also meine weiteren Hinweise sind:

  1. Ich hatte ein bisschen einen Blick auf die (lange) man page für die ENGINE Funktionen, und ich bin mir nicht ganz sicher, dass ENGINE_new Aufruf ausreichend ist.

  2. Ich habe nicht bemerkt, dass die Aufrufe an die HMAC_CTX_* Funktionen einen nicht initialisierten Zeiger anstelle eines Zeigers zu einer zugewiesenen Struktur nahmen. HMAC_CTX_init versucht, in den Speicher zu schreiben, auf den der Parameter ctx zeigt, der segfault wird. Sie müssen erklären und verwenden ctx wie folgt aus:

    HMAC_CTX ctx; 
    HMAC_CTX_init(&ctx); 
    HMAC_Init_ex(&ctx, key, 40, EVP_sha256(), e); 
    ... 
    

    diese Weise können Sie die Struktur auf dem Stapel sind die Zuteilung und dann einen Zeiger auf sie vorbei.

  3. Die HMAC Funktion nimmt nicht einen Zeiger auf eine CTX überhaupt, so abgesehen von globalen oder lokalen Thread-Speicherung, ich bin nicht sicher, was es ist Verbindung zum CTX wird. Ich denke, dass Sie das umgehen können, indem Sie HMAC_Update einmal oder mehrmals, gefolgt von HMAC_Final aufrufen, um das Ergebnis zu erhalten. Sie würden brauchen Platz für das Ergebnis zuzuweisen, so etwas wie das folgende würde dafür arbeiten:

    unsigned int len; 
    HMAC_Final(&ctx, result, &len); 
    
+0

Danke für den Vorschlag Martin, ich habe es versucht sie raus, aber ich bin immer noch fest. Ich bin neugierig auf den ENGINE-Kommentar, dass du ihn nicht benutzt hast. Ist es möglich, OpenSSL ohne Engine zu verwenden? – Fylke

1

Okay, stellt sich heraus, dass Sie müssen nicht einen Motor verwenden, aber ich hatte falsch verstanden genau wie man eine explizite Engine nicht benutzt. Ich habe auch falsch verstanden, wie man die Testvektoren richtig formatiert. Am Ende habe ich auf hmactest.c geschaut, was so ziemlich alles tut, was ich will, ich habe den Code einfach nicht verstanden.

Die endgültige Lösung zu dem, was ich versuche, sieht aus wie dies zu tun:

int main() { 
    unsigned char* key = (unsigned char*) "Jefe"; 
    unsigned char* data = (unsigned char*) "what do ya want for nothing?"; 
    unsigned char* expected = (unsigned char*) "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"; 
    unsigned char* result; 
    unsigned int result_len = 32; 
    int i; 
    static char res_hexstring[32]; 

    result = HMAC(EVP_sha256(), key, 4, data, 28, NULL, NULL); 
    for (i = 0; i < result_len; i++) { 
    sprintf(&(res_hexstring[i * 2]), "%02x", result[i]); 
    } 

    if (strcmp((char*) res_hexstring, (char*) expected) == 0) { 
    printf("Test ok, result length %d\n", result_len); 
    } else { 
    printf("Got %s instead of %s\n", res_hexstring, expected); 
    } 
} 

Aber da ich über etwas ganz anderes frage, ich bin nicht sicher, was mit der ursprünglichen Frage zu tun. Vorschläge?

+0

NULL. Hinweis: Die Übergabe eines NULL-Wertes für md zur Verwendung des statischen Arrays ist nicht Thread-sicher. https://www.openssl.org/docs/man1.0.2/crypto/hmac.html – codenamezero