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

Generated on Thu Nov 13 00:10:54 2003 for AlbumShaper by doxygen 1.3.4