0x00 前言
0x01 填充信息
2.如果大小(长度)满足 mod 512 == 448 mod 512,就在文件(消息)的末尾处添加64位(8字节)的值,值的内容是原消息的长度(以位为单位)
67 6E 75 62 64 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 00 00 00 00 00 00 00
注意到最后面这里有个0x28,数8个字节,就是0x0000000000000028,刚刚好是十进制的40,消息的内容是5个字节,也就是40位,还要注意到这里是小端字节序存储
0x02 数据说明
填充信息满足要求后就要开始计算MD5值了,首先先把需要的东西先列出来:
DWORD md5::A = 0x; DWORD md5::B = 0xEFCDAB89; DWORD md5::C = 0x98BADCFE; DWORD md5::D = 0x; DWORD md5::T[64] = { 0xD76AA478,0xE8C7B756,0xDB,0xC1BDCEEE,0xF57C0FAF,0x4787C62A,0xA,0xFD, 0xD8,0x8B44F7AF,0xFFFF5BB1,0x895CD7BE,0x6B,0xFD,0xAE,0x49B40821, 0xF61E2562,0xC040B340,0x265E5A51,0xE9B6C7AA,0xD62F105D,0x0,0xD8A1E681,0xE7D3FBC8, 0x21E1CDE6,0xC33707D6,0xF4D50D87,0x455A14ED,0xA9E3E905,0xFCEFA3F8,0x676F02D9,0x8D2A4C8A, 0xFFFA3942,0x8771F681,0x6D9D6122,0xFDE5380C,0xA4BEEA44,0x4BDECFA9,0xF6BB4B60,0xBEBFBC70, 0x289B7EC6,0xEAA127FA,0xD4EF3085,0x04881D05,0xD9D4D039,0xE6DB99E5,0x1FA27CF8,0xC4AC5665, 0xF,0x432AFF97,0xAB9423A7,0xFC93A039,0x655B59C3,0x8F0CCC92,0xFFEFF47D,0x85845DD1, 0x6FA87E4F,0xFE2CE6E0,0xA,0x4E0811A1,0xF7537E82,0xBD3AF235,0x2AD7D2BB,0xEB86D391 }; DWORD md5::s[64]={ 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21 }; DWORD md5::m[64]={ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12, 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2, 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 };
A = 0x0 B = 0x89ABCDEF C = 0xFEDCBA89 D = 0x
为了保证ABCD4个值在内存中的显示情况为上面情况,所以要调整数字的位置,故实际情况是:
A = 0x; B = 0xEFCDAB89; C = 0x98BADCFE; D = 0x;
0x03 处理信息
经过信息填充后,填充后的信息长度肯定是512位(64字节)的倍数,也就是说每512位(64字节)为1段可以分成n段,(n大于等于1),对于每一段信息(512位,64字节)又划分成16小段(每段32位,4个字节,用M表示)
for(i = 0; i < 4; ++i) {
FF(16); //括号内为执行次数 GG(16); HH(16); II(16); }
函数的内容分别是:
void md5::FF(DWORD &a,DWORD &b,DWORD &c,DWORD &d,DWORD mj,DWORD s,DWORD ti){
DWORD temp = F(b,c,d) + a + mj + ti; temp = (temp<<s)|(temp>>(32-s)); a = b + temp; } void md5::GG(DWORD &a,DWORD &b,DWORD &c,DWORD &d,DWORD mj,DWORD s,DWORD ti){
DWORD temp = G(b,c,d) + a + mj + ti; temp = (temp<<s)|(temp>>(32-s)); a = b + temp; } void md5::HH(DWORD &a,DWORD &b,DWORD &c,DWORD &d,DWORD mj,DWORD s,DWORD ti){
DWORD temp = H(b,c,d) + a + mj + ti; temp = (temp<<s)|(temp>>(32-s)); a = b + temp; } void md5::II(DWORD &a,DWORD &b,DWORD &c,DWORD &d,DWORD mj,DWORD s,DWORD ti){
DWORD temp = I(b,c,d) + a + mj + ti; temp = (temp<<s)|(temp>>(32-s)); a = b + temp; }
其中,F,G,H,I分别是:
DWORD md5::F(DWORD X,DWORD Y,DWORD Z){
return (X&Y)|((~X)&Z); } DWORD md5::G(DWORD X,DWORD Y,DWORD Z){
return (X&Z)|(Y&(~Z)); } DWORD md5::H(DWORD X,DWORD Y,DWORD Z){
return X^Y^Z; } DWORD md5::I(DWORD X,DWORD Y,DWORD Z){
return Y^(X|(~Z)); }
接下来是参数说明,由于每个函数的参数具有相同的意义,所以只说一个就行了。
a,b,c,d 4个参数对应的值是周期变化的,周期长度为4,所以是:
for(int j=0;j<16;j+=4){
//每次增加4 FF(A,B,C,D,M[m[j]],s[j],T[j]); FF(D,A,B,C,M[m[j+1]],s[j+1],T[j+1]); FF(C,D,A,B,M[m[j+2]],s[j+2],T[j+2]); FF(B,C,D,A,M[m[j+3]],s[j+3],T[j+3]); } //GG、HH、II也类似,每种函数执行16次(1轮4次,4轮16次)后再执行下一种函数 for(int j=0;j<16;j+=4){
GG(A,B,C,D,M[m[j]],s[j],T[j]); GG(D,A,B,C,M[m[j+1]],s[j+1],T[j+1]); GG(C,D,A,B,M[m[j+2]],s[j+2],T[j+2]); GG(B,C,D,A,M[m[j+3]],s[j+3],T[j+3]); }
当每段消息(512位,64个字节)都处理完之后,得到的a,b,c,d的值,按照地址的顺序从低到高打印对应的值,就是所求的MD5值。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/214847.html原文链接:https://javaforall.net
