• MD5算法--网盘秒传


      在用网盘传东西的时候,突然发现传某些几个G的文件竟然几秒钟就传到网盘上去了,刚开始还以为是传送发生了错误,然后又重复传了几次还是一样。然后上网一查,看到知乎上的一个提问的讨论查了些网上的资料才明白其中原理。

      对于网盘服务器上的每一个文件,服务器上都存有一个相应的唯一的特征值,然后当你从客户端传文件到网盘上时,会先计算你要传的文件的特征值,然后与服务器中存的对比,发现相同特征值则表明你要传的文件在服务器上已经存在,这时就实现秒传了。

      那这个唯一的特征值是如何计算的呢?不部分是用MD5算法。

      MD5算法功能就是对于你传入的一个任意长度的数据(其实根据算法的原理应该小于2的64次方bit,这个在目前的文件来说已经是无穷大了),然后经过处理,产生一个“唯一”的128位的信息。而且这个过程是不可逆的,也即你不能通过这个128位信息反推出原数据。

    1、MD5算法的历史

      1992年8月Ronald L. Rivest在向IETF提交了一份重要文件,描述了这种算法的原理,由于这种算法的公开性和安全性,在90年代被广泛使用在各种程序语言中,用以确保资料传递无误等。MD5由MD4、MD3、MD2改进而来,主要增强算法复杂度和不可逆性

      MD5较老,散列长度通常为128位,随着计算机运算能力提高,找到“碰撞”是可能的。因此,在少数安全要求高的场合不使用MD5。

      2004年,中国数学家王小云证明MD5数字签名算法可以产生碰撞。2007年,Marc Stevens,Arjen K. Lenstra和Benne de Weger进一步指出通过伪造软件签名,可重复性攻击MD5算法。研究者使用前缀碰撞法(chosen-prefix collision),使程序前端包含恶意程序,利用后面的空间添上垃圾代码凑出同样的MD5 哈希值。

    2、MD5算法的原理 (摘自: http://blog.csdn.net/forgotaboutgirl/article/details/7258109)

    MD5算法过程:
        对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

         第一步、填充:如果输入信息的长度(bit)对512求余的结果不等于448,就需要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0。填充完后,信息的长度就为N*512+448(bit);

         第二步、记录信息长度:用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。

         第三步、装入标准的幻数(四个整数):标准的幻数(物理顺序)是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定义应该是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有点晕哈,其实想一想就明白了。

         第四步、四轮循环运算:循环的次数是分组的个数(N+1) 

         1)将每一512字节细分成16个小组,每个小组64位(8个字节)
         
         2)先认识四个线性函数(&是与,|是或,~是非,^是异或)

      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))

        
        3)设Mj表示消息的第j个子分组(从0到15),<<<s表示循环左移s位,则四种操作为:

      FF(a,b,c,d,Mj,s,ti)表示a=b+((a+F(b,c,d)+Mj+ti)<<<s)
      GG(a,b,c,d,Mj,s,ti)表示a
    =b+((a+G(b,c,d)+Mj+ti)<<<s)
      HH(a,b,c,d,Mj,s,ti)表示a
    =b+((a+H(b,c,d)+Mj+ti)<<<s)
      II(a,b,c,d,Mj,s,ti)表示a
    =b+((a+I(b,c,d)+Mj+ti)<<<s)


        4)四轮运算

    第一轮
    a
    =FF(a,b,c,d,M0,7,0xd76aa478)
    b
    =FF(d,a,b,c,M1,12,0xe8c7b756)
    c
    =FF(c,d,a,b,M2,17,0x242070db)
    d
    =FF(b,c,d,a,M3,22,0xc1bdceee)
    a
    =FF(a,b,c,d,M4,7,0xf57c0faf)
    b
    =FF(d,a,b,c,M5,12,0x4787c62a)
    c
    =FF(c,d,a,b,M6,17,0xa8304613)
    d
    =FF(b,c,d,a,M7,22,0xfd469501)
    a
    =FF(a,b,c,d,M8,7,0x698098d8)
    b
    =FF(d,a,b,c,M9,12,0x8b44f7af)
    c
    =FF(c,d,a,b,M10,17,0xffff5bb1)
    d
    =FF(b,c,d,a,M11,22,0x895cd7be)
    a
    =FF(a,b,c,d,M12,7,0x6b901122)
    b
    =FF(d,a,b,c,M13,12,0xfd987193)
    c
    =FF(c,d,a,b,M14,17,0xa679438e)
    d
    =FF(b,c,d,a,M15,22,0x49b40821)

    第二轮
    a
    =GG(a,b,c,d,M1,5,0xf61e2562)
    b
    =GG(d,a,b,c,M6,9,0xc040b340)
    c
    =GG(c,d,a,b,M11,14,0x265e5a51)
    d
    =GG(b,c,d,a,M0,20,0xe9b6c7aa)
    a
    =GG(a,b,c,d,M5,5,0xd62f105d)
    b
    =GG(d,a,b,c,M10,9,0x02441453)
    c
    =GG(c,d,a,b,M15,14,0xd8a1e681)
    d
    =GG(b,c,d,a,M4,20,0xe7d3fbc8)
    a
    =GG(a,b,c,d,M9,5,0x21e1cde6)
    b
    =GG(d,a,b,c,M14,9,0xc33707d6)
    c
    =GG(c,d,a,b,M3,14,0xf4d50d87)
    d
    =GG(b,c,d,a,M8,20,0x455a14ed)
    a
    =GG(a,b,c,d,M13,5,0xa9e3e905)
    b
    =GG(d,a,b,c,M2,9,0xfcefa3f8)
    c
    =GG(c,d,a,b,M7,14,0x676f02d9)
    d
    =GG(b,c,d,a,M12,20,0x8d2a4c8a)

    第三轮
    a
    =HH(a,b,c,d,M5,4,0xfffa3942)
    b
    =HH(d,a,b,c,M8,11,0x8771f681)
    c
    =HH(c,d,a,b,M11,16,0x6d9d6122)
    d
    =HH(b,c,d,a,M14,23,0xfde5380c)
    a
    =HH(a,b,c,d,M1,4,0xa4beea44)
    b
    =HH(d,a,b,c,M4,11,0x4bdecfa9)
    c
    =HH(c,d,a,b,M7,16,0xf6bb4b60)
    d
    =HH(b,c,d,a,M10,23,0xbebfbc70)
    a
    =HH(a,b,c,d,M13,4,0x289b7ec6)
    b
    =HH(d,a,b,c,M0,11,0xeaa127fa)
    c
    =HH(c,d,a,b,M3,16,0xd4ef3085)
    d
    =HH(b,c,d,a,M6,23,0x04881d05)
    a
    =HH(a,b,c,d,M9,4,0xd9d4d039)
    b
    =HH(d,a,b,c,M12,11,0xe6db99e5)
    c
    =HH(c,d,a,b,M15,16,0x1fa27cf8)
    d
    =HH(b,c,d,a,M2,23,0xc4ac5665)

    第四轮
    a
    =II(a,b,c,d,M0,6,0xf4292244)
    b
    =II(d,a,b,c,M7,10,0x432aff97)
    c
    =II(c,d,a,b,M14,15,0xab9423a7)
    d
    =II(b,c,d,a,M5,21,0xfc93a039)
    a
    =II(a,b,c,d,M12,6,0x655b59c3)
    b
    =II(d,a,b,c,M3,10,0x8f0ccc92)
    c
    =II(c,d,a,b,M10,15,0xffeff47d)
    d
    =II(b,c,d,a,M1,21,0x85845dd1)
    a
    =II(a,b,c,d,M8,6,0x6fa87e4f)
    b
    =II(d,a,b,c,M15,10,0xfe2ce6e0)
    c
    =II(c,d,a,b,M6,15,0xa3014314)
    d
    =II(b,c,d,a,M13,21,0x4e0811a1)
    a
    =II(a,b,c,d,M4,6,0xf7537e82)
    b
    =II(d,a,b,c,M11,10,0xbd3af235)
    c
    =II(c,d,a,b,M2,15,0x2ad7d2bb)
    d
    =II(b,c,d,a,M9,21,0xeb86d391)


        5)每轮循环后,将A,B,C,D分别加上a,b,c,d,然后进入下一循环。

    3、MD5算法的java实现  (摘自: http://blog.csdn.net/forgotaboutgirl/article/details/7258109)

      1 /************************************************
      2  * MD5 算法
      3  * @author 我行我素
      4  * @Date 2007-07-01
      5 *************************************************/
      6 public class MD5 {
      7 
      8     static final String hexs[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
      9     //标准的幻数
     10     private static final long A=0x67452301L;
     11     private static final long B=0xefcdab89L;
     12     private static final long C=0x98badcfeL;
     13     private static final long D=0x10325476L;
     14 
     15     
     16     //下面这些S11-S44实际上是一个4*4的矩阵,在四轮循环运算中用到
     17     static final int S11 = 7;
     18     static final int S12 = 12;
     19     static final int S13 = 17;
     20     static final int S14 = 22;
     21 
     22     static final int S21 = 5;
     23     static final int S22 = 9;
     24     static final int S23 = 14;
     25     static final int S24 = 20;
     26 
     27     static final int S31 = 4;
     28     static final int S32 = 11;
     29     static final int S33 = 16;
     30     static final int S34 = 23;
     31 
     32     static final int S41 = 6;
     33     static final int S42 = 10;
     34     static final int S43 = 15;
     35     static final int S44 = 21;
     36     
     37     //java不支持无符号的基本数据(unsigned)
     38     private long [] result={A,B,C,D};//存储hash结果,共4×32=128位,初始化值为(幻数的级联)
     39     
     40     public static void main(String []args){
     41         MD5 md=new MD5();
     42         System.out.println("md5(abc)="+md.digest("abc"));
     43     }
     44     
     45     private String digest(String inputStr){
     46         byte [] inputBytes=inputStr.getBytes();
     47         int byteLen=inputBytes.length;//长度(字节)
     48         int groupCount=0;//完整分组的个数
     49         groupCount=byteLen/64;//每组512位(64字节)
     50         long []groups=null;//每个小组(64字节)再细分后的16个小组(4字节)
     51         
     52         //处理每一个完整 分组
     53         for(int step=0;step<groupCount;step++){
     54             groups=divGroup(inputBytes,step*64);
     55             trans(groups);//处理分组,核心算法
     56         }
     57         
     58         //处理完整分组后的尾巴
     59         int rest=byteLen%64;//512位分组后的余数
     60         byte [] tempBytes=new byte[64];
     61         if(rest<=56){
     62             for(int i=0;i<rest;i++)
     63                 tempBytes[i]=inputBytes[byteLen-rest+i];
     64             if(rest<56){
     65                 tempBytes[rest]=(byte)(1<<7);
     66                 for(int i=1;i<56-rest;i++)
     67                     tempBytes[rest+i]=0;
     68             }
     69             long len=(long)(byteLen<<3);
     70             for(int i=0;i<8;i++){
     71                 tempBytes[56+i]=(byte)(len&0xFFL);
     72                 len=len>>8;
     73             }
     74             groups=divGroup(tempBytes,0);
     75             trans(groups);//处理分组
     76         }else{
     77             for(int i=0;i<rest;i++)
     78                 tempBytes[i]=inputBytes[byteLen-rest+i];
     79             tempBytes[rest]=(byte)(1<<7);
     80             for(int i=rest+1;i<64;i++)
     81                 tempBytes[i]=0;
     82             groups=divGroup(tempBytes,0);
     83             trans(groups);//处理分组
     84             
     85             for(int i=0;i<56;i++)
     86                 tempBytes[i]=0;
     87             long len=(long)(byteLen<<3);
     88             for(int i=0;i<8;i++){
     89                 tempBytes[56+i]=(byte)(len&0xFFL);
     90                 len=len>>8;
     91             }
     92             groups=divGroup(tempBytes,0);
     93             trans(groups);//处理分组
     94         }
     95         
     96         //将Hash值转换成十六进制的字符串
     97         String resStr="";
     98         long temp=0;
     99         for(int i=0;i<4;i++){
    100             for(int j=0;j<4;j++){
    101                 temp=result[i]&0x0FL;
    102                 String a=hexs[(int)(temp)];
    103                 result[i]=result[i]>>4;
    104                 temp=result[i]&0x0FL;
    105                 resStr+=hexs[(int)(temp)]+a;
    106                 result[i]=result[i]>>4;
    107             }
    108         }
    109         return resStr;
    110     }
    111     
    112     /**
    113      * 从inputBytes的index开始取512位,作为新的分组
    114      * 将每一个512位的分组再细分成16个小组,每个小组64位(8个字节)
    115      * @param inputBytes
    116      * @param index
    117      * @return
    118      */
    119     private static long[] divGroup(byte[] inputBytes,int index){
    120         long [] temp=new long[16];
    121         for(int i=0;i<16;i++){
    122             temp[i]=b2iu(inputBytes[4*i+index])|
    123                 (b2iu(inputBytes[4*i+1+index]))<<8|
    124                 (b2iu(inputBytes[4*i+2+index]))<<16|
    125                 (b2iu(inputBytes[4*i+3+index]))<<24;
    126         }
    127         return temp;
    128     }
    129     
    130     /**
    131      * 这时不存在符号位(符号位存储不再是代表正负),所以需要处理一下
    132      * @param b
    133      * @return
    134      */
    135     public static long b2iu(byte b){
    136         return b < 0 ? b & 0x7F + 128 : b;
    137      }
    138     
    139     /**
    140      * 主要的操作,四轮循环
    141      * @param groups[]--每一个分组512位(64字节)
    142      */
    143     private void trans(long[] groups) {
    144         long a = result[0], b = result[1], c = result[2], d = result[3];
    145         /*第一轮*/
    146         a = FF(a, b, c, d, groups[0], S11, 0xd76aa478L); /* 1 */
    147         d = FF(d, a, b, c, groups[1], S12, 0xe8c7b756L); /* 2 */
    148         c = FF(c, d, a, b, groups[2], S13, 0x242070dbL); /* 3 */
    149         b = FF(b, c, d, a, groups[3], S14, 0xc1bdceeeL); /* 4 */
    150         a = FF(a, b, c, d, groups[4], S11, 0xf57c0fafL); /* 5 */
    151         d = FF(d, a, b, c, groups[5], S12, 0x4787c62aL); /* 6 */
    152         c = FF(c, d, a, b, groups[6], S13, 0xa8304613L); /* 7 */
    153         b = FF(b, c, d, a, groups[7], S14, 0xfd469501L); /* 8 */
    154         a = FF(a, b, c, d, groups[8], S11, 0x698098d8L); /* 9 */
    155         d = FF(d, a, b, c, groups[9], S12, 0x8b44f7afL); /* 10 */
    156         c = FF(c, d, a, b, groups[10], S13, 0xffff5bb1L); /* 11 */
    157         b = FF(b, c, d, a, groups[11], S14, 0x895cd7beL); /* 12 */
    158         a = FF(a, b, c, d, groups[12], S11, 0x6b901122L); /* 13 */
    159         d = FF(d, a, b, c, groups[13], S12, 0xfd987193L); /* 14 */
    160         c = FF(c, d, a, b, groups[14], S13, 0xa679438eL); /* 15 */
    161         b = FF(b, c, d, a, groups[15], S14, 0x49b40821L); /* 16 */
    162 
    163         /*第二轮*/
    164         a = GG(a, b, c, d, groups[1], S21, 0xf61e2562L); /* 17 */
    165         d = GG(d, a, b, c, groups[6], S22, 0xc040b340L); /* 18 */
    166         c = GG(c, d, a, b, groups[11], S23, 0x265e5a51L); /* 19 */
    167         b = GG(b, c, d, a, groups[0], S24, 0xe9b6c7aaL); /* 20 */
    168         a = GG(a, b, c, d, groups[5], S21, 0xd62f105dL); /* 21 */
    169         d = GG(d, a, b, c, groups[10], S22, 0x2441453L); /* 22 */
    170         c = GG(c, d, a, b, groups[15], S23, 0xd8a1e681L); /* 23 */
    171         b = GG(b, c, d, a, groups[4], S24, 0xe7d3fbc8L); /* 24 */
    172         a = GG(a, b, c, d, groups[9], S21, 0x21e1cde6L); /* 25 */
    173         d = GG(d, a, b, c, groups[14], S22, 0xc33707d6L); /* 26 */
    174         c = GG(c, d, a, b, groups[3], S23, 0xf4d50d87L); /* 27 */
    175         b = GG(b, c, d, a, groups[8], S24, 0x455a14edL); /* 28 */
    176         a = GG(a, b, c, d, groups[13], S21, 0xa9e3e905L); /* 29 */
    177         d = GG(d, a, b, c, groups[2], S22, 0xfcefa3f8L); /* 30 */
    178         c = GG(c, d, a, b, groups[7], S23, 0x676f02d9L); /* 31 */
    179         b = GG(b, c, d, a, groups[12], S24, 0x8d2a4c8aL); /* 32 */
    180 
    181         /*第三轮*/
    182         a = HH(a, b, c, d, groups[5], S31, 0xfffa3942L); /* 33 */
    183         d = HH(d, a, b, c, groups[8], S32, 0x8771f681L); /* 34 */
    184         c = HH(c, d, a, b, groups[11], S33, 0x6d9d6122L); /* 35 */
    185         b = HH(b, c, d, a, groups[14], S34, 0xfde5380cL); /* 36 */
    186         a = HH(a, b, c, d, groups[1], S31, 0xa4beea44L); /* 37 */
    187         d = HH(d, a, b, c, groups[4], S32, 0x4bdecfa9L); /* 38 */
    188         c = HH(c, d, a, b, groups[7], S33, 0xf6bb4b60L); /* 39 */
    189         b = HH(b, c, d, a, groups[10], S34, 0xbebfbc70L); /* 40 */
    190         a = HH(a, b, c, d, groups[13], S31, 0x289b7ec6L); /* 41 */
    191         d = HH(d, a, b, c, groups[0], S32, 0xeaa127faL); /* 42 */
    192         c = HH(c, d, a, b, groups[3], S33, 0xd4ef3085L); /* 43 */
    193         b = HH(b, c, d, a, groups[6], S34, 0x4881d05L); /* 44 */
    194         a = HH(a, b, c, d, groups[9], S31, 0xd9d4d039L); /* 45 */
    195         d = HH(d, a, b, c, groups[12], S32, 0xe6db99e5L); /* 46 */
    196         c = HH(c, d, a, b, groups[15], S33, 0x1fa27cf8L); /* 47 */
    197         b = HH(b, c, d, a, groups[2], S34, 0xc4ac5665L); /* 48 */
    198 
    199         /*第四轮*/
    200         a = II(a, b, c, d, groups[0], S41, 0xf4292244L); /* 49 */
    201         d = II(d, a, b, c, groups[7], S42, 0x432aff97L); /* 50 */
    202         c = II(c, d, a, b, groups[14], S43, 0xab9423a7L); /* 51 */
    203         b = II(b, c, d, a, groups[5], S44, 0xfc93a039L); /* 52 */
    204         a = II(a, b, c, d, groups[12], S41, 0x655b59c3L); /* 53 */
    205         d = II(d, a, b, c, groups[3], S42, 0x8f0ccc92L); /* 54 */
    206         c = II(c, d, a, b, groups[10], S43, 0xffeff47dL); /* 55 */
    207         b = II(b, c, d, a, groups[1], S44, 0x85845dd1L); /* 56 */
    208         a = II(a, b, c, d, groups[8], S41, 0x6fa87e4fL); /* 57 */
    209         d = II(d, a, b, c, groups[15], S42, 0xfe2ce6e0L); /* 58 */
    210         c = II(c, d, a, b, groups[6], S43, 0xa3014314L); /* 59 */
    211         b = II(b, c, d, a, groups[13], S44, 0x4e0811a1L); /* 60 */
    212         a = II(a, b, c, d, groups[4], S41, 0xf7537e82L); /* 61 */
    213         d = II(d, a, b, c, groups[11], S42, 0xbd3af235L); /* 62 */
    214         c = II(c, d, a, b, groups[2], S43, 0x2ad7d2bbL); /* 63 */
    215         b = II(b, c, d, a, groups[9], S44, 0xeb86d391L); /* 64 */
    216 
    217         /*加入到之前计算的结果当中*/
    218         result[0] += a;
    219         result[1] += b;
    220         result[2] += c;
    221         result[3] += d;
    222         result[0]=result[0]&0xFFFFFFFFL;
    223         result[1]=result[1]&0xFFFFFFFFL;
    224         result[2]=result[2]&0xFFFFFFFFL;
    225         result[3]=result[3]&0xFFFFFFFFL;
    226     }
    227     
    228     /**
    229      * 下面是处理要用到的线性函数
    230      */
    231     private static long F(long x, long y, long z) {
    232         return (x & y) | ((~x) & z);
    233     }
    234 
    235     private static long G(long x, long y, long z) {
    236         return (x & z) | (y & (~z));
    237     }
    238 
    239     private static long H(long x, long y, long z) {
    240         return x ^ y ^ z;
    241     }
    242 
    243     private static long I(long x, long y, long z) {
    244         return y ^ (x | (~z));
    245     }
    246 
    247     private static long FF(long a, long b, long c, long d, long x, long s,
    248             long ac) {
    249         a += (F(b, c, d)&0xFFFFFFFFL) + x + ac;
    250         a = ((a&0xFFFFFFFFL)<< s) | ((a&0xFFFFFFFFL) >>> (32 - s));
    251         a += b;
    252         return (a&0xFFFFFFFFL);
    253     }
    254 
    255     private static long GG(long a, long b, long c, long d, long x, long s,
    256             long ac) {
    257         a += (G(b, c, d)&0xFFFFFFFFL) + x + ac;
    258         a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
    259         a += b;
    260         return (a&0xFFFFFFFFL);
    261     }
    262 
    263     private static long HH(long a, long b, long c, long d, long x, long s,
    264             long ac) {
    265         a += (H(b, c, d)&0xFFFFFFFFL) + x + ac;
    266         a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
    267         a += b;
    268         return (a&0xFFFFFFFFL);
    269     }
    270 
    271     private static long II(long a, long b, long c, long d, long x, long s,
    272             long ac) {
    273         a += (I(b, c, d)&0xFFFFFFFFL) + x + ac;
    274         a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
    275         a += b;
    276         return (a&0xFFFFFFFFL);
    277     }
    278 }
  • 相关阅读:
    lintcode:Find the Connected Component in the Undirected Graph 找出无向图汇总的相连要素
    lintcode:Recover Rotated Sorted Array恢复旋转排序数组
    lintcode:Number of Islands 岛屿的个数
    lintcode :Trailing Zeros 尾部的零
    lintcode:Flip Bits 将整数A转换为B
    lintcode:strStr 字符串查找
    lintcode:Subtree 子树
    lintcode 容易题:Partition Array by Odd and Even 奇偶分割数组
    lintcode:在二叉查找树中插入节点
    lintcode:在O(1)时间复杂度删除链表节点
  • 原文地址:https://www.cnblogs.com/blues-harp/p/3661689.html
Copyright © 2020-2023  润新知