[C/C++ 演算法]-純C 檔案MD5計算

[C/C++ 演算法]-純C 檔案MD5計算

[C/C++ 演算法]-純C 檔案MD5計算

 

資料來源:http://people.csail.mit.edu/rivest/Md5.c

 

 

#ifndef MD5_H_INCLUDED

#define MD5_H_INCLUDED

/*

 **********************************************************************

 ** md5.h — Header file for implementation of MD5                   **

 ** RSA Data Security, Inc. MD5 Message Digest Algorithm             **

 ** Created: 2/17/90 RLR                                             **

 ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version              **

 ** Revised (for MD5): RLR 4/27/91                                   **

 **   — G modified to have y&~z instead of y&z                      **

 **   — FF, GG, HH modified to add in last register done            **

 **   — Access pattern: round 2 works mod 5, round 3 works mod 3    **

 **   — distinct additive constant for each step                    **

 **   — round 4 added, working mod 7                                **

 **********************************************************************

 */

 

/*

 **********************************************************************

 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **

 **                                                                  **

 ** License to copy and use this software is granted provided that   **

 ** it is identified as the “RSA Data Security, Inc. MD5 Message     **

 ** Digest Algorithm” in all material mentioning or referencing this **

 ** software or this function.                                       **

 **                                                                  **

 ** License is also granted to make and use derivative works         **

 ** provided that such works are identified as “derived from the RSA **

 ** Data Security, Inc. MD5 Message Digest Algorithm” in all         **

 ** material mentioning or referencing the derived work.             **

 **                                                                  **

 ** RSA Data Security, Inc. makes no representations concerning      **

 ** either the merchantability of this software or the suitability   **

 ** of this software for any particular purpose.  It is provided “as **

 ** is” without express or implied warranty of any kind.             **

 **                                                                  **

 ** These notices must be retained in any copies of any part of this **

 ** documentation and/or software.                                   **

 **********************************************************************

 */

 

/* typedef a 32 bit type */

typedefunsignedlongint UINT4;

 

/* Data structure for MD5 (Message Digest) computation */

typedefstruct{

  UINT4 i[2];                   /* number of _bits_ handled mod 2^64 */

  UINT4 buf[4];                                    /* scratch buffer */

  unsignedchar in[64];                              /* input buffer */

  unsignedchar digest[16];     /* actual digest after MD5Final call */

} MD5_CTX;

 

void MD5Init ();

void MD5Update ();

void MD5Final ();

 

 

#endif // MD5_H_INCLUDED

 

 

/*

 **********************************************************************

 ** md5.c                                                            **

 ** RSA Data Security, Inc. MD5 Message Digest Algorithm             **

 ** Created: 2/17/90 RLR                                             **

 ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version                  **

 **********************************************************************

 */

 

/*

 **********************************************************************

 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **

 **                                                                  **

 ** License to copy and use this software is granted provided that   **

 ** it is identified as the “RSA Data Security, Inc. MD5 Message     **

 ** Digest Algorithm” in all material mentioning or referencing this **

 ** software or this function.                                       **

 **                                                                  **

 ** License is also granted to make and use derivative works         **

 ** provided that such works are identified as “derived from the RSA **

 ** Data Security, Inc. MD5 Message Digest Algorithm” in all         **

 ** material mentioning or referencing the derived work.             **

 **                                                                  **

 ** RSA Data Security, Inc. makes no representations concerning      **

 ** either the merchantability of this software or the suitability   **

 ** of this software for any particular purpose.  It is provided “as **

 ** is” without express or implied warranty of any kind.             **

 **                                                                  **

 ** These notices must be retained in any copies of any part of this **

 ** documentation and/or software.                                   **

 **********************************************************************

 */

 

/* — include the following line if the md5.h header file is separate — */

/* #include “md5.h” */

 

/* forward declaration */

#include md5.h

staticvoid Transform ();

 

staticunsignedchar PADDING[64]={

  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

};

 

/* F, G and H are basic MD5 functions: selection, majority, parity */

#define F(x, y, z)(((x)&(y))|((~x)&(z)))

#define G(x, y, z)(((x)&(z))|((y)&(~z)))

#define H(x, y, z)((x)^(y)^(z))

#define I(x, y, z)((y)^((x)|(~z)))

 

/* ROTATE_LEFT rotates x left n bits */

#define ROTATE_LEFT(x, n)(((x)<<(n))|((x)>>(32-(n))))

 

/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */

/* Rotation is separate from addition to prevent recomputation */

#define FF(a, b, c, d, x, s, ac) \

  {(a)+= F ((b),(c),(d))+(x)+(UINT4)(ac); \

   (a)= ROTATE_LEFT ((a),(s)); \

   (a)+=(b); \

  }

#define GG(a, b, c, d, x, s, ac) \

  {(a)+= G ((b),(c),(d))+(x)+(UINT4)(ac); \

   (a)= ROTATE_LEFT ((a),(s)); \

   (a)+=(b); \

  }

#define HH(a, b, c, d, x, s, ac) \

  {(a)+= H ((b),(c),(d))+(x)+(UINT4)(ac); \

   (a)= ROTATE_LEFT ((a),(s)); \

   (a)+=(b); \

  }

#define II(a, b, c, d, x, s, ac) \

  {(a)+= I ((b),(c),(d))+(x)+(UINT4)(ac); \

   (a)= ROTATE_LEFT ((a),(s)); \

   (a)+=(b); \

  }

 

void MD5Init (mdContext)

MD5_CTX *mdContext;

{

  mdContext->i[0]= mdContext->i[1]=(UINT4)0;

 

  /* Load magic initialization constants.

   */

  mdContext->buf[0]=(UINT4)0x67452301;

  mdContext->buf[1]=(UINT4)0xefcdab89;

  mdContext->buf[2]=(UINT4)0x98badcfe;

  mdContext->buf[3]=(UINT4)0x10325476;

}

 

void MD5Update (mdContext, inBuf, inLen)

MD5_CTX *mdContext;

unsignedchar*inBuf;

unsignedint inLen;

{

  UINT4 in[16];

  int mdi;

  unsignedint i, ii;

 

  /* compute number of bytes mod 64 */

  mdi =(int)((mdContext->i[0]>>3)&0x3F);

 

  /* update number of bits */

  if((mdContext->i[0]+((UINT4)inLen <<3))< mdContext->i[0])

    mdContext->i[1]++;

  mdContext->i[0]+=((UINT4)inLen <<3);

  mdContext->i[1]+=((UINT4)inLen >>29);

 

  while(inLen–){

    /* add new character to buffer, increment mdi */

    mdContext->in[mdi++]=*inBuf++;

 

    /* transform if necessary */

    if(mdi ==0x40){

      for(i =0, ii =0; i <16; i++, ii +=4)

        in[i]=(((UINT4)mdContext->in[ii+3])<<24)|

                (((UINT4)mdContext->in[ii+2])<<16)|

                (((UINT4)mdContext->in[ii+1])<<8)|

                ((UINT4)mdContext->in[ii]);

      Transform (mdContext->buf, in);

      mdi =0;

    }

  }

}

 

void MD5Final (mdContext)

MD5_CTX *mdContext;

{

  UINT4 in[16];

  int mdi;

  unsignedint i, ii;

  unsignedint padLen;

 

  /* save number of bits */

  in[14]= mdContext->i[0];

  in[15]= mdContext->i[1];

 

  /* compute number of bytes mod 64 */

  mdi =(int)((mdContext->i[0]>>3)&0x3F);

 

  /* pad out to 56 mod 64 */

  padLen =(mdi <56)?(56 mdi):(120 mdi);

  MD5Update (mdContext, PADDING, padLen);

 

  /* append length in bits and transform */

  for(i =0, ii =0; i <14; i++, ii +=4)

    in[i]=(((UINT4)mdContext->in[ii+3])<<24)|

            (((UINT4)mdContext->in[ii+2])<<16)|

            (((UINT4)mdContext->in[ii+1])<<8)|

            ((UINT4)mdContext->in[ii]);

  Transform (mdContext->buf, in);

 

  /* store buffer in digest */

  for(i =0, ii =0; i <4; i++, ii +=4){

    mdContext->digest[ii]=(unsignedchar)(mdContext->buf[i]&0xFF);

    mdContext->digest[ii+1]=

      (unsignedchar)((mdContext->buf[i]>>8)&0xFF);

    mdContext->digest[ii+2]=

      (unsignedchar)((mdContext->buf[i]>>16)&0xFF);

    mdContext->digest[ii+3]=

      (unsignedchar)((mdContext->buf[i]>>24)&0xFF);

  }

}

 

/* Basic MD5 step. Transform buf based on in.

 */

staticvoid Transform (buf, in)

UINT4 *buf;

UINT4 *in;

{

  UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];

 

  /* Round 1 */

#define S11 7

#define S12 12

#define S13 17

#define S14 22

  FF ( a, b, c, d, in[0], S11,3614090360);/* 1 */

  FF ( d, a, b, c, in[1], S12,3905402710);/* 2 */

  FF ( c, d, a, b, in[2], S13,  606105819);/* 3 */

  FF ( b, c, d, a, in[3], S14,3250441966);/* 4 */

  FF ( a, b, c, d, in[4], S11,4118548399);/* 5 */

  FF ( d, a, b, c, in[5], S12,1200080426);/* 6 */

  FF ( c, d, a, b, in[6], S13,2821735955);/* 7 */

  FF ( b, c, d, a, in[7], S14,4249261313);/* 8 */

  FF ( a, b, c, d, in[8], S11,1770035416);/* 9 */

  FF ( d, a, b, c, in[9], S12,2336552879);/* 10 */

  FF ( c, d, a, b, in[10], S13,4294925233);/* 11 */

  FF ( b, c, d, a, in[11], S14,2304563134);/* 12 */

  FF ( a, b, c, d, in[12], S11,1804603682);/* 13 */

  FF ( d, a, b, c, in[13], S12,4254626195);/* 14 */

  FF ( c, d, a, b, in[14], S13,2792965006);/* 15 */

  FF ( b, c, d, a, in[15], S14,1236535329);/* 16 */

 

  /* Round 2 */

#define S21 5

#define S22 9

#define S23 14

#define S24 20

  GG ( a, b, c, d, in[1], S21,4129170786);/* 17 */

  GG ( d, a, b, c, in[6], S22,3225465664);/* 18 */

  GG ( c, d, a, b, in[11], S23,  643717713);/* 19 */

  GG ( b, c, d, a, in[0], S24,3921069994);/* 20 */

  GG ( a, b, c, d, in[5], S21,3593408605);/* 21 */

  GG ( d, a, b, c, in[10], S22,   38016083);/* 22 */

  GG ( c, d, a, b, in[15], S23,3634488961);/* 23 */

  GG ( b, c, d, a, in[4], S24,3889429448);/* 24 */

  GG ( a, b, c, d, in[9], S21,  568446438);/* 25 */

  GG ( d, a, b, c, in[14], S22,3275163606);/* 26 */

  GG ( c, d, a, b, in[3], S23,4107603335);/* 27 */

  GG ( b, c, d, a, in[8], S24,1163531501);/* 28 */

  GG ( a, b, c, d, in[13], S21,2850285829);/* 29 */

  GG ( d, a, b, c, in[2], S22,4243563512);/* 30 */

  GG ( c, d, a, b, in[7], S23,1735328473);/* 31 */

  GG ( b, c, d, a, in[12], S24,2368359562);/* 32 */

 

  /* Round 3 */

#define S31 4

#define S32 11

#define S33 16

#define S34 23

  HH ( a, b, c, d, in[5], S31,4294588738);/* 33 */

  HH ( d, a, b, c, in[8], S32,2272392833);/* 34 */

  HH ( c, d, a, b, in[11], S33,1839030562);/* 35 */

  HH ( b, c, d, a, in[14], S34,4259657740);/* 36 */

  HH ( a, b, c, d, in[1], S31,2763975236);/* 37 */

  HH ( d, a, b, c, in[4], S32,1272893353);/* 38 */

  HH ( c, d, a, b, in[7], S33,4139469664);/* 39 */

  HH ( b, c, d, a, in[10], S34,3200236656);/* 40 */

  HH ( a, b, c, d, in[13], S31,  681279174);/* 41 */

  HH ( d, a, b, c, in[0], S32,3936430074);/* 42 */

  HH ( c, d, a, b, in[3], S33,3572445317);/* 43 */

  HH ( b, c, d, a, in[6], S34,   76029189);/* 44 */

  HH ( a, b, c, d, in[9], S31,3654602809);/* 45 */

  HH ( d, a, b, c, in[12], S32,3873151461);/* 46 */

  HH ( c, d, a, b, in[15], S33,  530742520);/* 47 */

  HH ( b, c, d, a, in[2], S34,3299628645);/* 48 */

 

  /* Round 4 */

#define S41 6

#define S42 10

#define S43 15

#define S44 21

  II ( a, b, c, d, in[0], S41,4096336452);/* 49 */

  II ( d, a, b, c, in[7], S42,1126891415);/* 50 */

  II ( c, d, a, b, in[14], S43,2878612391);/* 51 */

  II ( b, c, d, a, in[5], S44,4237533241);/* 52 */

  II ( a, b, c, d, in[12], S41,1700485571);/* 53 */

  II ( d, a, b, c, in[3], S42,2399980690);/* 54 */

  II ( c, d, a, b, in[10], S43,4293915773);/* 55 */

  II ( b, c, d, a, in[1], S44,2240044497);/* 56 */

  II ( a, b, c, d, in[8], S41,1873313359);/* 57 */

  II ( d, a, b, c, in[15], S42,4264355552);/* 58 */

  II ( c, d, a, b, in[6], S43,2734768916);/* 59 */

  II ( b, c, d, a, in[13], S44,1309151649);/* 60 */

  II ( a, b, c, d, in[4], S41,4149444226);/* 61 */

  II ( d, a, b, c, in[11], S42,3174756917);/* 62 */

  II ( c, d, a, b, in[2], S43,  718787259);/* 63 */

  II ( b, c, d, a, in[9], S44,3951481745);/* 64 */

 

  buf[0]+= a;

  buf[1]+= b;

  buf[2]+= c;

  buf[3]+= d;

}

 

/*

 **********************************************************************

 ** End of md5.c                                                     **

 ******************************* (cut) ********************************

 */

 

 

#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <string.h>
#include "md5.h"
//資料來源:http://people.csail.mit.edu/rivest/Md5.c
 
/* Prints message digest buffer in mdContext as 32 hexadecimal digits.
   Order is from low-order byte to high-order byte of digest.
   Each byte is printed with high-order hexadecimal digit first.
 */
staticvoid MDPrint (MD5_CTX *mdContext)
{
  int i;
 
  for(i =0; i <16; i++)
    printf("%02x", mdContext->digest[i]);
}
 
/* size of test block */
#define TEST_BLOCK_SIZE 1000
 
/* number of blocks to process */
#define TEST_BLOCKS 10000
 
/* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */
staticlong TEST_BYTES =(long)TEST_BLOCK_SIZE *(long)TEST_BLOCKS;
 
/* A time trial routine, to measure the speed of MD5.
   Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE
   characters.
 */
staticvoid MDTimeTrial ()
{
  MD5_CTX mdContext;
  time_t endTime, startTime;
  unsignedchar data[TEST_BLOCK_SIZE];
  unsignedint i;
 
  /* initialize test data */
  for(i =0; i < TEST_BLOCK_SIZE; i++)
    data[i]=(unsignedchar)(i &0xFF);
 
  /* start timer */
  printf("MD5 time trial. Processing %ld characters...\n", TEST_BYTES);
  time(&startTime);
 
  /* digest data in TEST_BLOCK_SIZE byte blocks */
  MD5Init (&mdContext);
  for(i = TEST_BLOCKS; i >0; i--)
    MD5Update (&mdContext, data, TEST_BLOCK_SIZE);
  MD5Final (&mdContext);
 
  /* stop timer, get time difference */
  time(&endTime);
  MDPrint (&mdContext);
  printf(" is digest of test input.\n");
  printf
    ("Seconds to process test input: %ld\n",(long)(endTime-startTime));
  printf
    ("Characters processed per second: %ld\n",
     TEST_BYTES/(endTime-startTime));
}
 
/* Computes the message digest for string inString.
   Prints out message digest, a space, the string (in quotes) and a
   carriage return.
 */
staticvoid MDString (char*inString)
{
  MD5_CTX mdContext;
  unsignedint len =strlen(inString);
 
  MD5Init (&mdContext);
  MD5Update (&mdContext, inString, len);
  MD5Final (&mdContext);
  MDPrint (&mdContext);
  printf("\"%s\"\n\n", inString);
}
 
/* Computes the message digest for a specified file.
   Prints out message digest, a space, the file name, and a carriage
   return.
 */
staticvoid MDFile (char*filename)
 
{
  FILE*inFile =fopen(filename,"rb");
  MD5_CTX mdContext;
  int bytes;
  unsignedchar data[1024];
 
  if(inFile ==NULL){
    printf("%s can't be opened.\n", filename);
    return;
  }
 
  MD5Init (&mdContext);
  while((bytes =fread(data,1,1024, inFile))!=0)
    MD5Update (&mdContext, data, bytes);
  MD5Final (&mdContext);
  MDPrint (&mdContext);
  printf("%s\n", filename);
  fclose(inFile);
}
 
/* Writes the message digest of the data from stdin onto stdout,
   followed by a carriage return.
 */
staticvoid MDFilter ()
{
  MD5_CTX mdContext;
  int bytes;
  unsignedchar data[16];
 
  MD5Init (&mdContext);
  while((bytes =fread(data,1,16,stdin))!=0)
    MD5Update (&mdContext, data, bytes);
  MD5Final (&mdContext);
  MDPrint (&mdContext);
  printf("\n");
}
 
/* Runs a standard suite of test data.
 */
staticvoid MDTestSuite ()
{
  printf("MD5 test suite results:\n\n");
  MDString ("");
  MDString ("a");
  MDString ("abc");
  MDString ("message digest");
  MDString ("abcdefghijklmnopqrstuvwxyz");
  MDString
    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
  MDString
    ("1234567890123456789012345678901234567890\
1234567890123456789012345678901234567890");
  /* Contents of file foo are "abc" */
  MDFile ("foo");
}
 
intmain(int argc,char*argv[])
{
  int i;
 
  /* For each command line argument in turn:
  ** filename          -- prints message digest and name of file
  ** -sstring          -- prints message digest and contents of string
  ** -t                -- prints time trial statistics for 1M characters
  ** -x                -- execute a standard suite of test data
  ** (no args)         -- writes messages digest of stdin onto stdout
  */
  /*
  //原始寫法
  if (argc == 1)
    MDFilter ();
  else
    for (i = 1; i < argc; i++)
      if (argv[i][0] == '-' && argv[i][1] == 's')
        MDString (argv[i] + 2);
      else if (strcmp (argv[i], "-t") == 0)
        MDTimeTrial ();
      else if (strcmp (argv[i], "-x") == 0)
        MDTestSuite ();
      else MDFile (argv[i]);
   */
    MDFile (argv[1]);//JASH modify
    return0;
}
 
/*
 **********************************************************************
 ** End of md5driver.c                                               **
 ******************************* (cut) ********************************
 */

 

 


 

 


發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *