MD5
概述
MD5是一种广泛引用的密码散列函数,用于为任意长度的数据产生一个固定长128bits(16 bytes)的散列值,来确保信息传输的一致性.
MD5于1992年公开,用以取代MD4算法.
算法过程
1.数据填充
MD5和MD4的数据填充相同.
MD5可以对任意长度的数据进行散列,在算法之前需要对数据进行填充,使其位长度(bits)对512(64 bytes)求余的结果为448(56 bytes).即最后需要空出64bits(8 bytes),这8字节用于填充长度信息,因此最终结果对齐到512bits.
填充步骤如下:
- 在原始信息的末尾填充一个
1和若干个0,直到满足上述求余结果. - 在第
1步结果的后面附加一个64bits长度的数据(其值为原始信息的长度信息,单位为bit),如果长度信息超过64bits,则取低64位.
注意:
- 填充数据应该使用
小端序进行处理,包括原始数据和64bits的长度信息. - 最终的结果是512bits对齐的,即每个分组为512bits.
- 后续说的
1字(1-word)代表4字节,即32-bits.
2.初始化MD缓冲区
MD5使用4个缓冲区,命名为A,B,C,D.每个缓冲区均为32bits,以小端序储存:
1 | word A: 01 23 45 67 |
由于以小端序存储,因此在C程序中应该为如下程序:
1 |
3.处理分组数据
每521bits(即64-bytes/16-words)数据为一组,每个分组单独进行处理.
注意:仍然以小端序进行处理.
四个辅助非线性函数F,G,H,I
首先定义四个辅助函数:
1 | F( X ,Y ,Z ) = ( X & Y ) | ( (~X) & Z ) |
其中,F为"如果X则Y,否则Z; H为"诸位异或"或称之为"奇偶校验".
四个函数FF,GG,HH,II
定义如下:
1 | FF(a ,b ,c ,d ,Mj ,s ,ti ): a = b + ( (a + F(b,c,d) + Mj + ti) <<< s) |
其中,<<<代表循环左移.
表T
如下是后面要用到的T表:
1 | static const uint32_t T[64] = { |
主循环
该步骤使用一个有64个元素的表T[0...63],该表的每个元素T[i]的值为的整数部分. 即T[i] = int(sin(i) * pow(2,32)),可以硬编码进程序,表如前所述.
将每个分组(512-bits/64bytes)分为16个子分组(4-bytes),即M[0...15]
首先需要将四个缓冲区A,B,C,D复制到另外的四个位置AA,BB,CC,DD:
1 | AA = A |
注意在第一个分组处理之前,A,B,C,D已被初始化.
主循环处理每个16-WORDs的分组,共有四个轮次(ROUND),每个轮次都很相似,执行四轮操作:
1 | /* ROUND 1 */ |
然后,四个缓冲区(寄存器): A,B,C,D增加其原来的值:
1 | A = A + AA |
到此,一轮主循环结束,如此逐个使用每个16-WORDs分组执行以上算法.
输出结果
最终输出的结果即为四个缓冲区的值A,B,C,D的级联,共128-bits,一般将其转换为16进制表示.
注意: 输出时,从A的低字节开始,到D的高字节结束,即小端序.(?)

