本帖最后由 sky_yx 于 2015-12-30 14:23 编辑
算法描述
对md5算法简要的叙述可以为:md5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
在md5算法中,首先需要对信息进行填充,使其字节长度对512求余的结果等于448。因此,信息的字节长度(bits length)将被扩展至n*512+448,即n*64+56个字节(bytes),n为一个正整数。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后,在在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,现在的信息字节长度=n* 512+448+64=(n+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。
md5中有四个32位被称作链接变量(chaining variable)的整数参数,他们分别为:a=0x01234567,b=0x89 abcdef,c=0xfedcba98,d=0x76543210。
当设置好这四个链接变量后,就开始进入算法的四轮循环运算。循环的次数是信息中512位信息分组的数目。
将上面四个链接变量复制到另外四个变量中:a到a, b到b,c到c,d到d。
主循环有四轮(md4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向右环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a 、b、c或d中之一。
以一下是每次操作中用到的四个非线性函数(每轮一个)。
- 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))
复制代码 (&是与,|是或,~是非,^是异或)
这四个函数的说明:如果x、y和z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。
f是一个逐位运算的函数。即,如果x,那么y,否则z。函数h 是逐位奇偶操作符。
假设mj表示消息的第j个子分组(从0到15), <<
ff(a,b,c,d,mj,s,ti)表示a=b+((a+(f(b,c,d)+mj+ti) << gg(a,b,c,d,mj,s,ti)表示a=b+((a+(g(b,c,d)+mj+ti) << hh(a,b,c,d,mj,s,ti)表示a=b+((a+(h(b,c,d)+mj+ti) << ii(a,b,c,d,mj,s,ti)表示a=b+((a+(i(b,c,d)+mj+ti) <<
这四轮(64步)是:
第一轮
- ff(a,b,c,d,m0,7,0xd76aa478)
- ff(d,a,b,c,m1,12,0xe8c7b756)
- ff(c,d,a,b,m2,17,0x242070db)
- ff(b,c,d,a,m3, 22,0xc1bdceee)
- ff(a,b,c,d,m4,7,0xf57c0faf)
- ff(d,a,b,c,m5,12,0x4787c62a)
- ff(c,d,a,b,m6,17,0xa8304613)
- ff(b,c,d,a,m7,22,0xfd469501)
- ff(a,b,c,d,m8,7,0x698098d8)
- ff(d,a,b,c,m9,12,0x8b44f7af)
- ff(c,d,a,b,m10,17,0xffff5bb1)
- ff(b,c,d,a,m11,22,0x895cd7be)
- ff(a,b,c,d,m12,7,0x6b901122)
- ff(d,a,b,c,m13,12,0xfd987193)
- ff(c,d,a,b,m14,17,0xa679438e)
- ff(b,c,d,a,m15,22,0x49b40821)
复制代码 第二轮
- gg(a,b,c,d,m1,5,0xf61e2562)
- gg(d,a,b,c,m6,9,0xc040b340)
- gg(c,d,a,b,m11,14,0x265e5a51)
- gg(b,c,d,a,m0,20,0xe9b6c7aa)
- gg(a,b,c,d,m5,5,0xd62f105d)
- gg(d,a,b,c,m10,9,0x02441453)
- gg(c,d,a,b,m15,14,0xd8a1e681)
- gg(b,c,d,a,m4,20,0xe7d3fbc8)
- gg(a,b,c,d,m9,5,0x21e1cde6)
- gg(d,a,b,c,m14,9,0xc33707d6)
- gg(c,d,a,b,m3,14,0xf4d50d87)
- gg(b,c,d,a,m8,20,0x455a14ed)
- gg(a,b,c,d,m13,5,0xa9e3e905)
- gg(d,a,b,c,m2,9,0xfcefa3f8)
- gg(c,d,a,b,m7,14,0x676f02d9)
- gg(b,c,d,a,m12,20,0x8d2a4c8a)
复制代码 第三轮
- hh(a,b,c,d,m5,4,0xfffa3942)
- hh(d,a,b,c,m8,11,0x8771f681)
- hh(c,d,a,b,m11,16,0x6d9d6122)
- hh(b,c,d,a,m14,23,0xfde5380c)
- hh(a,b,c,d,m1,4,0xa4beea44)
- hh(d,a,b,c,m4,11,0x4bdecfa9)
- hh(c,d,a,b,m7,16,0xf6bb4b60)
- hh(b,c,d,a,m10,23,0xbebfbc70)
- hh(a,b,c,d,m13,4,0x289b7ec6)
- hh(d,a,b,c,m0,11,0xeaa127fa)
- hh(c,d,a,b,m3,16,0xd4ef3085)
- hh(b,c,d,a,m6,23,0x04881d05)
- hh(a,b,c,d,m9,4,0xd9d4d039)
- hh(d,a,b,c,m12,11,0xe6db99e5)
- hh(c,d,a,b,m15,16,0x1fa27cf8)
- hh(b,c,d,a,m2,23,0xc4ac5665)
复制代码 第四轮
- ii(a,b,c,d,m0,6,0xf4292244)
- ii(d,a,b,c,m7,10,0x432aff97)
- ii(c,d,a,b,m14,15,0xab9423a7)
- ii(b,c,d,a,m5,21,0xfc93a039)
- ii(a,b,c,d,m12,6,0x655b59c3)
- ii(d,a,b,c,m3,10,0x8f0ccc92)
- ii(c,d,a,b,m10,15,0xffeff47d)
- ii(b,c,d,a,m1,21,0x85845dd1)
- ii(a,b,c,d,m8,6,0x6fa87e4f)
- ii(d,a,b,c,m15,10,0xfe2ce6e0)
- ii(c,d,a,b,m6,15,0xa3014314)
- ii(b,c,d,a,m13,21,0x4e0811a1)
- ii(a,b,c,d,m4,6,0xf7537e82)
- ii(d,a,b,c,m11,10,0xbd3af235)
- ii(c,d,a,b,m2,15,0x2ad7d2bb)
- ii(b,c,d,a,m9,21,0xeb86d391)
复制代码 常数ti 可以如下选择:
在第i步中,ti是4294967296*abs(sin(i))的整数部分,i的单位是弧度。(4294967296等于2的32次方)
所有这些完成之后,将a、b、c、d分别加上a、b、c、d。然后用下一分组数据继续运行算法,最后的输出是a、b、c和d的级联。
当你按照我上面所说的方法实现md5算法以后,你可以用以下几个信息对你做出来的程序作一个简单的测试,看看程序有没有错误。
- md5 ("") = d41d8cd98f00b204e9800998ecf8427e
- md5 ("a") = 0cc175b9c0f1b6a831c399e269772661
- md5 (" abc") = 900150983cd24fb0d6963f7d28e17f72
- md5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
- md5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496 cca67e13b
- md5 ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz 0123456789") =
- d174ab98d277d9f5a5611c2c9f419d9f
- md5 (" 123456789012345678901234567890123456789012345678901234567890123456789
- 01234567890") = 57edf4a22be3c955ac49da2e2107b67a
复制代码 如果你用上面的信息分别对你做的md5算法实例做测试,最后得出的结论和标准答案完全一样,那我就要在这里象你道一声祝贺了。要知道,我的程序在第一次编译成功的时候是没有得出和上面相同的结果的。
md5的安全性
md5相对md4所作的改进:
1. 增加了第四轮;
2. 每一步均有唯一的加法常数;
3. 为减弱第二轮中函数g的对称性从(x&y)|(x&z)|(y&z) 变为(x&z)|(y&(~z));
4. 第一步加上了上一步的结果,这将引起更快的雪崩效应;
5. 改变了第二轮和第三轮中访问消息子分组的次序,使其更不相似;
6. 近似优化了每一轮中的循环左移位移量以实现更快的雪崩效应。各轮的位移量互不相同。
|