2008-10-28 4 views
10

Я пытаюсь настроить базовый тест хеширования HMAC-SHA-256, но у меня возникают проблемы с настройкой двигателя. В идеале я хотел бы настроить только алгоритм HMAC-SHA, но до сих пор я даже не получил общий случай, когда загружать все алгоритмы в работу. В настоящее время я получаю segfaults в строке, где я пытаюсь установить дайджесты по умолчанию.Понимание инициализации двигателя в OpenSSL

Кроме того, я регулярно являюсь Java-парнем, поэтому не стесняйтесь указывать на какие-либо ошибки в коде.

#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: Программа теперь развилось к следующему, но я до сих пор segfaulting в 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); 

ответ

13

Проблема с вашим первоначальным предложением заключается в том, что Мартин сказал, что вам нужно инициализировать ДВИГАТЕЛЬ. Проблема с вашим отредактированным кодом заключалась в том, что вы делали ENGINE_new, что дает вам совершенно новый ДВИГАТЕЛЬ, который вам тогда необходимо предоставить с помощью методов шифрования, методов дайджеста и т. Д. На самом деле, для чего вы хотите (и что почти все хотят), просто полное игнорирование всего ДВИГАТЕЛЯ - правильный выбор.

Некоторых вспомогательные задачи:

  • ваши строки были шестигранными, но требовался \ й на символ на самом деле получить шестнадцатеричные байты в этой позиции в строке, которую я подозреваю, было то, что вы хотели.
  • Вы пытались хэш-байт 40 байт из «данных», который был не таким длинным (фактический эффект: вы частично отделили бы строку результата)
  • Ваш ожидаемый результат был (насколько я могу судить) неверно
  • вы распечатываете случайные символы на терминал, так как функция HMAC будет производить 32 байта случайных двоичных данных, а не печатных материалов.

Следующий код компилирует, работает и проходит тест. Это немного отличается от примера кода вы нашли (так как он все еще использует отдельные HMAC_ * функция - полезно, если вы хотите сделать ваше хеширование по кусочкам, используя HMAC_Update):

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

Конечно, это не ответьте на свой первоначальный вопрос о том, как инициализировать ДВИГАТЕЛИ, но на самом деле нет правильного ответа на этот вопрос, не имея больше контекста, какой контекст оказывается неактуальным в вашей ситуации ...

0

Это выглядит так, как будто ничего не выделяет двигатель, поэтому первое использование e является segfault. Я думаю, вам нужно сначала позвонить ENGINE *ENGINE_new(void).

(Обратите внимание, что я использовал OpenSSL, но я раньше не использовал ENGINE функции.)

Update: Я не очень доволен свой собственный ответ (я должен был накатать к чай, раньше). Так что мои дальнейшие примечания:

  1. У меня было немного взглянуть на (длинный) man page для ENGINE функций, и я не совсем уверен, что вызов ENGINE_new достаточно.

  2. Я не заметил, что вызовы функций HMAC_CTX_* принимали неинициализированный указатель, а не указатель на выделенную структуру. HMAC_CTX_init попытается записать в память, указанную параметром ctx, который будет segfault. Вы должны объявить и использовать ctx как это:

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

    Таким образом, вы выделить структуру в стек, а затем передать указатель на него.

  3. HMAC функция не принимает указатель на CTX на всех, так что помимо глобальной или локальной памяти потока, я не уверен, что это соединение с CTX будет. Я думаю, вы можете обойти это, вызвав HMAC_Update один или несколько раз, за ​​которым следует HMAC_Final, чтобы получить результат. Вы должны были бы выделить место для этого результата, так что-то вроде следующего будет работать для этого:

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

Спасибо за предложение Martin, я попробовал но я все еще застрял. Мне любопытно про комментарий ENGINE о том, что вы его не использовали. Можно ли использовать OpenSSL без двигателя? – Fylke 2008-10-28 14:07:28

1

Хорошо, получается, что вы не должны использовать двигатель, но я не понял точно, как не использовать явный движок. Я также неправильно понял, как правильно форматировать тестовые векторы. В конце я посмотрел на hmactest.c, который в значительной степени делает все, что я хочу сделать, я просто не понял код.

Окончательное решение, что я пытался сделать, выглядит следующим образом:

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

Но так как я спрашивал о чем-то совсем другое, я не уверен в том, что делать с оригинальным вопросом. Предложения?

+0

NULL. Примечание: передача значения NULL для использования md для статического массива не является потокобезопасной. https://www.openssl.org/docs/man1.0.2/crypto/hmac.html – codenamezero 2018-01-29 15:42:11