MD5和SHA-1都被称作哈希(Hash)函数,用过Java语言的人对这个术语应该相当熟悉。Java类库里的Object类定义了hashCode这个函数,但是java的概念略有不同。正式的哈希函数的定义是“把任意长度的数据计算成固定长度的数据”。也就是说函数的输入是任意长的,输出总是固定长度的。MD5和SHA-1是两种加密用哈希函数,MD5的返回值总是128bit的,SHA-1的返回值是160bit,都是固定长度。MD5如果按十六进制表示的话是32位十六进制的数,SHA-1是40位十六进制的数。 你输入任意长度的字符串,都会返回给你相应固定长度的十六进制返回值。这两个函数的返回值都被称为信息摘要(Message Digest,实际上MD就是Message Digest的缩写)。 那么两个函数为什么可以用在加密上呢?因为他们都有这几个特性: 1.都是“不可逆”的函数。不存在一个算法能够由哈希值倒算出原始信息。 2.对原始信息的任何一点改变都会导致结果的哈希值巨大的不同。举个例子,假如原始数据是几百万字的文章,你在其中哪怕改动一个标点,计算出的哈希值都会有很大的变化。 3.运算代价是相对较低的。普通的AMDOpteron2.2GHz的芯片,每秒可以计算出335MB数据的MD5值,可以计算192MB数据的SHA-1值。 参见https://en.wikipedia.org/wiki/SHA-1#Comparison_of_SHA_functions。 4.类似于1,除非通过蛮力的穷举法,否则无法找到两段不同的信息而有相同的哈希值。(这一点现在已被证明是不成立的了,请看后文) 那么这两个函数的特点在哪里呢?特点在于都能“通过哈希值唯一标识原信息”。这个怎么讲,就是比如原始信息是A,我知道原始信息的哈希值Ha,如果我有另一段信息,这段信息的哈希值也是Ha的话,我就能“以极大的可靠性”断定这另一段信息就是A。也就是说哈希值能“唯一”标识原始信息。原因是什么呢?

1.两段不同信息“碰巧”有着相同的哈希值的概率是很低的,对于MD5来说是2的128次方分之一,这个数字是多小呢:太阳的表面积是6万亿平方公里,一个原子的截面积大约是1平方纳米,假设你是一个原子,把你放在56个太阳中任意一个的表面,这个概率是我在这56个太阳上随意指定一点,正好点中你的概率,而你是一个小小小的原子。对SHA-1来说,这个概率就更低了。 2.那么有没有办法人工伪造一段信息正好有Ha这个哈希值呢?根据上面的1和4,这个可能性是很低的,要通过穷举法的巨大的运算量才能做到。

他们的用处

1.密码加密 2.文件校验 ***

MD5相当于超损压缩。其算法过程如下

对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

1.填充:如果输入信息的长度(bit)对512求余的结果不等于448,就需要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0。填充完后,信息的长度就为N512+448(bit); 2.记录信息长度:用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N512+448+64=(N+1)*512位。 3.装入标准的幻数(四个整数):标准的幻数(物理顺序)是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定义应该是: (A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有点晕哈,其实想一想就明白了。 4.四轮循环运算:循环的次数是分组的个数(N+1) 1.将每一512字节细分成16个小组,每个小组64位(8个字节) 2.先认识四个线性函数(&是与,|是或,~是非,^是异或)

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))

3.设Mj表示消息的第j个子分组(从0到15) FF(a,b,c,d,Mj,s,ti)表示a=b+((a+F(b,c,d)+Mj+ti)«<s) GG(a,b,c,d,Mj,s,ti)表示a=b+((a+G(b,c,d)+Mj+ti)«<s) HH(a,b,c,d,Mj,s,ti)表示a=b+((a+H(b,c,d)+Mj+ti)«<s) II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(b,c,d)+Mj+ti)«<s) 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,然后进入下一循环。