关于HMAC-SHA-1的算法问题

阿振 2010-11-10 09:15:33
大家好,最近研究OTP,自然而然的就要扯到了算法,说道算法自然而然的就谈起了HMAC的算法,问题是采用RFC2104中的算法,计算HMAC-MD5计算出来的东西是正常的,换成HMAC-SHA1却老是和RFC文档中的不一样。

测试HMAC-SHA1的测试用:
The following test data uses the ASCII string
"12345678901234567890" for the secret:
Secret = 0x3132333435363738393031323334353637383930
Table 1 details for each count, the intermediate HMAC value.
Count Hexadecimal HMAC-SHA-1(secret, count)
0 cc93cf18508d94934c64b65d8ba7667fb7cde4b0
1 75a48a19d4cbe100644e8ac1397eea747a2d33ab
2 0bacb7fa082fef30782211938bc1c5e70416ff44
3 66c28227d03a2d5529262ff016a1e6ef76557ece
4 a904c900a64b35909874b33e61c5938a8e15ed1c
5 a37e783d7b7233c083d4f62926c7a25f238d0316
6 bc9cd28561042c83f219324d3c607256c03272ae
7 a4fb960c0bc06e1eabb804e5b397cdc4b45596fa
8 1b3c89f65e6c9e883012052823443f048b4332db
9 1637409809a679dc698207310c8c7fc07290d9e5

这里的是2进制截断之后的相对应的HOTP值
hexadecimal and decimal) and then the HOTP value.
Truncated
Count Hexadecimal Decimal HOTP
0 4c93cf18 1284755224 755224
1 41397eea 1094287082 287082
2 82fef30 137359152 359152
3 66ef7655 1726969429 969429
4 61c5938a 1640338314 338314
5 33c083d4 868254676 254676
6 7256c032 1918287922 287922
7 4e5b397 82162583 162583
8 2823443f 673399871 399871
9 2679dc69 645520489 520489

我的程序计算出来的值为
A426393DB19B233562EC7E4FA5FA0B368B16E8E4

HMAC_MD5源码
void hmac_md5( unsigned char* text, /* pointer to data stream */
int text_len, /* length of data stream */
unsigned char* key, /* pointer to authentication key */
int key_len, /* length of authentication key */
unsigned char* digest /* caller digest to be filled in */
)

{
MD5_CTX context;
unsigned char k_ipad[65]; /* inner padding -
* key XORd with ipad
*/
unsigned char k_opad[65]; /* outer padding -
* key XORd with opad
*/
unsigned char tk[16];
int i;
/* if key is longer than 64 bytes reset it to 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;
}

/*
* the HMAC_MD5 transform looks like:
*
* MD5(K XOR opad, MD5(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected
*/

/* start out by storing key in pads */
memset(k_ipad, 0,sizeof(k_ipad));
memset(k_opad, 0,sizeof(k_opad));
memcpy(k_ipad,key,key_len);
memcpy(k_opad,key,key_len);



/* XOR key with ipad and opad values */
for (i=0; i<64; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/*
* perform inner MD5
*/
MD5Init(&context); /* init context for 1st * pass */
MD5Update(&context, k_ipad, 64); /* start with inner pad */
MD5Update(&context, text, text_len); /* then text of datagram */
MD5Final(digest, &context); /* finish up 1st pass */
/** perform outer MD5*/
MD5Init(&context); /* init context for 2nd * pass */
MD5Update(&context, k_opad, 64); /* start with outer pad */
MD5Update(&context, digest, 16); /* then results of 1st
* hash */
MD5Final(digest, &context); /* finish up 2nd pass */
}

这个是HMAC-SHA1的源码:

void hmac_SHA1( unsigned char* text, /* pointer to data stream */
int text_len, /* length of data stream */
unsigned char* key, /* pointer to authentication key */
int key_len, /* length of authentication key */
unsigned char* digest /* caller digest to be filled in */
)
{
SHA objSHA;

unsigned char k_ipad[64]; /* inner padding -
* key XORd with ipad
*/
unsigned char k_opad[64]; /* outer padding -
* key XORd with opad
*/
unsigned char tk[20];
int i;
/* if key is longer than 64 bytes reset it to key=SHA(key) */
if (key_len > SHA::DIGESTSIZE)
{
objSHA.Update(key, key_len);
objSHA.Final(tk);
key = tk;
key_len = 20;
}


memset(k_ipad, 0,sizeof(k_ipad));
memset(k_opad, 0,sizeof(k_opad));
memcpy(k_ipad,key,key_len);
memcpy(k_opad,key,key_len);



/* XOR key with ipad and opad values */
for (i=0; i<64; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/*
* perform inner SHA
*/

objSHA.Init(); /* init context for 1st * pass */
objSHA.Update(k_ipad, 64); /* start with inner pad */
objSHA.Update(text, text_len); /* then text of datagram */
objSHA.Final(digest); /* finish up 1st pass */
/** perform outer SHA*/
objSHA.Init(); /* init context for 2nd * pass */
objSHA.Update(k_opad, 64); /* start with outer pad */
objSHA.Update(digest, 16); /* then results of 1st* hash */
objSHA.Final(digest); /* finish up 2nd pass */
}



这个是为了实现HASH多态而采用的一般HMAC,可以更具HASH对象输出长度的不同而实现不同的HMAC算法
BOOL HMAC(HashBase* pobjBase,BYTE* pbText,DWORD dwTextLen,BYTE* pbKey,DWORD dwKeyLen,BYTE* byDigest,DWORD* pdwDigestLen)
{
if(!pobjBase ||
!pbText ||
!dwTextLen ||
!pbKey ||
!dwKeyLen ||
!byDigest ||
!pdwDigestLen)
{
return FALSE;
}

BYTE* pbIpad = 0;
BYTE* pbOpad = 0;
BYTE* pbCalcKey = 0;
DWORD dwHashSize = 0;
DWORD dwPadSize = 0;
DWORD dwRet = 0;


dwHashSize = pobjBase->DigestSize();
if(*pdwDigestLen < dwHashSize)
{
return FALSE;
}

do
{
if(!dwHashSize)
{
break;
}

dwPadSize = 64;//(dwHashSize<<2);
pbIpad = new BYTE [dwPadSize+1];
pbOpad = new BYTE [dwPadSize+1];
pbCalcKey = new BYTE [dwHashSize];
if(!pbIpad || !pbOpad || !pbCalcKey)
{
break;
}
memset(pbIpad, 0,dwPadSize+1);
memset(pbOpad, 0,dwPadSize+1);
memset(pbCalcKey, 0,dwHashSize);

if(dwKeyLen > dwHashSize)
{
pobjBase->CalculateDigest(pbCalcKey,pbKey,dwKeyLen);
dwKeyLen = dwHashSize;
}
else
{
memcpy(pbCalcKey,pbKey,dwKeyLen);
}

memcpy(pbIpad,pbCalcKey,dwKeyLen);
memcpy(pbOpad,pbCalcKey,dwKeyLen);


for (DWORD i=0; i<dwPadSize; i++)
{
pbIpad[i] ^= 0x36;
pbOpad[i] ^= 0x5c;
}

pobjBase->Update(pbIpad, dwPadSize);
pobjBase->Update(pbText, dwTextLen);
pobjBase->Final(byDigest);

pobjBase->Update(pbOpad, dwPadSize);
pobjBase->Update(byDigest, 16);
pobjBase->Final(byDigest);

*pdwDigestLen = dwHashSize;
dwRet = TRUE;
} while (0);

if(pbIpad)
{
delete pbIpad;
}
if(pbOpad)
{
delete pbOpad;
}
if(pbCalcKey)
{
delete pbCalcKey;
}

return dwRet;
}

望各位老鸟菜鸟一起参与进来。进来都是客。在这里先谢谢大家了!
...全文
1001 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
DarknessG 2013-06-17
  • 打赏
  • 举报
回复
楼主,能把HMAC-MD5和HMAC-SHA-1的源码发给我吗? 451586365@qq.com 谢谢〜
GuojwLokelly 2013-02-24
  • 打赏
  • 举报
回复
楼主,能把HMAC-MD5和HMAC-SHA-1的源码发给我吗,最近想研究下这个. 314908273@qq.com 谢谢!!!!
ps427 2012-08-21
  • 打赏
  • 举报
回复
楼主请把 HMAC-MD5和HMAC-SHA-1的源码发给我,比较研究下 再用。

284464830@qq.com
谢谢
ririhedou 2012-06-27
  • 打赏
  • 举报
回复
楼主可以将源代码发一下吗 410290995@qq.com 万分感谢!!!!!!!
lanyuhengji 2012-06-19
  • 打赏
  • 举报
回复
楼主能把源码发一份给我么拜谢了 zhuook@126.com
ewindfall 2012-05-04
  • 打赏
  • 举报
回复
楼主,发一份,谢谢。w9933885@foxmail.com
xiam068649 2012-02-15
  • 打赏
  • 举报
回复
我也想要一份HMAC-MD5和HMAC-SHA-1的源码,谢谢楼主,524046096@qq.com
imagewxg 2011-10-13
  • 打赏
  • 举报
回复
方便的话,请楼主将源码发给我,谢谢,imagewxg@163.com
mybbsall 2011-08-05
  • 打赏
  • 举报
回复
请楼主发一份HMAC-MD5和HMAC-SHA-1的源码发给我,谢谢! myxblog@sina.com
lkqibin 2011-03-04
  • 打赏
  • 举报
回复
楼主请把 HMAC-MD5和HMAC-SHA-1的源码发给我,比较研究下 再用。

lkqibin@yahoo.com.cn

谢谢
阿振 2010-11-16
  • 打赏
  • 举报
回复
听起来很悬乎,实际上就那么点东西,无非就是将密钥和HASH进行组合运算,即不同的密钥+不用的HASH算法,得到的HMAC算法则不一样,相对与一般的HASH算法来说多了一个输入的变因(即密钥)。HMAC实际上还是用的HASH算法,之前出错的原因是应为一直采用MD5去计算长度大于64的密钥,然而正确的做法是使用对应的HASH算法去计算,例如HMAC-SHA-1中就应该采用SHA去计算而不是MD5,反之在HMAC-MD5算法中就应该使用MD5去计算而不是SHA。不过这么多了在此结贴。至于源码方面有需要的朋友将邮箱贴下来。
xxcsf 2010-11-12
  • 打赏
  • 举报
回复
楼主,请问你这个算法是在什么平台上运行呀,我也是正在算HMAC-SHA1的算法,但现在还没有头序,这个与SHA-1的算法有相似的地方吗?
wokonglinglude 2010-11-10
  • 打赏
  • 举报
回复
顶一个 楼主自己解决了
阿振 2010-11-10
  • 打赏
  • 举报
回复
解决了,通过RFC2202的测试用例文档的测试用例和源码的参考。
这里贴上测试用例和源码
2. Test Cases for HMAC-MD5

test_case = 1
key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
key_len = 16
data = "Hi There"
data_len = 8
digest = 0x9294727a3638bb1c13f48ef8158bfc9d

test_case = 2
key = "Jefe"
key_len = 4
data = "what do ya want for nothing?"
data_len = 28
digest = 0x750c783e6ab0b503eaa86e310a5db738

test_case = 3
key = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
key_len 16
data = 0xdd repeated 50 times
data_len = 50
digest = 0x56be34521d144c88dbb8c733f0e8b3f6

test_case = 4
key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819
key_len 25
data = 0xcd repeated 50 times
data_len = 50
digest = 0x697eaf0aca3a3aea3a75164746ffaa79

test_case = 5
key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
key_len = 16
data = "Test With Truncation"
data_len = 20
digest = 0x56461ef2342edc00f9bab995690efd4c
digest-96 0x56461ef2342edc00f9bab995

test_case = 6
key = 0xaa repeated 80 times
key_len = 80
data = "Test Using Larger Than Block-Size Key - Hash Key First"
data_len = 54
digest = 0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd

test_case = 7
key = 0xaa repeated 80 times
key_len = 80
data = "Test Using Larger Than Block-Size Key and Larger
Than One Block-Size Data"
data_len = 73
digest = 0x6f630fad67cda0ee1fb1f562db3aa53e

3. Test Cases for HMAC-SHA-1

test_case = 1
key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
key_len = 20
data = "Hi There"
data_len = 8
digest = 0xb617318655057264e28bc0b6fb378c8ef146be00

test_case = 2
key = "Jefe"
key_len = 4
data = "what do ya want for nothing?"
data_len = 28
digest = 0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79

test_case = 3
key = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
key_len = 20
data = 0xdd repeated 50 times
data_len = 50
digest = 0x125d7342b9ac11cd91a39af48aa17b4f63f175d3

test_case = 4
key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819
key_len = 25
data = 0xcd repeated 50 times
data_len = 50
digest = 0x4c9007f4026250c6bc8414f9bf50c86c2d7235da

test_case = 5
key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
key_len = 20
data = "Test With Truncation"
data_len = 20
digest = 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04
digest-96 = 0x4c1a03424b55e07fe7f27be1

test_case = 6
key = 0xaa repeated 80 times
key_len = 80
data = "Test Using Larger Than Block-Size Key - Hash Key First"
data_len = 54
digest = 0xaa4ae5e15272d00e95705637ce8a3b55ed402112

test_case = 7
key = 0xaa repeated 80 times
key_len = 80
data = "Test Using Larger Than Block-Size Key and Larger
Than One Block-Size Data"
data_len = 73
digest = 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91
data_len = 20
digest = 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04
digest-96 = 0x4c1a03424b55e07fe7f27be1

test_case = 6
key = 0xaa repeated 80 times
key_len = 80
data = "Test Using Larger Than Block-Size Key - Hash Key
First"
data_len = 54
digest = 0xaa4ae5e15272d00e95705637ce8a3b55ed402112

test_case = 7
key = 0xaa repeated 80 times
key_len = 80
data = "Test Using Larger Than Block-Size Key and Larger
Than One Block-Size Data"
data_len = 73
digest = 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91

4. Security Considerations

This docuemnt raises no security issues. Discussion on the strength
of the HMAC construction can be found in [HMAC].

References

[HMAC] Krawczyk, H., Bellare, M., and R. Canetti,
"HMAC: Keyed-Hashing for Message Authentication",
RFC2104, February 1997.

[MD5] Rivest, R., "The MD5 Message-Digest Algorithm",
RFC1321, April 1992.

[SHA] NIST, FIPS PUB 180-1: Secure Hash Standard, April 1995.

[OG] Oehler, M., and R. Glenn,
"HMAC-MD5 IP Authentication with Replay Prevention",
RFC2085, February 1997.

[CG] Chang, S., and R. Glenn,
"HMAC-SHA IP Authentication with Replay Prevention",
Work in Progress.

Authors' Addresses

Pau-Chen Cheng
IBM T.J. Watson Research Center
P.O.Box 704
Yorktown Heights, NY 10598

EMail: pau@watson.ibm.com

Robert Glenn
NIST
Building 820, Room 455
Gaithersburg, MD 20899

EMail: rob.glenn@nist.gov

Appendix

This appendix contains the C reference code which implements HMAC-
SHA-1 using an existing SHA-1 library. It assumes that the SHA-1
library has similar API's as those of the MD5 code described in RFC
1321. The code for HMAC-MD5 is similar, just replace the strings
"SHA" and "sha" with "MD5" and "md5". HMAC-MD5 code is also listed in
RFC2104.

#ifndef SHA_DIGESTSIZE
#define SHA_DIGESTSIZE 20
#endif

#ifndef SHA_BLOCKSIZE
#define SHA_BLOCKSIZE 64
#endif

#ifndef MD5_DIGESTSIZE
#define MD5_DIGESTSIZE 16
#endif

#ifndef MD5_BLOCKSIZE
#define MD5_BLOCKSIZE 64
#endif

/* Function to print the digest */
void
pr_sha(FILE* fp, char* s, int t)
{
int i ;

fprintf(fp, "0x") ;
for (i = 0 ; i < t ; i++)
fprintf(fp, "%02x", s[i]) ;
fprintf(fp, "0) ;
}

void truncate
(
char* d1, /* data to be truncated */
char* d2, /* truncated data */
int len /* length in bytes to keep */
)
{
int i ;
for (i = 0 ; i < len ; i++) d2[i] = d1[i];
}

/* Function to compute the digest */
void
hmac_sha
(
char* k, /* secret key */
int lk, /* length of the key in bytes */
char* d, /* data */
int ld, /* length of data in bytes */
char* out, /* output buffer, at least "t" bytes */
int t
)
{
SHA_CTX ictx, octx ;
char isha[SHA_DIGESTSIZE], osha[SHA_DIGESTSIZE] ;
char key[SHA_DIGESTSIZE] ;
char buf[SHA_BLOCKSIZE] ;
int i ;

if (lk > SHA_BLOCKSIZE) {

SHA_CTX tctx ;

SHAInit(&tctx) ;
SHAUpdate(&tctx, k, lk) ;
SHAFinal(key, &tctx) ;

k = key ;
lk = SHA_DIGESTSIZE ;
}

/**** Inner Digest ****/

SHAInit(&ictx) ;

/* Pad the key for inner digest */
for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x36 ;
for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x36 ;

SHAUpdate(&ictx, buf, SHA_BLOCKSIZE) ;
SHAUpdate(&ictx, d, ld) ;

SHAFinal(isha, &ictx) ;

/**** Outter Digest ****/

SHAInit(&octx) ;

/* Pad the key for outter digest */

for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x5C ;
for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x5C ;

SHAUpdate(&octx, buf, SHA_BLOCKSIZE) ;
SHAUpdate(&octx, isha, SHA_DIGESTSIZE) ;

SHAFinal(osha, &octx) ;

/* truncate and print the results */
t = t > SHA_DIGESTSIZE ? SHA_DIGESTSIZE : t ;
truncate(osha, out, t) ;
pr_sha(stdout, out, t) ;

}

64,651

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧