Понимание инициализации двигателя в OpenSSL
Я пытаюсь настроить базовый тест хеширования HMAC-SHA-256, но у меня возникают проблемы с настройкой двигателя. В идеале я хотел бы настроить только алгоритм HMAC-SHA, но до сих пор я даже не получил общий случай, когда загружать все алгоритмы в работу. В настоящее время я получаю segfaults в строке, где я пытаюсь установить дайджесты по умолчанию.
Кроме того, я регулярно являюсь 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: теперь программа развивается следующим образом, но я по-прежнему испытываю трудности с 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);
Ответы
Ответ 1
Проблема с вашим первоначальным предложением, как сказал Мартин, заключается в том, что вам нужно инициализировать ДВИГАТЕЛЬ. Проблема с вашим отредактированным кодом заключалась в том, что вы делали ENGINE_new, что дает вам совершенно новый ДВИГАТЕЛЬ, который вам тогда необходимо предоставить с помощью методов шифрования, методов дайджеста и т.д. На самом деле, для чего вы хотите (и что почти все хотят), просто полное игнорирование всего ДВИГАТЕЛЯ - правильный выбор.
Некоторые дополнительные проблемы:
- ваши строки были шестыми, но вам понадобилось \x на символ, чтобы на самом деле получить этот шестнадцатеричный байт в этой позиции в строке, что, я подозреваю, было тем, что вы хотели.
- вы пытались хэшировать 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;
}
Конечно, он не отвечает на ваш первоначальный вопрос о том, как инициализировать ДВИГАТЕЛИ, но на самом деле нет правильного ответа на этот вопрос, не имея больше контекста, какой контекст оказывается неактуальным в вашей ситуации...
Ответ 2
Хорошо, получается, что вам не нужно использовать движок, но я неправильно понял, как не использовать явный движок. Я также неправильно понял, как правильно форматировать тестовые векторы. В конце я посмотрел на 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);
}
}
Но поскольку я спрашивал о чем-то совершенно другом, я не уверен, что делать с исходным вопросом. Предложения?
Ответ 3
Похоже, что ничего не выделяет движок, поэтому первое использование e
является segfault. Я думаю, вам нужно сначала позвонить ENGINE *ENGINE_new(void)
.
(Обратите внимание, что я использовал OpenSSL, но раньше я не использовал функции ENGINE
.)
Обновление. Я не очень доволен своим собственным ответом (раньше мне приходилось бросаться на чай). Итак, мои дальнейшие заметки:
-
Я немного взглянул на (длинную) справочную страницу для функций ENGINE
и Я не совсем уверен, что вызова ENGINE_new
достаточно.
-
Я не заметил, что вызовы функций HMAC_CTX_*
занимали неинициализированный указатель, а не указатель на выделенную структуру. HMAC_CTX_init
попытается записать в память, указанную параметром ctx
, который будет segfault. Вам нужно объявить и использовать ctx
следующим образом:
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, key, 40, EVP_sha256(), e);
...
Таким образом вы выделяете структуру в стеке, а затем передаете ему указатель.
-
Функция HMAC
вообще не принимает указатель на ctx
, поэтому, помимо глобального или потокового локального хранилища, я не уверен, что это соединение с ctx
. Я думаю, вы можете обойти это, вызвав HMAC_Update
один или несколько раз, а затем HMAC_Final
, чтобы получить результат. Вам нужно будет выделить пространство для этого результата, поэтому для этого будет создано следующее:
unsigned int len;
HMAC_Final(&ctx, result, &len);