zoukankan      html  css  js  c++  java
  • MD5的实现

    以前编写的一个程序,当时编了挺长的时间。代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    
    FILE* f_open();//找到所要求的文章(默认在d:\\practise\\*.txt)
    unsigned long long int* md5_len(FILE*f,unsigned long long int len[2]);//返回信息的原始长度和处理后的长度
    unsigned char* message(unsigned long long int len[2],FILE* f);//返回处理后的信息地址
    void Init(unsigned int &A,unsigned int &B,unsigned int &C,unsigned int &D);//初始化链接常量
    void FF(unsigned int &a,unsigned int &b,unsigned int &c,unsigned int &d,
        unsigned int M,int s,long long int ti,int F,
        unsigned int (*X)(unsigned int X,unsigned int Y,unsigned int Z,int F));//每轮调用函数
    unsigned int F(unsigned int X,unsigned int Y,unsigned int Z,int F);//非线性运算
    unsigned int TI(int i);//产生常数ti
    unsigned int PP(unsigned int x);//反转结果
    void main()
    {
    unsigned long long int len[2];//文件长度(按字符)
    unsigned int ti;//常数ti
    unsigned char *S;//字符串指针
    unsigned int M[16],s,incre;//M[16]分组,s偏移量,incre数组编号增量
    unsigned int A[4]={},a[4]={};//A[4]初始连接常量及返回值,a[4]过程中变量
    int I;//数组起始编号
      Init(A[0],A[1],A[2],A[3]);
      unsigned int (*X)(unsigned int X,unsigned int Y,unsigned int Z,int F);
      unsigned long long int s_i=0;
       FILE* f;
       f=f_open();
       if(f==NULL)exit(0);
       md5_len(f,len);
       if(len[0]==-1)
           {
               printf("文件为空!\n");
               exit(0);
            }
       S=message(len,f);
       printf("信息串与补位在内存中的存储:\n");
       for(int i=0;i<len[1];i++)
       printf("%02x",S[i]);
       printf("\n");
        X=F;
    
       for(int i=0;i<len[1]/64;i++)
       {
           a[0]=A[0];
           a[1]=A[1];
           a[2]=A[2];
           a[3]=A[3];
           //printf("A[0]%x\nA[1]%x\nA[2]%x\nA[3]%x\n",A[0],A[1],A[2],A[3]);
           memset(M,0,64);
           memcpy(M,S+s_i,64);
           s_i+=64;
           //M[i]=(unsigned int)(s+s_i);
           printf("信息串与补位在分组里的形式:\n");
           for(int i=0;i<16;i++)
              printf("%08x",M[i]);
                printf("\n");
         for(int j=0;j<4;j++)
         {
             switch(j)
             {
             case 0:  I=0;incre=1;
                      for(int k=0;k<16;k++)
                      {
                          ti=TI(k+1);
                          //printf("0x%x\n",ti);
                       switch(k%4)
                               {
                               case 0: s=7;FF(a[0],a[1],a[2],a[3],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 1: s=12;FF(a[3],a[0],a[1],a[2],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 2: s=17;FF(a[2],a[3],a[0],a[1],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 3: s=22;FF(a[1],a[2],a[3],a[0],M[(I+k*incre)%16],s,ti,j,X);break;
                               }
                        }break;
             case 1:  I=1;incre=5;
                      for(int k=0;k<16;k++)
                      {
                           ti=TI(k+17);
                           //printf("0x%x\n",ti);
                       switch(k%4)
                               {
                               case 0: s=5;FF(a[0],a[1],a[2],a[3],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 1: s=9;FF(a[3],a[0],a[1],a[2],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 2: s=14;FF(a[2],a[3],a[0],a[1],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 3: s=20;FF(a[1],a[2],a[3],a[0],M[(I+k*incre)%16],s,ti,j,X);break;
                               }
                        }break;
             case 2:  I=5;incre=3;
                      for(int k=0;k<16;k++)
                      {
                           ti=TI(k+33);
                           //printf("0x%x\n",ti);
                       switch(k%4)
                               {
                               case 0: s=4;FF(a[0],a[1],a[2],a[3],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 1: s=11;FF(a[3],a[0],a[1],a[2],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 2: s=16;FF(a[2],a[3],a[0],a[1],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 3: s=23;FF(a[1],a[2],a[3],a[0],M[(I+k*incre)%16],s,ti,j,X);break;
                               }
                        }break;
             case 3:  I=0;incre=7;
                      for(int k=0;k<16;k++)
                      {
                           ti=TI(k+49);
                           //printf("0x%x\n",ti);
                       switch(k%4)
                               {
                               case 0: s=6;FF(a[0],a[1],a[2],a[3],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 1: s=10;FF(a[3],a[0],a[1],a[2],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 2: s=15;FF(a[2],a[3],a[0],a[1],M[(I+k*incre)%16],s,ti,j,X);break;
                               case 3: s=21;FF(a[1],a[2],a[3],a[0],M[(I+k*incre)%16],s,ti,j,X);break;
                               }    
                        }break;
         }
         //printf("F返回值为%u\n",X);        
       }
         A[0]+=a[0];
         A[1]+=a[1];
         A[2]+=a[2];
         A[3]+=a[3];  
      }
       printf("所得MD5编码为%08x%08x%08x%08x\n",PP(A[0]),PP(A[1]),PP(A[2]),PP(A[3]));
       free(S);
       fclose(f);
    }
    
    FILE* f_open()
    {
    FILE *f;
        printf("请输入文件名称:\n");
        char f_name[50]={};
        scanf("%s",f_name);
        char f_path[100]={};
        sprintf(f_path,"D:\\practise\\%s.txt",f_name);
        f=fopen(f_path,"rb");
        if(f==NULL)
        {
            printf("找不到文件\n");
                return NULL;
        }
        return f;
    }
    
    unsigned long long int* md5_len(FILE*f,unsigned long long int len[2])
    {
       fseek(f,0L,SEEK_END);
       len[0]=ftell(f);
       fseek(f,0L,SEEK_SET);
       if(len[0]%64==56)//判断信息长度是否为N*512+448
          len[1]= (len[0]+8);//信息长度余数是448,只需加上64位二进制长度
       else 
           if(len[0]%64<56)
           len[1]= (len[0]+56-len[0]%64+8);//信息长度余数小于448,补足
           else
               if(len[0]%64>56)
               len[1]= (len[0]+64-len[0]%64+56+8);//信息长度余数大于448,补满512后再补448
         return len;
    }
    
    void Init( unsigned int &A,unsigned int &B,unsigned int &C,unsigned int &D)
    {
     A=0x67452301;
     B=0xefcdab89;
     C=0x98badcfe;
     D=0x10325476;
    }
    
    
    unsigned int TI(int i)
    {
    long long int ti;
     ti=(long long int)4294967296*abs(sin((double)i));
     return ti;
    }
    
    unsigned int F(unsigned int X,unsigned int Y,unsigned int Z,int F)
    {
        switch(F)
        {
        case 0: return (X&Y)|((~X)&Z);
        case 1: return (X&Z)|(Y&(~Z));
        case 2: return X^Y^Z;
        case 3: return Y^(X|(~Z));
        default : return 0;
        }
    }
    
    void FF(unsigned int &a,unsigned int &b,unsigned int &c,unsigned int &d,
        unsigned int M,int s,long long int ti,int F,
        unsigned int (*X)(unsigned int X,unsigned int Y,unsigned int Z,int F))
    {
        a+=X(b,c,d,F)+M+ti;
        a=(a<<s)|(a>>(32-s));
            a+=b;
        //a=b+(((a+X(b,c,d,F)+M+ti)<<s)|((a+X(b,c,d,F)+M+ti)>>(32-s)));不知为何不行
     //printf("%08x\n",a);
    }
    
     unsigned char* message(unsigned long long int len[2],FILE* f)
    {
        unsigned char *s;
        unsigned int flen[2];
       s=(unsigned char*)malloc((sizeof(char)*len[1]));
       memset(s,0,len[1]);
       fread(s,len[0],1,f);
       printf("信息串为:\n");
       printf("%s\n",s);
       fseek(f,0L,SEEK_SET);
       printf("文件长度是:%lld字节\n md5长度是:%lld字节\n",len[0],len[1]);
       flen[1]=len[0]/0x20000000;//按低位在前,高位在后的顺序存储该长度
       flen[0]=(len[0]%0x20000000)*8;
    
       printf("填入长度是%08x%08x\n",flen[1],flen[0]);
       if(len[1]-len[0]-8>0)
       {    
           s[len[0]]=128;//是信息后首个位赋1,并不是整个字符
          for( int i=1;i<len[1]-len[0]-8;i++)
            s[len[0]+i]=0;
       }
       memcpy(s+len[1]-8,flen,8);
       return s;
    }
    
     unsigned int PP(unsigned int x)
     {
     return (x<<24)|((x<<8)&0xff0000)|((x>>8)&0xff00)|(x>>24);
     }

    难点就是字符在unsigned int 和long long int 中的存储和表现形式吧,说实话,还不太了解。。。 百度百科不太给力吧。还有一个点就是移位的公式有些不太理解。①
    a+=X(b,c,d,F)+M+ti;②a=(a<<s)|(a>>(32-s));③ a+=b;分开就可以,而a=b+(((a+X(b,c,d,F)+M+ti)<<s)|((a+X(b,c,d,F)+M+ti)>>(32-s)));就不行了,费解。。。
    上图吧,真不容易 



  • 相关阅读:
    迪杰斯特拉_优先队列 模板
    POJ3268(Dijkstra_邻接矩阵)
    Uva-10815
    Uva-10474
    同余方程
    欧几里得算法与扩展欧几里得算法
    大整数型的加法
    Uva442
    《哲学起步》读后感 读书笔记
    《论大战略》读后感 读书笔记
  • 原文地址:https://www.cnblogs.com/idealing/p/3068672.html
Copyright © 2011-2022 走看看