md5全过程详解

参考自:http://blog.sina.com.cn/s/blog_6fe0eb1901014cpl.html#cmt_54A25B76-7F000001-6D7FA63B-829-8A0

md5详解:
    原字符串为N*512+R位,8位是一个字节(也叫字符)
    填充:如果R大于448,则填充不够64位,而我们需要64位保留字节存储字符串的原长
    原长存储:如果长度大于64位的长度,则只存取前64位的长
    把记录原长的64位按照小端规则(64位分高32位和低32位,如0x12则高32位为 0x0000 0000 低32位为 0x0000 0012 )排列放入填充好的数组(先叫它数组吧),
    分组:将每512位分成16组,即每组32位,也是4个字节,例如abcd。存入int变量时(不清出其它类型可以不,自己百度),需要注意大端小端的问题,我们看见的是大端排列的,内存中是小端排列的,md5是按内存中的小端的输出
        一个16进制占用4位,即8个16进制为一组,也就是用16进制表示则为16*8个16进制数共为512位。也可以表示为(4*8)*16
        例如abcde的16进制(对应ascii码)表示为 61 62 63 64 65 ,此时长度为4*10=40位,不足512位,使用先补一个1再补n个0的形式补齐512位(原长与512取余不大于448)
        abcde共5个字符,即5*8=40=0x28,即长度位为0x2800 0000 ,0000 0000,8个16进制位一组,为保持内存中的小端排序与前面相同,我们输入的排列为0000 0028 ,0000 0000
    初始化结束,开始进入计算公式和参数说明部分+
    MD5有四个32位的被称作链接变量的整数参数,我们进行如下设置(默认固定的设置,下边的是大端排序的数,在内存中的排序即是01234567 89abcdef fedcba98 76543210):
        A=0x67452301,
        B=0xefcdab89,
        C=0x98badcfe,
        D=0x10325476。
    声明四个中间变量a,b,c,d,赋值:a = A, b = B, c = C, d = 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的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。
    假设M[j]表示消息的第j个子分组(从0到15),这里的 ti 也是固定的貌似,因为看到的好几篇文章都是相同的参数
        FF(a, b, c, d, M[j], s, ti)表示 a = b + ((a + F(b, c, d) + Mj + ti) <<< s)
        GG(a, b, c, d, M[j], s, ti)表示 a = b + ((a + G(b, c, d) + Mj + ti) <<< s)
        HH(a, b, c, d, M[j], s, ti)表示 a = b + ((a + H(b, c, d) + Mj + ti) <<< s)
        II(a, b, c, d, M[j], s, ti)表示 a = b + ((a + I(b, c, d) + Mj + ti) <<< s)
    要确保形参a在内存中的值改变了,可以在形参中用按引用调用(&a),或返回a值取代原来a值。
    准备结束,进入正式的计算部分
    这个循环的循环次数为512位分组的个数(即之前提到的N+1或者N+2)。每次循环执行以下的步骤,我就不用文字表述了,直接用代码展示,相信大家能理解:

    {

        a = A; b = B; c = C; d = D;

        //传说中的对M[j]的第一轮循环

        FF(a,b,c,d,M[0],7,0xd76aa478);
        FF(d,a,b,c,M[1],12,0xe8c7b756);
        FF(c,d,a,b,M[2],17,0x242070db);
        FF(b,c,d,a,M[3],22,0xc1bdceee);
        FF(a,b,c,d,M[4],7,0xf57c0faf);
        FF(d,a,b,c,M[5],12,0x4787c62a);
        FF(c,d,a,b,M[6],17,0xa8304613);
        FF(b,c,d,a,M[7],22,0xfd469501) ;
        FF(a,b,c,d,M[8],7,0x698098d8) ;
        FF(d,a,b,c,M[9],12,0x8b44f7af) ;
        FF(c,d,a,b,M[10],17,0xffff5bb1) ;
        FF(b,c,d,a,M[11],22,0x895cd7be) ;
        FF(a,b,c,d,M[12],7,0x6b901122) ;
        FF(d,a,b,c,M[13],12,0xfd987193) ;
        FF(c,d,a,b,M[14],17,0xa679438e) ;
        FF(b,c,d,a,M[15],22,0x49b40821);

        //传说中对M[j]的第二轮循环
        GG(a,b,c,d,M[1],5,0xf61e2562);
        GG(d,a,b,c,M[6],9,0xc040b340);
        GG(c,d,a,b,M[11],14,0x265e5a51);
        GG(b,c,d,a,M[0],20,0xe9b6c7aa) ;
        GG(a,b,c,d,M[5],5,0xd62f105d) ;
        GG(d,a,b,c,M[10],9,0x02441453) ;
        GG(c,d,a,b,M[15],14,0xd8a1e681);
        GG(b,c,d,a,M[4],20,0xe7d3fbc8) ;
        GG(a,b,c,d,M[9],5,0x21e1cde6) ;
        GG(d,a,b,c,M[14],9,0xc33707d6) ;
        GG(c,d,a,b,M[3],14,0xf4d50d87) ;
        GG(b,c,d,a,M[8],20,0x455a14ed);
        GG(a,b,c,d,M[13],5,0xa9e3e905);
        GG(d,a,b,c,M[2],9,0xfcefa3f8) ;
        GG(c,d,a,b,M[7],14,0x676f02d9) ;
        GG(b,c,d,a,M[12],20,0x8d2a4c8a);

        //传说中对M[j]的第三轮循环
        HH(a,b,c,d,M[5],4,0xfffa3942);
        HH(d,a,b,c,M[8],11,0x8771f681);
        HH(c,d,a,b,M[11],16,0x6d9d6122);
        HH(b,c,d,a,M[14],23,0xfde5380c) ;
        HH(a,b,c,d,M[1],4,0xa4beea44) ;
        HH(d,a,b,c,M[4],11,0x4bdecfa9) ;
        HH(c,d,a,b,M[7],16,0xf6bb4b60) ;
        HH(b,c,d,a,M[10],23,0xbebfbc70);
        HH(a,b,c,d,M[13],4,0x289b7ec6);
        HH(d,a,b,c,M[0],11,0xeaa127fa);
        HH(c,d,a,b,M[3],16,0xd4ef3085);
        HH(b,c,d,a,M[6],23,0x04881d05);
        HH(a,b,c,d,M[9],4,0xd9d4d039);
        HH(d,a,b,c,M[12],11,0xe6db99e5);
        HH(c,d,a,b,M[15],16,0x1fa27cf8) ;
        HH(b,c,d,a,M[2],23,0xc4ac5665);

        //传说中对M[j]的第四轮循环
        II(a,b,c,d,M[0],6,0xf4292244) ;
        II(d,a,b,c,M[7],10,0x432aff97) ;
        II(c,d,a,b,M[14],15,0xab9423a7);
        II(b,c,d,a,M[5],21,0xfc93a039) ;
        II(a,b,c,d,M[12],6,0x655b59c3) ;
        II(d,a,b,c,M[3],10,0x8f0ccc92) ;
        II(c,d,a,b,M[10],15,0xffeff47d);
        II(b,c,d,a,M[1],21,0x85845dd1) ;
        II(a,b,c,d,M[8],6,0x6fa87e4f) ;
        II(d,a,b,c,M[15],10,0xfe2ce6e0);
        II(c,d,a,b,M[6],15,0xa3014314) ;
        II(b,c,d,a,M[13],21,0x4e0811a1);
        II(a,b,c,d,M[4],6,0xf7537e82) ;
        II(d,a,b,c,M[11],10,0xbd3af235);
        II(c,d,a,b,M[2],15,0x2ad7d2bb);
        II(b,c,d,a,M[9],21,0xeb86d391);

        A += a;
        B += b;
        C += c;
        D += d;

    }

处理完所有的512位的分组后,得到一组新的A,B,C,D的值,将这些值按ABCD的顺序级联,然后输出。这里还要注意,输出的MD5是按内存中数值的排列顺序,所以我们要分别对A,B,C,D的值做一个小端规则的转换。
举个例子:A有32位,分成4个字节A1A2A3A4。输出A的时候,要这样输出:A4A3 A2A1。这样就能输出正确的MD5了。
下边给几个测试使用:
    MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
    MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
    MD5 (“ab”) = 187ef4436122d1cc2f40dc2b92f0eba0
    MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
    MD5 (“abcde”) = ab56b4d92b40713acc5af89985d4b786
    MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
    MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
    MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") = f29939a25efabaef3b87e2cbfe641315
 

你可能感兴趣的:(加密解密算法)