一、说一说概念
数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名、数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密。数据摘要算法也被称为哈希(Hash)算法、散列算法。MD是应用非常广泛的一个算法家族,尤其是 MD5(Message-Digest Algorithm 5,消息摘要算法版本5),它由MD2、MD3、MD4发展而来,由Ron Rivest(RSA公司)在1992年提出,被广泛应用于数据完整性校验、数据(消息)摘要、数据加密等。MD2、MD4、MD5 都产生16字节(128位)的校验值,一般用32位十六进制数表示。MD2的算法较慢但相对安全,MD4速度很快,但安全性下降,MD5比MD4更安全、速度更快。在互联网上进行大文件传输时,都要得用MD5算法产生一个与文件匹配的、存储MD5值的文本文件(后缀名为 .md5或.md5sum),这样接收者在接收到文件后,就可以利用与 SFV 类似的方法来检查文件完整性,绝大多数大型软件公司或开源组织都是以这种方式来校验数据完整性,而且部分操作系统也使用此算法来对用户密码进行加密,另外,它也是目前计算机犯罪中数据取证的最常用算法。
二:MD5的原理
对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
- 第一步、填充
把待做摘要的数据转成2进制形式,把它的长度对512取余数。如果结果不等于448,则需要用填充1或0来使其满足格式。填充的规则就是填充1个1和n个0。填充完成后待做摘要算法的数据的长度就为N*512+448(bit); - 第二步、记录信息长度
用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。 - 第三步、装入标准的幻数(四个整数)
说白了就是4个常量(都是16进制的呀):
A=01234567
B=89ABCDEF
C=FEDCBA98
D=76543210
然后把它们赋值个4个变量a,b,c,d
即
a=A;
b=B;
c=C;
d=D; - 第四步、四轮循环运算
1) 首先介绍下运算中会用到的函数:
F(X,Y,Z)=(X&Y)|((~X)&Z)
G(X,Y,Z)=(X&Z)|(Y&(~Z))
H(X,Y,Z)=X^Y^Z
I(X,Y,Z)=Y^(X|(~Z))
看函数没啥可说的 与或非等二进制运算。
2)还记得上面所说的数据要分成512个字节为一组的数据块吗?
取出一块来把它分成16份 ,每份就是64位(8字节),并把它们编号为M0~M115。
3)接下来开始操作了。操作函数如下:
拿FF操作为例讲解参数,FF(a,b,c,d,Mj,s,ti) 其中a,b,c,d 就是上面讲的常量。
因为有4个操作函数 M又有16块 所以要运行4轮 每轮运行16次.最后会获得新的a,b,c,d.(四轮运算 如下)。
4)四轮运算
第一轮
a=FF(a,b,c,d,M0,7,0xd76aa478)
b=FF(d,a,b,c,M1,12,0xe8c7b756)
c=FF(c,d,a,b,M2,17,0x242070db)
d=FF(b,c,d,a,M3,22,0xc1bdceee)
a=FF(a,b,c,d,M4,7,0xf57c0faf)
b=FF(d,a,b,c,M5,12,0x4787c62a)
c=FF(c,d,a,b,M6,17,0xa8304613)
d=FF(b,c,d,a,M7,22,0xfd469501)
a=FF(a,b,c,d,M8,7,0x698098d8)
b=FF(d,a,b,c,M9,12,0x8b44f7af)
c=FF(c,d,a,b,M10,17,0xffff5bb1)
d=FF(b,c,d,a,M11,22,0x895cd7be)
a=FF(a,b,c,d,M12,7,0x6b901122)
b=FF(d,a,b,c,M13,12,0xfd987193)
c=FF(c,d,a,b,M14,17,0xa679438e)
d=FF(b,c,d,a,M15,22,0x49b40821)
第二轮
a=GG(a,b,c,d,M1,5,0xf61e2562)
b=GG(d,a,b,c,M6,9,0xc040b340)
c=GG(c,d,a,b,M11,14,0x265e5a51)
d=GG(b,c,d,a,M0,20,0xe9b6c7aa)
a=GG(a,b,c,d,M5,5,0xd62f105d)
b=GG(d,a,b,c,M10,9,0x02441453)
c=GG(c,d,a,b,M15,14,0xd8a1e681)
d=GG(b,c,d,a,M4,20,0xe7d3fbc8)
a=GG(a,b,c,d,M9,5,0x21e1cde6)
b=GG(d,a,b,c,M14,9,0xc33707d6)
c=GG(c,d,a,b,M3,14,0xf4d50d87)
d=GG(b,c,d,a,M8,20,0x455a14ed)
a=GG(a,b,c,d,M13,5,0xa9e3e905)
b=GG(d,a,b,c,M2,9,0xfcefa3f8)
c=GG(c,d,a,b,M7,14,0x676f02d9)
d=GG(b,c,d,a,M12,20,0x8d2a4c8a)
第三轮
a=HH(a,b,c,d,M5,4,0xfffa3942)
b=HH(d,a,b,c,M8,11,0x8771f681)
c=HH(c,d,a,b,M11,16,0x6d9d6122)
d=HH(b,c,d,a,M14,23,0xfde5380c)
a=HH(a,b,c,d,M1,4,0xa4beea44)
b=HH(d,a,b,c,M4,11,0x4bdecfa9)
c=HH(c,d,a,b,M7,16,0xf6bb4b60)
d=HH(b,c,d,a,M10,23,0xbebfbc70)
a=HH(a,b,c,d,M13,4,0x289b7ec6)
b=HH(d,a,b,c,M0,11,0xeaa127fa)
c=HH(c,d,a,b,M3,16,0xd4ef3085)
d=HH(b,c,d,a,M6,23,0x04881d05)
a=HH(a,b,c,d,M9,4,0xd9d4d039)
b=HH(d,a,b,c,M12,11,0xe6db99e5)
c=HH(c,d,a,b,M15,16,0x1fa27cf8)
d=HH(b,c,d,a,M2,23,0xc4ac5665)
第四轮
a=II(a,b,c,d,M0,6,0xf4292244)
b=II(d,a,b,c,M7,10,0x432aff97)
c=II(c,d,a,b,M14,15,0xab9423a7)
d=II(b,c,d,a,M5,21,0xfc93a039)
a=II(a,b,c,d,M12,6,0x655b59c3)
b=II(d,a,b,c,M3,10,0x8f0ccc92)
c=II(c,d,a,b,M10,15,0xffeff47d)
d=II(b,c,d,a,M1,21,0x85845dd1)
a=II(a,b,c,d,M8,6,0x6fa87e4f)
b=II(d,a,b,c,M15,10,0xfe2ce6e0)
c=II(c,d,a,b,M6,15,0xa3014314)
d=II(b,c,d,a,M13,21,0x4e0811a1)
a=II(a,b,c,d,M4,6,0xf7537e82)
b=II(d,a,b,c,M11,10,0xbd3af235)
c=II(c,d,a,b,M2,15,0x2ad7d2bb)
d=II(b,c,d,a,M9,21,0xeb86d391)
5)每轮循环后,都会获得新的a,b,c,d.作如下操作获得新的A,B,C,D。
A=A+a;
B=B+b;
C=C+c;
D=D+d;
如果上面最开始的数据块未用完 则把最新的A、B、C、D重新赋值给a、b、c、d。重复上面的运算。直到没有剩下的数据块为止。
6)将最后生成的A,B,C,D级联,A为低位,D为高位。最终生成一个128位的值,即是摘要值。
三、代码实例
package util;
import java.security.MessageDigest;
public class MD {
/**
* @Title : encodeMD2
* @Description : MD2消息摘要
* @return : byte[] 返回类型
* @throws
*/
public static byte[] encodeMD2(byte[] data) throws Exception{
//初始化MessageDigest
MessageDigest md = MessageDigest.getInstance("MD2");
//执行消息摘要
return md.digest(data);
}
/**
* @Title : encodeMD5
* @Description : md5消息摘要
* @return : byte[] 返回类型
* @throws
*/
public static byte[] encodeMD5(byte[] data)throws Exception{
//初始化MessageDigest
MessageDigest md = MessageDigest.getInstance("MD5");
//执行消息摘要
return md.digest(data);
}
}
package test;
import static org.junit.Assert.*;
import org.junit.Test;
import util.MD;
public class MDTest {
@Test
public final void testEncodeMD2() throws Exception{
String str = "MD2消息摘要";
//获得消息摘要
byte[] data1 = MD.encodeMD2(str.getBytes());
byte[] data2 = MD.encodeMD2(str.getBytes());
//校验
assertArrayEquals(data1,data2);
}
@Test
public final void testEncodeMD5() throws Exception{
String str = "MD5消息摘要";
//获得消息摘要
byte[] data1 = MD.encodeMD5(str.getBytes());
byte[] data2 = MD.encodeMD5(str.getBytes());
//校验
assertArrayEquals(data1,data2);
}
}
参考视频:
天空乐园CCIE系列-第9集-HASH算法原理和分析
http://www.tudou.com/programs/view/FZWv882kq30/
参考其他网络资源:
http://noalgo.info/600.html
百度百科:摘要算法 等。