跳到主要内容

附录 - 示例代码 (Appendix - Sample Code)

为了说明目的, 我们提供以下 HMAC-MD5 实现的示例代码以及一些相应的测试向量 (代码基于 [MD5] 中描述的 MD5 代码)。

/*
** Function: hmac_md5
*/

void
hmac_md5(text, text_len, key, key_len, digest)
unsigned char* text; /* 指向数据流的指针 */
int text_len; /* 数据流的长度 */
unsigned char* key; /* 指向认证密钥的指针 */
int key_len; /* 认证密钥的长度 */
caddr_t digest; /* 调用者要填充的摘要 */

{
MD5_CTX context;
unsigned char k_ipad[65]; /* 内部填充 -
* 密钥与 ipad 异或
*/
unsigned char k_opad[65]; /* 外部填充 -
* 密钥与 opad 异或
*/
unsigned char tk[16];
int i;
/* 如果密钥长于 64 字节, 将其重置为 key=MD5(key) */
if (key_len > 64) {

MD5_CTX tctx;

MD5Init(&tctx);
MD5Update(&tctx, key, key_len);
MD5Final(tk, &tctx);

key = tk;
key_len = 16;
}

/*
* HMAC_MD5 变换如下:
*
* MD5(K XOR opad, MD5(K XOR ipad, text))
*
* 其中 K 是 n 字节密钥
* ipad 是字节 0x36 重复 64 次
* opad 是字节 0x5c 重复 64 次
* text 是被保护的数据
*/

/* 首先将密钥存储在填充中 */
bzero( k_ipad, sizeof k_ipad);
bzero( k_opad, sizeof k_opad);
bcopy( key, k_ipad, key_len);
bcopy( key, k_opad, key_len);

/* 将密钥与 ipad 和 opad 值异或 */
for (i=0; i<64; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/*
* 执行内部 MD5
*/
MD5Init(&context); /* 初始化第 1 次
* 传递的上下文 */
MD5Update(&context, k_ipad, 64) /* 从内部填充开始 */
MD5Update(&context, text, text_len); /* 然后是数据报的文本 */
MD5Final(digest, &context); /* 完成第 1 次传递 */
/*
* 执行外部 MD5
*/
MD5Init(&context); /* 初始化第 2 次
* 传递的上下文 */
MD5Update(&context, k_opad, 64); /* 从外部填充开始 */
MD5Update(&context, digest, 16); /* 然后是第 1 次
* 散列的结果 */
MD5Final(digest, &context); /* 完成第 2 次传递 */
}

测试向量 (Test Vectors)

字符串末尾的 \0 不包含在测试中:

测试用例 1:

key =         0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
key_len = 16 字节
data = "Hi There"
data_len = 8 字节
digest = 0x9294727a3638bb1c13f48ef8158bfc9d

测试用例 2:

key =         "Jefe"
data = "what do ya want for nothing?"
data_len = 28 字节
digest = 0x750c783e6ab0b503eaa86e310a5db738

测试用例 3:

key =         0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
key_len 16 字节
data = 0xDDDDDDDDDDDDDDDDDDDD...
..DDDDDDDDDDDDDDDDDDDD...
..DDDDDDDDDDDDDDDDDDDD...
..DDDDDDDDDDDDDDDDDDDD...
..DDDDDDDDDDDDDDDDDDDD
data_len = 50 字节
digest = 0x56be34521d144c88dbb8c733f0e8b3f6