Main Page   Compound List   File List   Compound Members   File Members  

md5.cpp

Go to the documentation of this file.
00001 //==============================================
00002 //  copyright            : (C) 2003 by Will Stokes
00003 //==============================================
00004 //  This program is free software; you can redistribute it 
00005 //  and/or modify it under the terms of the GNU General 
00006 //  Public License as published by the Free Software 
00007 //  Foundation; either version 2 of the License, or  
00008 //  (at your option) any later version.         
00009 //
00010 //  As a special exception, Will Stokes gives permission to 
00011 //  link this program with Qt non-commercial edition, and 
00012 //  distribute the resulting executable, without including the 
00013 //  source code for the Qt non-commercial edition in the 
00014 //  source distribution. 
00015 //==============================================
00016 
00017 
00018 // MD5.CC - source code for the C++/object oriented translation and 
00019 //          modification of MD5.
00020 
00021 // Translation and modification (c) 1995 by Mordechai T. Abzug 
00022 
00023 // This translation/ modification is provided "as is," without express or 
00024 // implied warranty of any kind.
00025 
00026 // The translator/ modifier does not claim (1) that MD5 will do what you think 
00027 // it does; (2) that this translation/ modification is accurate; or (3) that 
00028 // this software is "merchantible."  (Language for this disclaimer partially 
00029 // copied from the disclaimer below).
00030 
00031 /* based on:
00032 
00033    MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
00034    MDDRIVER.C - test driver for MD2, MD4 and MD5
00035 
00036 
00037    Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
00038 rights reserved.
00039 
00040 License to copy and use this software is granted provided that it
00041 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
00042 Algorithm" in all material mentioning or referencing this software
00043 or this function.
00044 
00045 License is also granted to make and use derivative works provided
00046 that such works are identified as "derived from the RSA Data
00047 Security, Inc. MD5 Message-Digest Algorithm" in all material
00048 mentioning or referencing the derived work.
00049 
00050 RSA Data Security, Inc. makes no representations concerning either
00051 the merchantability of this software or the suitability of this
00052 software for any particular purpose. It is provided "as is"
00053 without express or implied warranty of any kind.
00054 
00055 These notices must be retained in any copies of any part of this
00056 documentation and/or software.
00057 
00058  */
00059 
00060 #include "md5.h"
00061 #include <assert.h>
00062 #include <string>
00063 
00064 // MD5 simple initialization method
00065 MD5::MD5()
00066 {
00067   init();
00068 }
00069 
00070 // MD5 block update operation. Continues an MD5 message-digest
00071 // operation, processing another message block, and updating the
00072 // context.
00073 
00074 void MD5::update (uint1 *input, uint4 input_length) {
00075 
00076   uint4 input_index, buffer_index;
00077   uint4 buffer_space;                // how much space is left in buffer
00078 
00079   if (finalized){  // so we can't update!
00080     cerr << "MD5::update:  Can't update a finalized digest!" << endl;
00081     return;
00082   }
00083 
00084   // Compute number of bytes mod 64
00085   buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
00086 
00087   // Update number of bits
00088   if (  (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
00089     count[1]++;
00090 
00091   count[1] += ((uint4)input_length >> 29);
00092 
00093 
00094   buffer_space = 64 - buffer_index;  // how much space is left in buffer
00095 
00096   // Transform as many times as possible.
00097   if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
00098     // fill the rest of the buffer and transform
00099     memcpy (buffer + buffer_index, input, buffer_space);
00100     transform (buffer);
00101 
00102     // now, transform each 64-byte piece of the input, bypassing the buffer
00103     for (input_index = buffer_space; input_index + 63 < input_length; 
00104          input_index += 64)
00105       transform (input+input_index);
00106 
00107     buffer_index = 0;  // so we can buffer remaining
00108   }
00109   else
00110     input_index=0;     // so we can buffer the whole input
00111 
00112 
00113   // and here we do the buffering:
00114   memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
00115 }
00116 
00117 
00118 
00119 // MD5 update for files.
00120 // Like above, except that it works on files (and uses above as a primitive.)
00121 
00122 void MD5::update(FILE *file){
00123 
00124   unsigned char buffer[1024];
00125   int len;
00126 
00127   while (true)
00128   {
00129     len=fread(buffer, 1, 1024, file);
00130     if(!len)
00131     {  break; }
00132       
00133     update(buffer, len);
00134    }
00135 
00136   fclose (file);
00137 
00138 }
00139 
00140 
00141 
00142 
00143 
00144 
00145 // MD5 update for istreams.
00146 // Like update for files; see above.
00147 
00148 void MD5::update(istream& stream){
00149 
00150   unsigned char buffer[1024];
00151   int len;
00152 
00153   while (stream.good()){
00154     stream.read((char*)buffer, 1024); // note that return value of read is unusable.
00155     len=stream.gcount();
00156     update(buffer, len);
00157   }
00158 
00159 }
00160 
00161 
00162 
00163 
00164 
00165 
00166 // MD5 update for ifstreams.
00167 // Like update for files; see above.
00168 
00169 void MD5::update(ifstream& stream){
00170 
00171   unsigned char buffer[1024];
00172   int len;
00173 
00174   while (stream.good()){
00175     stream.read((char*)buffer, 1024); // note that return value of read is unusable.
00176     len=stream.gcount();
00177     update(buffer, len);
00178   }
00179 
00180 }
00181 
00182 
00183 
00184 
00185 
00186 
00187 // MD5 finalization. Ends an MD5 message-digest operation, writing the
00188 // the message digest and zeroizing the context.
00189 
00190 
00191 void MD5::finalize (){
00192 
00193   unsigned char bits[8];
00194   unsigned int index, padLen;
00195   static uint1 PADDING[64]={
00196     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00197     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00198     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00199     };
00200 
00201   if (finalized){
00202     cerr << "MD5::finalize:  Already finalized this digest!" << endl;
00203     return;
00204   }
00205 
00206   // Save number of bits
00207   encode (bits, count, 8);
00208 
00209   // Pad out to 56 mod 64.
00210   index = (uint4) ((count[0] >> 3) & 0x3f);
00211   padLen = (index < 56) ? (56 - index) : (120 - index);
00212   update (PADDING, padLen);
00213 
00214   // Append length (before padding)
00215   update (bits, 8);
00216 
00217   // Store state in digest
00218   encode (digest, state, 16);
00219 
00220   // Zeroize sensitive information
00221   memset (buffer, 0, sizeof(*buffer));
00222 
00223   finalized=1;
00224 
00225 }
00226 
00227 
00228 
00229 
00230 MD5::MD5(FILE *file){
00231 
00232   init();  // must be called be all constructors
00233   update(file);
00234   finalize ();
00235 }
00236 
00237 
00238 
00239 
00240 MD5::MD5(istream& stream){
00241 
00242   init();  // must called by all constructors
00243   update (stream);
00244   finalize();
00245 }
00246 
00247 
00248 
00249 MD5::MD5(ifstream& stream){
00250 
00251   init();  // must called by all constructors
00252   update (stream);
00253   finalize();
00254 }
00255 
00256 
00257 
00258 unsigned char *MD5::raw_digest(){
00259 
00260   uint1 *s = new uint1[16];
00261 
00262   if (!finalized){
00263     cerr << "MD5::raw_digest:  Can't get digest if you haven't "<<
00264       "finalized the digest!" <<endl;
00265     return ( (unsigned char*) "");
00266   }
00267 
00268   memcpy(s, digest, 16);
00269   return s;
00270 }
00271 
00272 
00273 
00274 QString MD5::hex_digest(){
00275 
00276   int i;
00277   char *s= new char[33];
00278 
00279   if (!finalized){
00280     cerr << "MD5::hex_digest:  Can't get digest if you haven't "<<
00281       "finalized the digest!" <<endl;
00282     return "";
00283   }
00284 
00285   for (i=0; i<16; i++)
00286     sprintf(s+i*2, "%02x", digest[i]);
00287 
00288   s[32]='\0';
00289 
00290   QString result(s);
00291   delete s;
00292   return result;
00293 }
00294 
00295 
00296 // PRIVATE METHODS:
00297 
00298 
00299 
00300 void MD5::init(){
00301   finalized=0;  // we just started!
00302 
00303   // Nothing counted, so count=0
00304   count[0] = 0;
00305   count[1] = 0;
00306 
00307   // Load magic initialization constants.
00308   state[0] = 0x67452301;
00309   state[1] = 0xefcdab89;
00310   state[2] = 0x98badcfe;
00311   state[3] = 0x10325476;
00312 }
00313 
00314 
00315 
00316 // Constants for MD5Transform routine.
00317 // Although we could use C++ style constants, defines are actually better,
00318 // since they let us easily evade scope clashes.
00319 
00320 #define S11 7
00321 #define S12 12
00322 #define S13 17
00323 #define S14 22
00324 #define S21 5
00325 #define S22 9
00326 #define S23 14
00327 #define S24 20
00328 #define S31 4
00329 #define S32 11
00330 #define S33 16
00331 #define S34 23
00332 #define S41 6
00333 #define S42 10
00334 #define S43 15
00335 #define S44 21
00336 
00337 
00338 
00339 
00340 // MD5 basic transformation. Transforms state based on block.
00341 void MD5::transform (uint1 block[64]){
00342 
00343   uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00344 
00345   decode (x, block, 64);
00346 
00347   assert(!finalized);  // not just a user error, since the method is private
00348 
00349   /* Round 1 */
00350   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
00351   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
00352   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
00353   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
00354   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
00355   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
00356   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
00357   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
00358   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
00359   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
00360   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
00361   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
00362   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
00363   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
00364   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
00365   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
00366 
00367  /* Round 2 */
00368   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
00369   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
00370   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
00371   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
00372   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
00373   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
00374   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
00375   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
00376   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
00377   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
00378   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
00379   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
00380   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
00381   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
00382   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
00383   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
00384 
00385   /* Round 3 */
00386   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
00387   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
00388   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
00389   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
00390   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
00391   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
00392   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
00393   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
00394   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
00395   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
00396   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
00397   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
00398   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
00399   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
00400   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
00401   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
00402 
00403   /* Round 4 */
00404   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
00405   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
00406   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
00407   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
00408   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
00409   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
00410   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
00411   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
00412   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
00413   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
00414   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
00415   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
00416   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
00417   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
00418   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
00419   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
00420 
00421   state[0] += a;
00422   state[1] += b;
00423   state[2] += c;
00424   state[3] += d;
00425 
00426   // Zeroize sensitive information.
00427   memset ( (uint1 *) x, 0, sizeof(x));
00428 
00429 }
00430 
00431 
00432 
00433 // Encodes input (UINT4) into output (unsigned char). Assumes len is
00434 // a multiple of 4.
00435 void MD5::encode (uint1 *output, uint4 *input, uint4 len) {
00436 
00437   unsigned int i, j;
00438 
00439   for (i = 0, j = 0; j < len; i++, j += 4) {
00440     output[j]   = (uint1)  (input[i] & 0xff);
00441     output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
00442     output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
00443     output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
00444   }
00445 }
00446 
00447 
00448 
00449 
00450 // Decodes input (unsigned char) into output (UINT4). Assumes len is
00451 // a multiple of 4.
00452 void MD5::decode (uint4 *output, uint1 *input, uint4 len){
00453 
00454   unsigned int i, j;
00455 
00456   for (i = 0, j = 0; j < len; i++, j += 4)
00457     output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
00458       (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
00459 }
00460 
00461 
00462 
00463 
00464 
00465 // Note: Replace "for loop" with standard memcpy if possible.
00466 void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){
00467 
00468   unsigned int i;
00469 
00470   for (i = 0; i < len; i++)
00471     output[i] = input[i];
00472 }
00473 
00474 
00475 
00476 // Note: Replace "for loop" with standard memset if possible.
00477 void MD5::memset (uint1 *output, uint1 value, uint4 len){
00478 
00479   unsigned int i;
00480 
00481   for (i = 0; i < len; i++)
00482     output[i] = value;
00483 }
00484 
00485 
00486 
00487 // ROTATE_LEFT rotates x left n bits.
00488 
00489 inline unsigned int MD5::rotate_left  (uint4 x, uint4 n){
00490   return (x << n) | (x >> (32-n))  ;
00491 }
00492 
00493 
00494 
00495 
00496 // F, G, H and I are basic MD5 functions.
00497 
00498 inline unsigned int MD5::F            (uint4 x, uint4 y, uint4 z){
00499   return (x & y) | (~x & z);
00500 }
00501 
00502 inline unsigned int MD5::G            (uint4 x, uint4 y, uint4 z){
00503   return (x & z) | (y & ~z);
00504 }
00505 
00506 inline unsigned int MD5::H            (uint4 x, uint4 y, uint4 z){
00507   return x ^ y ^ z;
00508 }
00509 
00510 inline unsigned int MD5::I            (uint4 x, uint4 y, uint4 z){
00511   return y ^ (x | ~z);
00512 }
00513 
00514 
00515 
00516 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
00517 // Rotation is separate from addition to prevent recomputation.
00518 
00519 
00520 inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
00521                     uint4  s, uint4 ac){
00522  a += F(b, c, d) + x + ac;
00523  a = rotate_left (a, s) +b;
00524 }
00525 
00526 inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
00527                     uint4 s, uint4 ac){
00528  a += G(b, c, d) + x + ac;
00529  a = rotate_left (a, s) +b;
00530 }
00531 
00532 inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
00533                     uint4 s, uint4 ac){
00534  a += H(b, c, d) + x + ac;
00535  a = rotate_left (a, s) +b;
00536 }
00537 
00538 inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
00539                              uint4 s, uint4 ac){
00540  a += I(b, c, d) + x + ac;
00541  a = rotate_left (a, s) +b;
00542 }
00543 //--------------------------------------------------
00544 //returns md5 for a given file
00545 QString getMD5(ifstream& stream)
00546 {
00547   MD5 obj( stream );
00548   return obj.hex_digest();
00549 }
00550 //--------------------------------------------------
00551 //compares md5's for two files, returns true if they match
00552 bool filesMatch(ifstream& stream, QString oldMD5)
00553 {
00554   MD5 obj( stream );
00555   return (obj.hex_digest() == oldMD5);
00556 }
00557 //--------------------------------------------------

Generated on Tue Jun 10 23:41:21 2003 for AlbumShaper by doxygen 1.3.1