关于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;
}
望各位老鸟菜鸟一起参与进来。进来都是客。在这里先谢谢大家了!