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

vos/metaobjects/misc/md5.cc

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 "md5.hh"
00049 
00050 #include <assert.h>
00051 #include <string>
00052 #include <iostream>
00053 
00054 
00055 
00056 
00057 // _MD5 simple initialization method
00058 
00059 _MD5::_MD5(){
00060 
00061   init();
00062 
00063 }
00064 
00065 
00066 
00067 
00068 // _MD5 block update operation. Continues an _MD5 message-digest
00069 // operation, processing another message block, and updating the
00070 // context.
00071 
00072 void _MD5::update (uint1 *input, uint4 input_length) {
00073 
00074   uint4 input_index, buffer_index;
00075   uint4 buffer_space;                // how much space is left in buffer
00076 
00077   if (finalized){  // so we can't update!
00078     cerr << "_MD5::update:  Can't update a finalized digest!" << endl;
00079     return;
00080   }
00081 
00082   // Compute number of bytes mod 64
00083   buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
00084 
00085   // Update number of bits
00086   if (  (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
00087     count[1]++;
00088 
00089   count[1] += ((uint4)input_length >> 29);
00090 
00091 
00092   buffer_space = 64 - buffer_index;  // how much space is left in buffer
00093 
00094   // Transform as many times as possible.
00095   if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
00096     // fill the rest of the buffer and transform
00097     memcpy (buffer + buffer_index, input, buffer_space);
00098     transform (buffer);
00099 
00100     // now, transform each 64-byte piece of the input, bypassing the buffer
00101     for (input_index = buffer_space; input_index + 63 < input_length;
00102      input_index += 64)
00103       transform (input+input_index);
00104 
00105     buffer_index = 0;  // so we can buffer remaining
00106   }
00107   else
00108     input_index=0;     // so we can buffer the whole input
00109 
00110 
00111   // and here we do the buffering:
00112   memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
00113 }
00114 
00115 
00116 
00117 // _MD5 update for files.
00118 // Like above, except that it works on files (and uses above as a primitive.)
00119 
00120 void _MD5::update(FILE *file){
00121 
00122   unsigned char buffer[1024];
00123   int len;
00124 
00125   while (len=fread(buffer, 1, 1024, file))
00126     update(buffer, len);
00127 
00128   fclose (file);
00129 
00130 }
00131 
00132 
00133 
00134 
00135 
00136 
00137 // _MD5 update for istreams.
00138 // Like update for files; see above.
00139 
00140 void _MD5::update(istream& stream){
00141 
00142   unsigned char buffer[1024];
00143   int len;
00144 
00145   while (stream.good()){
00146     stream.read((char*)buffer, 1024); // note that return value of read is unusable.
00147     len=stream.gcount();
00148     update(buffer, len);
00149   }
00150 
00151 }
00152 
00153 
00154 
00155 
00156 
00157 
00158 // _MD5 update for ifstreams.
00159 // Like update for files; see above.
00160 
00161 void _MD5::update(ifstream& stream){
00162 
00163   unsigned char buffer[1024];
00164   int len;
00165 
00166   while (stream.good()){
00167     stream.read((char*)buffer, 1024); // note that return value of read is unusable.
00168     len=stream.gcount();
00169     update(buffer, len);
00170   }
00171 
00172 }
00173 
00174 
00175 
00176 
00177 
00178 
00179 // _MD5 finalization. Ends an _MD5 message-digest operation, writing the
00180 // the message digest and zeroizing the context.
00181 
00182 
00183 void _MD5::finalize (){
00184 
00185   unsigned char bits[8];
00186   unsigned int index, padLen;
00187   static uint1 PADDING[64]={
00188     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00189     0, 0, 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
00191     };
00192 
00193   if (finalized){
00194     cerr << "_MD5::finalize:  Already finalized this digest!" << endl;
00195     return;
00196   }
00197 
00198   // Save number of bits
00199   encode (bits, count, 8);
00200 
00201   // Pad out to 56 mod 64.
00202   index = (uint4) ((count[0] >> 3) & 0x3f);
00203   padLen = (index < 56) ? (56 - index) : (120 - index);
00204   update (PADDING, padLen);
00205 
00206   // Append length (before padding)
00207   update (bits, 8);
00208 
00209   // Store state in digest
00210   encode (digest, state, 16);
00211 
00212   // Zeroize sensitive information
00213   memset (buffer, 0, sizeof(*buffer));
00214 
00215   finalized=1;
00216 
00217 }
00218 
00219 
00220 
00221 
00222 _MD5::_MD5(FILE *file){
00223 
00224   init();  // must be called be all constructors
00225   update(file);
00226   finalize ();
00227 }
00228 
00229 
00230 
00231 
00232 _MD5::_MD5(istream& stream){
00233 
00234   init();  // must called by all constructors
00235   update (stream);
00236   finalize();
00237 }
00238 
00239 
00240 
00241 _MD5::_MD5(ifstream& stream){
00242 
00243   init();  // must called by all constructors
00244   update (stream);
00245   finalize();
00246 }
00247 
00248 
00249 
00250 unsigned char *_MD5::raw_digest(){
00251 
00252   uint1 *s = new uint1[16];
00253 
00254   if (!finalized){
00255     cerr << "_MD5::raw_digest:  Can't get digest if you haven't "<<
00256       "finalized the digest!" <<endl;
00257     return ( (unsigned char*) "");
00258   }
00259 
00260   memcpy(s, digest, 16);
00261   return s;
00262 }
00263 
00264 
00265 
00266 char *_MD5::hex_digest(){
00267 
00268   int i;
00269   char *s= new char[33];
00270 
00271   if (!finalized){
00272     cerr << "_MD5::hex_digest:  Can't get digest if you haven't "<<
00273       "finalized the digest!" <<endl;
00274     return "";
00275   }
00276 
00277   for (i=0; i<16; i++)
00278     sprintf(s+i*2, "%02x", digest[i]);
00279 
00280   s[32]='\0';
00281 
00282   return s;
00283 }
00284 
00285 
00286 
00287 
00288 
00289 ostream& operator<<(ostream &stream, _MD5 context){
00290 
00291   stream << context.hex_digest();
00292   return stream;
00293 }
00294 
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 }

Generated on Tue Aug 12 03:55:44 2003 for Interreality Project - VOS by doxygen 1.3.2