md5.cpp

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

Generated on Wed Nov 8 16:37:13 2006 for AlbumShaper by  doxygen 1.4.7