md5的输入为512位的倍数,输出为128位。
首先填充消息,使其长度为与448模512同余,即长度为512的倍数减64。填充的消息第一位为1,之后全部为0。
需要注意的是,即使原消息长度刚好为与448模512同余,仍需要填充;即使原消息长度刚好为512的整数倍,仍需要填充。
再将这剩余64位填充为原来消息的长度(二进制),若是原来消息的长度大于64位(2的64次方),如原消息的长度为70位(2的70次方),则忽略高6位的数据,只填充低64位(即长度L mod 2的64次方)。
之后序列长度就为512的倍数了,这里每一个512位称为一个分组,又将每一个512为分为16个32位,称为一个子分组(M0~M15)。
之后进行4轮运算,每一轮进行16次操作,分别针对这16个子分组。
原消息有几个分组就行进几次循环,循环这4轮运算,每次循环需要一个128位序列当“种子”,之后输出一个128位的序列,这个序列与下一分组继续作用产生下一次的128位输出。第一次循环时128位序列初始化为4个32(十六进制)位变量:A=01234567h;B=89abcdefh;C=fedcba98h;D=76543210h,注意这些变量在内存中的顺序是低值存放低字节,所以在程序中应该是:A=0x67452301;B=0xefcdab89;C=0x98badcfe;D=0x10325476.最后的一个分组产生的128位输出进行逆操作即为最终输出。(有点拗口,可以对照图片,或看代码...)
下面来具体说说每次循环的4轮运算。
这四轮运算需要用到一个常数表,这些常数T[i](i=1~64)等于4294967296*abs(sin(i))所得结果的整数部分,其中i用弧度表示。这样做是为了通过正弦函数和幂函数来进一步消除变换中的线性。
T[1] | 0xd76aa478 |
T[2] |
0xe8c7b756 |
T[3] |
0x242070db |
T[4] |
0xc1bdceee |
T[5] |
0xf57c0faf |
T[6] |
0x4787c62a |
T[7] |
0xa8304613 |
T[8] |
0xfd469501 |
T[9] |
0x698098d8 |
T[10] |
0x8b44f7af |
T[11] |
0xffff5bb1 |
T[12] |
0x895cd7be |
T[13] |
0x6b901122 |
T[14] |
0xfd987193 |
T[15] |
0xa679438e |
T[16] |
0x49b40821 |
T[17] |
0xf61e2562 |
T[18] |
0xc040b340 |
T[19] |
0x265e5a51 |
T[20] |
0xe9b6c7aa |
T[21] |
0xd62f105d |
T[22] |
0x02441453 |
T[23] |
0xd8a1e681 |
T[24] |
0xe7d3fbc8 |
T[25] |
0x21e1cde6 |
T[26] |
0xc33707d6 |
T[27] |
0xf4d50d87 |
T[28] |
0x455a14ed |
T[29] |
0xa9e3e905 |
T[30] |
0xfcefa3f8 |
T[31] |
0x676f02d9 |
T[32] |
0x8d2a4c8a |
T[33] |
0xfffa3942 |
T[34] |
0x8771f681 |
T[35] |
0x6d9d6122 |
T[36] |
0xfde5380c |
T[37] |
0xa4beea44 |
T[38] |
0x4bdecfa9 |
T[39] |
0xf6bb4b60 |
T[40] |
0xbebfbc70 |
T[41] |
0x289b7ec6 |
T[42] |
0xeaa127fa |