现在的位置: 首页 > 综合 > 正文

md5 算法的c语言实现及应用

2013年10月24日 ⁄ 综合 ⁄ 共 13905字 ⁄ 字号 评论关闭

  1. #由于工作需要,稍微学了学md5方面的知识,现分享给大家,不耻聆听指教。
  2. #运行环境linux2.4以上。
  3. ##########
  4. #  md5.h #
  5. ##########
  6. #ifndef MD5_H
  7. #define MD5_H
  8. #define md5byte     unsigned char
  9. #define SIZEOF_UNSIGNED_LONG   4
  10. #if SIZEOF_UNSIGNED_LONG==     4
  11. # define UWORD32    unsigned long
  12. #elif SIZEOF_UNSIGNED_INT==4
  13. # define UWORD32    unsigned int
  14. #else
  15. # error I do not know what to use for a UWORD32.
  16. #endif
  17. typedef  struct MD5Context
  18. {
  19.     UWORD32 buf[4];
  20.     UWORD32 bytes[2];
  21.     UWORD32 in[16];
  22. } MD5_CTX;
  23. void MD5Init(struct MD5Context *context);
  24. void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len);
  25. void MD5Final(unsigned char digest[16], struct MD5Context *context);
  26. void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
  27. #define   STACK_SIZE   512
  28. #define   MD5SUMS      "md5sums" 
  29. typedef struct md5arc
  30. {
  31.         char dirname[STACK_SIZE];
  32.         char md5string[32];
  33. }md5_arc;
  34. typedef struct stack
  35. {
  36.     char file_dir[STACK_SIZE];
  37.     int  top;
  38. }str_dir;
  39. static void MDString (char *string);
  40. void md5_to_string(unsigned char *unx,char *string);
  41. static void MDFile(const char *filename,char *store);
  42. #endif
  43. ############
  44. #  md5.c   #
  45. ############
  46. #include <string.h>     /* for memcpy() */
  47. #include <sys/types.h>      /* for stupid systems */
  48. #include <netinet/in.h>     /* for ntohl() */
  49. #include "md5.h"
  50. #ifdef WORDS_BIGENDIAN
  51. void
  52. byteSwap(UWORD32 *buf, unsigned words)
  53. {
  54.     md5byte *p = (md5byte *)buf;
  55.     do {
  56.         *buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 |
  57.             ((unsigned)p[1] << 8 | p[0]);
  58.         p += 4;
  59.     } while (--words);
  60. }
  61. #else
  62. #define byteSwap(buf,words)
  63. #endif
  64. void
  65. MD5Init(struct MD5Context *ctx)
  66. {
  67.     ctx->buf[0] = 0x67452301;
  68.     ctx->buf[1] = 0xefcdab89;
  69.     ctx->buf[2] = 0x98badcfe;
  70.     ctx->buf[3] = 0x10325476;
  71.     ctx->bytes[0] = 0;
  72.     ctx->bytes[1] = 0;
  73. }
  74. void
  75. MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len)
  76. {
  77.     UWORD32 t;
  78.     
  79.     /* Update byte count */
  80.     
  81.     t = ctx->bytes[0];
  82.     if ((ctx->bytes[0] = t + len) < t)
  83.                             ctx->bytes[1]++;    /* Carry from low to high */
  84.     
  85.     t = 64 - (t & 0x3f);    /* Space available in ctx->in (at least 1) */
  86.     if (t > len) {
  87.         memcpy((md5byte *)ctx->in + 64 - t, buf, len);
  88.         return;
  89.     }
  90.     /* First chunk is an odd size */
  91.     memcpy((md5byte *)ctx->in + 64 - t, buf, t);
  92.     byteSwap(ctx->in, 16);
  93.     MD5Transform(ctx->buf, ctx->in);
  94.     buf += t;
  95.     len -= t;
  96.     /* Process data in 64-byte chunks */
  97.     while (len >= 64) {
  98.         memcpy(ctx->in, buf, 64);
  99.         byteSwap(ctx->in, 16);
  100.         MD5Transform(ctx->buf, ctx->in);
  101.         buf += 64;
  102.         len -= 64;
  103.     }
  104.     
  105.     /* Handle any remaining bytes of data. */
  106.     memcpy(ctx->in, buf, len);
  107. }
  108. void
  109. MD5Final(md5byte digest[16], struct MD5Context *ctx)
  110. {
  111.     int count = ctx->bytes[0] & 0x3f;   /* Number of bytes in ctx->in */
  112.     md5byte *p = (md5byte *)ctx->in + count;
  113.     /* Set the first char of padding to 0x80.  There is always room. */
  114.     *p++ = 0x80;
  115.     /* Bytes of padding needed to make 56 bytes (-8..55) */
  116.     count = 56 - 1 - count;
  117.     if (count < 0) {    /* Padding forces an extra block */
  118.         memset(p, 0, count + 8);
  119.         byteSwap(ctx->in, 16);
  120.         MD5Transform(ctx->buf, ctx->in);
  121.         p = (md5byte *)ctx->in;
  122.         count = 56;
  123.     }
  124.     memset(p, 0, count);
  125.     byteSwap(ctx->in, 14);
  126.     
  127.     /* Append length in bits and transform */
  128.     ctx->in[14] = ctx->bytes[0] << 3;
  129.     ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
  130.     MD5Transform(ctx->buf, ctx->in);
  131.     
  132.     byteSwap(ctx->buf, 4);
  133.     memcpy(digest, ctx->buf, 16);
  134.     memset(ctx, 0, sizeof(ctx));    /* In case it's sensitive */
  135. }
  136. #ifndef ASM_MD5
  137. #define F1(x, y, z) (z ^ (x & (y ^ z)))
  138. #define F2(x, y, z) F1(z, x, y)
  139. #define F3(x, y, z) (x ^ y ^ z)
  140. #define F4(x, y, z) (y ^ (x | ~z))
  141. #define MD5STEP(f,w,x,y,z,in,s) /
  142.          (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
  143. void
  144. MD5Transform(UWORD32 buf[4], UWORD32 const in[16])
  145. {
  146.     register UWORD32 a, b, c, d;
  147.     a = buf[0];
  148.     b = buf[1];
  149.     c = buf[2];
  150.     d = buf[3];
  151.     
  152.     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
  153.     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
  154.     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
  155.     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
  156.     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
  157.     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
  158.     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
  159.     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
  160.     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
  161.     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
  162.     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
  163.     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
  164.     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
  165.     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
  166.     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
  167.     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
  168.     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
  169.     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
  170.     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
  171.     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
  172.     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
  173.     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
  174.     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
  175.     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
  176.     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
  177.     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
  178.     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
  179.     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
  180.     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
  181.     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
  182.     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
  183.     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
  184.     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
  185.     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
  186.     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
  187.     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
  188.     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
  189.     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
  190.     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
  191.     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
  192.     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
  193.     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
  194.     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
  195.     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
  196.     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
  197.     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
  198.     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
  199.     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
  200.     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
  201.     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
  202.     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
  203.     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
  204.     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
  205.     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
  206.     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
  207.     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
  208.     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
  209.     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
  210.     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
  211.     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
  212.     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
  213.     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
  214.     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
  215.     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
  216.     buf[0] += a;
  217.     buf[1] += b;
  218.     buf[2] += c;
  219.     buf[3] += d;
  220. }
  221. #endif
  222. ####################
  223. #  md5sum.c        #   
  224. #  md5的一些应用程序 #
  225. ####################
  226. #include  <stdio.h>
  227. #include  <fcntl.h>
  228. #include  <string.h>
  229. #include  <unistd.h>
  230. #include  <sys/stat.h>
  231. #include  <sys/types.h>
  232. #include  <dirent.h>
  233. #include  <errno.h>
  234. #include  "md5.h"
  235. static void MDPrint (unsigned char digest[1])
  236. {
  237.     unsigned int i;
  238.     printf("/n");
  239.     for(i = 0; i < 16; i++)
  240.         printf("%02x", digest[i]);
  241. }
  242. static void MDString (char *string)//打印出string的md5字符串
  243. {
  244.     MD5_CTX  context;
  245.     unsigned char digest[16];
  246.     unsigned int len = strlen(string);
  247.     MD5Init(&context);
  248.     MD5Update(&context, string, len);
  249.     MD5Final(digest, &context);
  250.     printf("%s = ", string);
  251.     MDPrint(digest);
  252.     printf("/n");
  253. }
  254. void
  255. md5_to_string(unsigned char *unx,char *string)
  256. {
  257.     int i;
  258.     char temp[3];
  259.     if(unx==NULL || string==NULL)
  260.         return;
  261.     
  262.     for(i=0;i<16;i++)
  263.     {
  264.         if(i==0)
  265.         {
  266.             sprintf(temp,"%02x",unx[i]);
  267.             strcpy(string,temp);
  268.         }
  269.         else
  270.         {
  271.             sprintf(temp,"%02x",unx[i]);
  272.             strcat(string,temp);
  273.         }
  274.     }
  275. }
  276. static void MDFile(const char *filename,char *store)
  277. {                      //计算文件filename的md5串,并保存到store中
  278.     FILE    *fd;
  279.     char    buffer[120];
  280.     struct  stat  buf;
  281.     int     size;
  282.     int     blocknum;
  283.     int     resize;
  284.     int     i;
  285.     
  286.     unsigned char digest[16];
  287.     MD5_CTX  context;
  288.     
  289.     if(lstat(filename,&buf)<0)
  290.     {
  291.         printf("stat file error: %s/n",filename);
  292.         exit(1);
  293.     }
  294.     if(buf.st_size==0)
  295.         size=buf.st_size;
  296.     else
  297.         size=buf.st_size-1;
  298.     
  299.     if((fd=fopen(filename,"r+"))==NULL)
  300.     {
  301.         printf("open file: %s error/n",filename);
  302.         exit(1);
  303.     }
  304.     
  305.     MD5Init(&context);
  306.     
  307.     if(size<=120)
  308.     {
  309.         fread(buffer,size,1,fd);
  310.         MD5Update(&context,buffer,size);
  311.         MD5Final(digest,&context);
  312.         fclose(fd);
  313.     }
  314.     else
  315.     {
  316.         blocknum=size/120;
  317.         resize=size-blocknum*120;
  318.         for(i=0;i<blocknum;i++)
  319.         {
  320.             fread(buffer,120,1,fd);
  321.             MD5Update(&context,buffer,120);
  322.         }
  323.         
  324.         fread(buffer,resize,1,fd);
  325.         MD5Update(&context,buffer,resize);
  326.         MD5Final(digest,&context);
  327.         fclose(fd);
  328.     }
  329.  //   printf("filename2:%s/n",filename);
  330.     
  331.     md5_to_string(digest,store);
  332. #ifdef _DEBUG_MESSAGE_
  333.     MDPrint(digest);
  334.     printf("/nin md5 file store is:%s/n",store);
  335.     
  336. #endif
  337.  //   printf("filename3:%s/n",filename);
  338. }
  339. void
  340. init_stack(str_dir *std)
  341. {
  342.   std->top=-1;
  343. }
  344. void
  345. pushchar(str_dir *std,char *ar )
  346. {
  347.     if(std->top>=STACK_SIZE-1)
  348.     {
  349.         printf("stack is full/n");
  350.         exit(0);
  351.     }
  352.     if(std->top<0)
  353.         strcpy(std->file_dir,ar);
  354.     else
  355.         strcat(std->file_dir,ar);
  356.     std->top+=strlen(ar);
  357.     std->file_dir[std->top+1]='/0';
  358. }
  359. void
  360. popchar(str_dir *std,int num)
  361. {
  362.     if (std->top==-1)
  363.     {
  364.         printf("stack is null/n");
  365.         exit(0);
  366.     }
  367.     char buf[STACK_SIZE];
  368.     strcpy(buf,std->file_dir);
  369.     memset(std->file_dir,0,strlen(std->file_dir));
  370.     memcpy(std->file_dir,buf,std->top-num+1);
  371.     std->top-=num;
  372.     std->file_dir[std->top+1]='/0';
  373. }
  374. void
  375. trave_dir(char *dirname, str_dir *std,FILE *fd)
  376. {                           //遍历计算目录dirname中文件的md5串
  377.     DIR * dp;               //并保存文件路径+该文件的md5串到fd中
  378.     struct dirent * entry;
  379.     struct stat statbuf;
  380.     if ((dp=opendir(dirname))==NULL)
  381.     {
  382.         printf("can't open directory:%s/n",dirname);
  383.         
  384.         exit(1);
  385.     }
  386. #ifdef  _DEBUF_MESSAGE_
  387.     char pwd[60];
  388.     getcwd(pwd,60);
  389.     printf("before chdir dir is: %s/n",pwd);
  390. #endif
  391.     
  392.     chdir(dirname);
  393. #ifdef  _DEBUG_MESSAGE_
  394.     getcwd(pwd,60);
  395.     printf("after chdir dir is: %s/n",pwd);
  396. #endif
  397.     while ((entry=readdir(dp))!=NULL)
  398.     {
  399.        if(strcmp(entry->d_name,"netpower")==0)
  400.             continue;
  401.         lstat(entry -> d_name,&statbuf);
  402.         if (S_ISREG(statbuf.st_mode))
  403.         {
  404.              
  405.             md5_arc *md5h;
  406.             md5h=(md5_arc *)malloc(sizeof(md5_arc));
  407.             
  408.             pushchar(std,"/");
  409.             pushchar(std,entry->d_name);
  410.                                                                                                     
  411.             strcpy(md5h->dirname,std->file_dir);
  412.             
  413.             MDFile(entry->d_name,md5h->md5string);
  414.             
  415.             fprintf(fd,"%s ",md5h->md5string);
  416.             fprintf(fd,"%s/n",md5h->dirname);
  417. #ifdef  _DEBUG_MESSAGE_
  418.             printf("%s/n",std->file_dir);
  419. #endif
  420.             popchar(std,strlen(entry->d_name)+1);
  421.             
  422.          
  423.         }
  424.         else if(S_ISDIR(statbuf.st_mode))
  425.         {
  426.             if (strcmp(".",entry -> d_name)==0||strcmp("..",entry -> d_name)==0)
  427.                 continue;
  428.             pushchar(std,"/");
  429.             pushchar(std,entry->d_name);
  430.             trave_dir(entry->d_name,std,fd);
  431.             popchar(std,strlen(entry->d_name)+1);
  432.         }
  433.         else 
  434.             continue;
  435.     }
  436.     chdir("..");
  437.     
  438.     closedir(dp);
  439. #ifdef  _DEBUG_MDSSAGE_
  440.     char pwd2[60];
  441.     getcwd(pwd2,60);
  442.     printf("after read dir  is: %s/n",pwd2);
  443. #endif
  444. }
  445. void 
  446. readchar(FILE *fd,char *store,char end)
  447. {
  448.     char buf1[16];
  449.     unsigned char buf2[16];
  450.     char b;
  451.     int i=0;
  452.     while((b=fgetc(fd))!=end)
  453.     {  
  454.         if(feof(fd))
  455.             return;
  456.         store[i]=b;
  457.         i++;
  458.     }
  459.         store[i]='/0';
  460.          
  461.         
  462. }
  463. void 
  464. creat_md5sums(char *dirname,char *md5file)
  465. //对一个目录dirname生成一个md5文件
  466. //里面保存着目录中的文件的路径及对应文件md5串。类似于:  
  467. // home/test/test1  7c2008f71c02e6f08a40cd7244ee3e79  
  468. // home/test/test2  f970e2767d0cfe75876ea857f92e319b    
  469. {   
  470.     FILE *fd;
  471.     if((fd=fopen(md5file,"a+"))==NULL)
  472.     {
  473.         printf("open file error/n");
  474.         exit(1);
  475.     }
  476.     str_dir  *std;
  477.     std=(str_dir *)malloc(sizeof(str_dir));
  478.     init_stack(std);
  479.     pushchar(std,dirname);
  480.     
  481.     trave_dir(dirname,std,fd);
  482.     free(std);
  483.     fclose(fd);
  484.                                             
  485. }
  486. int
  487. check(char *md5file) //对目录进行md5检验
  488. {
  489.     FILE *fd;
  490.     char md5string[32];
  491.     char filedir[STACK_SIZE];
  492.     char checkstring[32];
  493.     char buf[STACK_SIZE];
  494.     int  flag=1;
  495. #ifdef  _DEBUG_MESSAGE
  496.     printf("md5file :%s/n",md5file);
  497. #endif
  498.                       
  499.     if((fd=fopen(md5file,"r"))==NULL)
  500.     {
  501.         printf("open md5sums error/n");
  502.     }
  503.     while(!feof(fd))
  504.     {
  505.         readchar(fd,md5string,' ');
  506.         readchar(fd,filedir,'/n');
  507.         if(feof(fd))
  508.             break;
  509.         strcpy(buf,filedir);
  510.         MDFile(filedir,checkstring);
  511.         if(strcmp(md5string,checkstring)==0)
  512.             printf("check file:  %s      ......yes/n",buf);
  513.         if(strcmp(md5string,checkstring)!=0)
  514.         {
  515.             printf("check file:  %s      ......no/n",buf);
  516.             flag=0;
  517.         }
  518.     }
  519.     fclose(fd);
  520.     return flag;
  521. }

抱歉!评论已关闭.