Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/MD5.cpp

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

Generated on Thu Jul 29 15:56:08 2004 for OpenSim by doxygen 1.3.6