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的高字节结束,即小端序
.(?)