zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    买房的贷款时间是否是越长越好?https://www.zhihu.com/question/20842791
    asp.net cookie and session
    leelazero and google colab
    download file by python in google colab
    physical processor, core, logical processor
    通过powershell操作eventlog
    openxml in sql server
    get the page name from url
    How to Execute Page_Load() in Page's Base Class?
    Difference between HttpContext.Request and Request
  • 原文地址:https://www.cnblogs.com/blues-harp/p/3661689.html
Copyright © 2011-2022 走看看