使用nist向量值作为输入的openssl hmac代码的验证系统

时间:2017-04-13 03:54:27

标签: c openssl cryptography hmac

我写了一个c代码,它接受key和message的输入值,调用openssl hmac函数并生成mac代码的结果。 输入值从NIST测试向量

收集
#define KEY_SIZE 11         // in bytes
#define MSG_SIZE 129          // in bytes
#include <stdio.h>
#include <string.h>
#include <openssl/hmac.h>

void str2hex(char *, char*, int);

int main() {
   char *key, *msg;
   unsigned char keyy[KEY_SIZE], msgt[MSG_SIZE], temp[4];
   unsigned char* result;
   unsigned int i, len = 20,Tlen = 10;

   key = "";//values specified below
   msg ="";//values specified below
   /*CONVERT STRING TO HEX DIGITS - KEY*/
   str2hex(key, keyy, KEY_SIZE);
  //CONVERT STRING TO HEX DIGITS - MSG*//
   str2hex(msg, msgt, MSG_SIZE);


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

   HMAC_CTX ctx;
   HMAC_CTX_init(&ctx);


   HMAC_Init_ex(&ctx, keyy, strlen(keyy), EVP_sha1(), NULL);
   HMAC_Update(&ctx, (unsigned char*)&msgt, strlen(msgt));
   HMAC_Final(&ctx, result, &len);
   HMAC_CTX_cleanup(&ctx);

   printf("HMAC digest: ");

   for (i = 0; i < Tlen; i++)
    printf("%02x", result[i]);

   printf("\n");

   free(result);

   return 0;
}
//=====================  string to hex conversion 
================================//

void str2hex(char *str, char *hex, int len) {
  int tt, ss;
  unsigned char temp[4];
  for (tt = 0, ss = 0; tt < len, ss < 2 * len; tt++, ss += 2) {
    temp[0] = '0';
    temp[1] = 'x';
    temp[2] = str[ss];
    temp[3] = str[ss + 1];

    hex[tt] = (int) strtol(temp, NULL, 0);
  }
}

//---------------------------------------------------------------------------------//

给出的第一个输入:

Key = 82f3b69a1bff4de15c33
Msg = fcd6d98bef45ed6850806e96f255fa0c8114b72873abe8f43c10bea7c1df706f10458e6d4e1c9201f057b8492fa10fe4b541d0fc9d41ef839acff1bc76e3fdfebf2235b5bd0347a9a6303e83152f9f8db941b1b94a8a1ce5c273b55dc94d99a171377969234134e7dad1ab4c8e46d18df4dc016764cf95a11ac4b491a2646be1

生成的输出:

 HMAC digest: 1ba0e66cf72efc349207

Nist_Mac = 1ba0e66cf72efc349207

它如此成功

但是对于第二个输入

Key = 4766e6fe5dffc98a5c50
Msg = d68b828a153f5198c005ee36c0af2ff92e84907517f01d9b7c7993469df5c21078fa356a8c9715ece2414be94e10e547f32cbb8d0582523ed3bb0066046e51722094aa44533d2c876e82db402fbb00a6c2f2cc3487973dfc1674463e81e42a39d9402941f39b5e126bafe864ea1648c0a5be0a912697a87e4f8eabf79cbf130e

生成的输出:

 HMAC digest: ca96f112a79882074b63

Nist_Mac = 007e4504041a12f9e345

它的失败。如果有人能查看我的代码,请告诉我我做错了什么,这将非常有帮助。

2 个答案:

答案 0 :(得分:2)

这里有两个问题。

首先,您在可能包含空字节的字符数组上使用strlen。由于此函数在查找空字节之前计算字节数,因此如果数组包含空字节,则无法获得预期结果(如第二个示例所示)。

不使用字节数组上的strlen来确定长度,而是使用数据的实际长度。由于您将包含十六进制数字的字符串转换为字节,因此字节数组的长度是输入字符串长度的一半。

HMAC_Init_ex(&ctx, keyy, strlen(key)/2, EVP_sha1(), NULL);
HMAC_Update(&ctx, msgt, strlen(msg)/2);

另请注意,您应将msgt传递给HMAC_Update,而不是&msgt,因为后者是指向数组的指针。

第二个问题出在您的str2hex函数中。构造temp时,没有足够的空间来终止空字节。这会导致strtol(需要以空字符结尾的字符串)读取超出数组末尾的内容。这会调用undefined behavior

在这种特殊情况下,你很“幸运”它可以工作,因为temp后面的内存中的字节碰巧包含空字节或非数字。但是,您无法依赖此行为。通过使temp长一个字节并将该字节显式设置为0来解决此问题。当您处于此状态时,还应修复函数参数中的有符号/无符号不匹配并更改{{1}的类型}到temp数组。

unsigned char

答案 1 :(得分:0)

在消息的字节位置58处,您有一个0x00字节(空)。由于您正在执行strlen(msgt),因此会产生58而不是128.摘自文档(强调我的):

  

C库函数size_t strlen(const char *str)计算字符串str 的长度,但不包括终止空字符

只需使用正确长度的消息,不要对不包含可打印字节的char数组使用字符串操作。