我写了一个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
它的失败。如果有人能查看我的代码,请告诉我我做错了什么,这将非常有帮助。
答案 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数组使用字符串操作。