1.HMAC算法
HMAC是一種基於Hash函數和密鑰進行消息認證的方法,通過這個算法可以保證通信雙方之前交互的消息來自對方並且沒有被篡改。
HMAC的作用:
[1]可以保證消息不被篡改,因為有Hash算法來保證。
[2]認證信源身份,因為有密鑰來保證。
即所謂HMAC算法就是通過提供一個Hash函數,一個key,一個字符串來計算出一個值。通信雙方約定好key之后,雙方各自使用這個算法交換算法結果來保證雙方之前交互過的消息來自對方並且沒有被篡改。
很明顯HMAC算法的輸入是:消息+key,並且提供一個Hash函數(例如MD5)。輸出就是一個字符串(如果是MD5,則這個字符串長度是16字節,如果是SHA1則是20字節)。
示例:ssl握手的最后一步,客戶端把握手的所有消息使用HMAC算法計算出一個值發送給服務器,服務器也做同樣的操作發送給客戶端。兩端通過比較自己的值和收到的值,來保證ssl握手時的消息沒有被篡改。
2.HMAC-MD5算法
HMAC-MD5算法就是HMAC算法的一個特例,即用md5作為HMAC的Hash函數。
計算流程:
(1) 在密鑰key后面添加0來創建一個長為B(64字節)的字符串(str),如果key超過64字節則使用key的md5代替key,再在后面加0補齊64字節。
(2) 將上一步生成的字符串(str)與ipad(0x36)做異或運算,形成結果字符串(istr)。
(3) 將數據流data附加到第二步的結果字符串(istr)的末尾。
(4) 做md5運算於第三步生成的數據流(istr)。
(5) 將第一步生成的字符串(str) 與opad(0x5c)做異或運算,形成結果字符串(ostr)。
(6) 再將第四步的結果(istr) 附加到第五步的結果字符串(ostr)的末尾(7) 做md5運算於第6步生成的數據流(ostr),最終輸出結果(out)。
3.HMAC-MD5算法實現
int hmac_md5(unsigned char *key, int key_len, unsigned char *data, int data_len, unsigned char *out, int olen)
{
unsigned i;
unsigned char tk[64],tktemp[64];
unsigned char *p;
// 如果密鑰長度大於64,使用key的md5值替換key
if(key_len > 64){
md5(key, key_len, tktemp);
key_len = 16;
}else{
memcpy(tktemp, key, key_len);
}
p = (unsigned char *)malloc(64 + (data_len > 16 ?(data_len):16));
if(NULL == p)
return -1;
// key后面置0,補齊64個字節
lite_proxy_memcpy(p, tktemp, key_len);
lite_proxy_memset(p+key_len,0,64-key_len);
//與0x36相異或
for(i=0; i<64; i++)
p[i]^=0x36;
memcpy(p+64, data, data_len);
md5(p, 64+data_len, tk);
lite_proxy_memcpy(p,tktemp,key_len);
lite_proxy_memset(p+key_len,0,64-key_len);
/*與0x5c異或*/
for(i=0; i<64; i++)
p[i]^=0x5c;
memcpy(p+64, tk, 16);
md5(p, 64+16, out);
free(p);
return 0;
}
4.問題
[1]HMAC的作用是保證之前交互的消息沒有被篡改並且來自對方(key來保證)。因此對於ssl,客戶端和服務器可以把(握手的消息+key)做md5,直接使用md5算法來代替HMAC-MD5算法,為什么ssl協議沒有這么做。
其實把(握手的消息+key)做md5,這個已經接近HMAC算法,因為HMAC算法就是把key混到data里面做一系列運算。只不過這一系列運算(HMAC)得到的結果比直接(握手的消息+key)做md5結果更加安全。
這也說明HMAC算法的本質就是md5(數據+key)。