hmac md5 java_HMAC-MD5算法原理及实现

如果要通过同一个渠道发送数据和散列值的话(比如消息认证码),就要考虑数据和MD5同时被篡改的问题,如果第三方修改了数据,然后进行MD5散列,并一块发给接收方,接收方并不能察觉到数据被篡改。HMAC-MD5就可以用一把发送方和接收方都有的key进行计算,而没有这把key的第三方是无法计算出正确的散列值的,这样就可以防止数据被篡改。

以下是分析节选,对于更详细的描述可以查阅RFC2104文档。

HMAC需要一个加密用散列函数(表示为H)和一个密钥K。

假设H是一个将数据块用一个基本的迭代压缩函数来加密的散列函数。

用B来表示数据块的长。(以上说提到的散列函数的分割数据块长B=64),用L来表示散列函数的输出数据长(MD5中L=16,SHA—1中L=20)。

密钥的长度可以是小于等于数据块长的任何正整数值。应用程序中使用的密钥长度若是比B大,则首先用使用散列 函数H作用于它,然后用H输出的L长度字符串作为在HMAC中实际使用的密钥。

一般情况下,推荐的最小密钥K长度是L长。(与H的输出数据长度相等)。 我们将定义两个固定且不同的字符串ipad,opad:

ipad = the byte 0x36 repeated B times

opad = the byte 0x5C repeated B times

#计算‘text'的HMAC:

H( K XOR opad, H(K XOR ipad, text))

即为以下步骤:

(1) append zeros to the end of K to create a B byte string

(e.g., if K is of length 20 bytes and B=64, then K will be

appended with 44 zero bytes 0x00)

(2) XOR (bitwise exclusive-OR) the B byte string computed in step

(1) with ipad

(3) append the stream of data 'text' to the B byte string resulting

from step (2)

(4) apply H to the stream generated in step (3)

(5) XOR (bitwise exclusive-OR) the B byte string computed in

step (1) with opad

(6) append the H result from step (4) to the B byte string

resulting from step (5)

(7) apply H to the stream generated in step (6) and output

the result

void hmac_md5(char* out, char* data, int dlen, char* key, int klen)

{

(1) 在密钥key后面添加0来创建一个长为B(64字节)的字符串(str)。

(2) 将上一步生成的字符串(str)与ipad(0x36)做异或运算,形成结果字符串(istr)。

(3) 将数据流data附加到第二步的结果字符串(istr)的末尾。

(4) 做md5运算于第三步生成的数据流(istr)。

(5) 将第一步生成的字符串(str)与opad(0x5c)做异或运算,形成结果字符串(ostr)。

(6) 再将第四步的结果(istr)附加到第五步的结果字符串(ostr)的末尾。

(7) 做md5运算于第六步生成的数据流(ostr),输出最终结果(out)。

}

#注:如果第一步中,key的长度klen大于64字节,则先进行md5运算,使其长度klen=16字节。

PHP实现:

function custom_hmac($algo, $data, $key, $raw_output = false)

{

$algo = strtolower($algo);

$pack = 'H'.strlen($algo('test'));

$size = 64;

$opad = str_repeat(chr(0x5C), $size);

$ipad = str_repeat(chr(0x36), $size);

if (strlen($key) > $size) {

$key = str_pad(pack($pack, $algo($key)), $size, chr(0x00));

} else {

$key = str_pad($key, $size, chr(0x00));

}

for ($i = 0; $i < strlen($key) - 1; $i++) {

$opad[$i] = $opad[$i] ^ $key[$i];

$ipad[$i] = $ipad[$i] ^ $key[$i];

}

$output = $algo($opad.pack($pack, $algo($ipad.$data)));

return ($raw_output) ? pack($pack, $output) : $output;

}

?>

Example Use:

custom_hmac('sha1', 'Hello, world!', 'secret', true);

?>

Java 实例:

public static String hmacSha1(String value, String key) {

try {

// Get an hmac_sha1 key from the raw key bytes

byte[] keyBytes = key.getBytes();

SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");

// Get an hmac_sha1 Mac instance and initialize with the signing key

Mac mac = Mac.getInstance("HmacSHA1");

mac.init(signingKey);

// Compute the hmac on input data bytes

byte[] rawHmac = mac.doFinal(value.getBytes());

// Convert raw bytes to Hex

byte[] hexBytes = new Hex().encode(rawHmac);

// Covert array of Hex bytes to a String

return new String(hexBytes, "UTF-8");

} catch (Exception e) {

throw new RuntimeException(e);

}

}


版权声明:本文为weixin_32715971原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。