Понимание инициализации движка в OpenSSL - PullRequest
10 голосов
/ 28 октября 2008

Я пытаюсь настроить базовый тест хэширования 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);
  }
}

РЕДАКТИРОВАТЬ: Программа теперь эволюционировала до следующего, но я все еще 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);

Ответы [ 3 ]

13 голосов
/ 29 октября 2008

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

Некоторые дополнительные проблемы:

  • ваши строки были шестнадцатеричными, но вам нужно было \ 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;
}

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

1 голос
/ 28 октября 2008

Хорошо, получается, что вам не нужно использовать движок, но я бы неправильно понял, как не использовать явный движок. Я также неправильно понял, как правильно отформатировать тестовые векторы. В конце концов, я посмотрел на 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 голосов
/ 28 октября 2008

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

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

Обновление : я не очень доволен своим собственным ответом (раньше мне приходилось бросаться к чаю). Итак, мои дальнейшие заметки:

  1. Я немного посмотрел на (длинную) справочную страницу для функций 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);
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...