C ++ OpenSSL HMACSHA1 работает, но не так, как я хочу - PullRequest
0 голосов
/ 29 сентября 2011

Этот код HMACSHA1 ниже работает для преобразования "Пароль" и "Сообщение" в AFF791FA574D564C83F6456CC198CBD316949DC9 в качестве доказательства http://buchananweb.co.uk/security01.aspx.

Мой вопрос: возможно ли иметь:

BYTE HMAC[] = {0x50,0x61,0x73,0x73,0x77,0x6F,0x72,0x64};
BYTE data2[] = {0x4D,0x65,0x73,0x73,0x61,0x67,0x65};

И все равно получите то же значение: AFF791FA574D564C83F6456CC198CBD316949DC9.

Например, если я был на сервере и получил пакет:

[HEADER] 08 50 61 73 73 77 6F 72 64 00
[HEADER] 07 4D 65 73 73 61 67 65 00

И я копирую 50 61 73 73 77 6F 72 64 & 4D 65 73 73 61 67 65 из пакета и использовал это для моего HMACSHA1.Как бы я поступил так, чтобы получить правильное значение HMACSHA1?

    BYTE HMAC[] = "Password";
    BYTE data2[] = "Message";
    //BYTE HMAC[] = {0x50,0x61,0x73,0x73,0x77,0x6F,0x72,0x64};
    //BYTE data2[] = {0x4D,0x65,0x73,0x73,0x61,0x67,0x65};
    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, HMAC, strlen((const char*)HMAC), EVP_sha1(), NULL);
    HMAC_Update(&ctx, data2, strlen((const char*)(data2)));
    HMAC_Final(&ctx, result, &result_len);
    HMAC_CTX_cleanup(&ctx);

    std::cout << "\n\n";


 for(int i=0;i<result_len;i++)
    std::cout << setfill('0') << setw(2) << hex << (int)result[i];

    int asd;
    std::cin >> asd;
// AFF791FA574D564C83F6456CC198CBD316949DC9

РЕДАКТИРОВАТЬ:

Это работает следующим образом:

BYTE HMAC[] = {0x50,0x61,0x73,0x73,0x77,0x6F,0x72,0x64, 0x00};
BYTE data2[] = {0x4D,0x65,0x73,0x73,0x61,0x67,0x65, 0x00};

Добавляя 0x00,в конце.Но мой вопрос больше связан с извлечением их из данных и их использованием ... все равно будет хорошо?

1 Ответ

2 голосов
/ 29 сентября 2011

Проблема заключается в связи между массивами, строками и нулевым символом.

Когда вы объявляете «Пароль», компилятор логически обрабатывает строковый литерал как массив из девяти байтов, {0x50,0x61,0x73,0x73,0x77,0x6F, 0x72,0x64, 0x00}. Когда вы вызываете strlen, он будет считать количество байтов, пока не встретит первый 0x00. strlen ("Password") вернет 8, хотя технически в массиве символов девять символов.

Итак, когда вы объявляете массив из 8 байтов следующим образом без завершающего нулевого байта:

BYTE HMAC[] = {0x50,0x61,0x73,0x73,0x77,0x6F,0x72,0x64};

Проблема в том, что "strlen (HMAC)" будет считать не менее 8 байтов и будет продолжать считать, пока проходит через неопределенную память, пока, наконец, (если вообще когда-либо) не достигнет нулевого байта. В лучшем случае вам может повезти, потому что в памяти стека всегда есть нулевой байт, дополняющий объявление массива. Скорее всего, он вернет значение, намного большее 8. Может быть, это приведет к сбою.

Таким образом, когда вы анализируете поля HMAC и MESSAGE из вашего пакета протокола, вы подсчитываете количество фактически проанализированных байтов (не включая завершающий ноль). И передайте это число в функции hmac, чтобы указать размер ваших данных.

Я не знаю ваш код протокола, но я надеюсь, что вы не используете strlen для анализа пакета, чтобы выяснить, где заканчивается строка внутри пакета. Умный злоумышленник может внедрить пакет без нулевого терминатора и заставить ваш код делать плохие вещи. Я надеюсь, что вы анализируете безопасно и тщательно. Типичный код протокола не включает нулевой завершающий байт в строках, упакованных внутри. Обычно «длина» кодируется как целочисленное поле, за которым следуют строковые байты. Облегчает анализ и определение, будет ли длина превышать размер пакета, считанный.

...