src/addon/md5.cpp

Go to the documentation of this file.
00001 //
00002 // MD5 message-digest algorithm
00003 // Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved.
00004 //
00005 // C++/object oriented translation and modification:
00006 // Copyright (C) 1995 Mordechai T. Abzug
00007 //
00008 // Further adaptations for SuperTux:
00009 // Copyright (C) 2008 Christoph Sommer <christoph.sommer@2008.expires.deltadevelopment.de>
00010 //
00011 // This translation/modification is provided "as is," without express or
00012 // implied warranty of any kind.
00013 //
00014 // The translators/modifiers do not claim:
00015 // (1) that MD5 will do what you think it does; 
00016 // (2) that this translation/ modification is accurate; or 
00017 // (3) that this software is "merchantible."
00018 //
00019 // based on:
00020 //
00021 // MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
00022 // MDDRIVER.C - test driver for MD2, MD4 and MD5
00023 // Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved.
00024 //
00025 // License to copy and use this software is granted provided that it
00026 // is identified as the "RSA Data Security, Inc. MD5 Message-Digest
00027 // Algorithm" in all material mentioning or referencing this software
00028 // or this function.
00029 // 
00030 // License is also granted to make and use derivative works provided
00031 // that such works are identified as "derived from the RSA Data
00032 // Security, Inc. MD5 Message-Digest Algorithm" in all material
00033 // mentioning or referencing the derived work.
00034 // 
00035 // RSA Data Security, Inc. makes no representations concerning either
00036 // the merchantability of this software or the suitability of this
00037 // software for any particular purpose. It is provided "as is"
00038 // without express or implied warranty of any kind.
00039 // 
00040 // These notices must be retained in any copies of any part of this
00041 // documentation and/or software.
00042 // 
00043 
00044 #include "addon/md5.hpp"
00045 
00046 #include <assert.h>
00047 #include <stdexcept>
00048 
00049 MD5::MD5() :
00050   finalized()
00051 {
00052   init();
00053 }
00054 
00055 void MD5::update (uint8_t* input, uint32_t input_length) {
00056 
00057   uint32_t input_index, buffer_index;
00058   uint32_t buffer_space; // how much space is left in buffer
00059 
00060   if (finalized) throw std::runtime_error("MD5::update: Can't update a finalized digest!");
00061 
00062   // Compute number of bytes mod 64
00063   buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
00064 
00065   // Update number of bits
00066   if ( (count[0] += ((uint32_t) input_length << 3))<((uint32_t) input_length << 3) ) count[1]++;
00067 
00068   count[1] += ((uint32_t)input_length >> 29);
00069 
00070   buffer_space = 64 - buffer_index; // how much space is left in buffer
00071 
00072   // Transform as many times as possible.
00073   if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
00074     // fill the rest of the buffer and transform
00075     memcpy (buffer + buffer_index, input, buffer_space);
00076     transform (buffer);
00077 
00078     // now, transform each 64-byte piece of the input, bypassing the buffer
00079     for (input_index = buffer_space; input_index + 63 < input_length;
00080          input_index += 64)
00081       transform (input+input_index);
00082 
00083     buffer_index = 0; // so we can buffer remaining
00084   } else
00085     input_index=0; // so we can buffer the whole input
00086 
00087   // and here we do the buffering:
00088   memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
00089 }
00090 
00091 void MD5::update(FILE *file) {
00092   uint8_t buffer[1024];
00093   int len;
00094 
00095   while ((len=fread(buffer, 1, 1024, file))) update(buffer, len);
00096 
00097   fclose (file);
00098 }
00099 
00100 void MD5::update(std::istream& stream) {
00101   uint8_t buffer[1024];
00102   int len;
00103 
00104   while (stream.good()) {
00105     stream.read((char*)buffer, 1024); // note that return value of read is unusable.
00106     len=stream.gcount();
00107     update(buffer, len);
00108   }
00109 }
00110 
00111 void MD5::update(std::ifstream& stream) {
00112   uint8_t buffer[1024];
00113   int len;
00114 
00115   while (stream.good()) {
00116     stream.read((char*)buffer, 1024); // note that return value of read is unusable.
00117     len=stream.gcount();
00118     update(buffer, len);
00119   }
00120 }
00121 
00122 MD5::MD5(FILE *file) :
00123   finalized()
00124 {
00125   init(); // must be called be all constructors
00126   update(file);
00127   finalize ();
00128 }
00129 
00130 MD5::MD5(std::istream& stream) : 
00131   finalized()
00132 {
00133   init(); // must called by all constructors
00134   update (stream);
00135   finalize();
00136 }
00137 
00138 MD5::MD5(std::ifstream& stream) :
00139   finalized()
00140 {
00141   init(); // must called by all constructors
00142   update (stream);
00143   finalize();
00144 }
00145 
00146 uint8_t* MD5::raw_digest() {
00147   uint8_t* s = new uint8_t[16];
00148 
00149   finalize();
00150 
00151   memcpy(s, digest, 16);
00152   return s;
00153 }
00154 
00155 std::string MD5::hex_digest() {
00156   int i;
00157   char* s= new char[33];
00158 
00159   finalize();
00160 
00161   for (i=0; i<16; i++) sprintf(s+i*2, "%02x", digest[i]);
00162 
00163   s[32]='\0';
00164 
00165   return s;
00166 }
00167 
00168 std::ostream& operator<<(std::ostream &stream, MD5 context) {
00169   stream << context.hex_digest();
00170   return stream;
00171 }
00172 
00173 // PRIVATE METHODS:
00174 
00175 void MD5::init() {
00176   finalized=false;
00177 
00178   // Nothing counted, so count=0
00179   count[0] = 0;
00180   count[1] = 0;
00181 
00182   // Load magic initialization constants.
00183   state[0] = 0x67452301;
00184   state[1] = 0xefcdab89;
00185   state[2] = 0x98badcfe;
00186   state[3] = 0x10325476;
00187 }
00188 
00189 void MD5::finalize() {
00190   if (finalized) return;
00191 
00192   uint8_t bits[8];
00193   unsigned int index, padLen;
00194   static uint8_t PADDING[64]={
00195     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00196     0, 0, 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
00198   };
00199 
00200   // Save number of bits
00201   encode (bits, count, 8);
00202 
00203   // Pad out to 56 mod 64.
00204   index = (uint32_t) ((count[0] >> 3) & 0x3f);
00205   padLen = (index < 56) ? (56 - index) : (120 - index);
00206   update (PADDING, padLen);
00207 
00208   // Append length (before padding)
00209   update (bits, 8);
00210 
00211   // Store state in digest
00212   encode (digest, state, 16);
00213 
00214   // Zeroize sensitive information
00215   memset (buffer, 0, sizeof(*buffer));
00216 
00217   finalized=true;
00218 }
00219 
00220 // Constants for MD5Transform routine.
00221 // Although we could use C++ style constants, defines are actually better,
00222 // since they let us easily evade scope clashes.
00223 
00224 #define S11 7
00225 #define S12 12
00226 #define S13 17
00227 #define S14 22
00228 #define S21 5
00229 #define S22 9
00230 #define S23 14
00231 #define S24 20
00232 #define S31 4
00233 #define S32 11
00234 #define S33 16
00235 #define S34 23
00236 #define S41 6
00237 #define S42 10
00238 #define S43 15
00239 #define S44 21
00240 
00241 void MD5::transform (uint8_t block[64]) {
00242   uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00243 
00244   decode (x, block, 64);
00245 
00246   assert(!finalized); // not just a user error, since the method is private
00247 
00248   /* Round 1 */
00249   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
00250   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
00251   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
00252   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
00253   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
00254   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
00255   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
00256   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
00257   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
00258   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
00259   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
00260   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
00261   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
00262   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
00263   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
00264   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
00265 
00266   /* Round 2 */
00267   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
00268   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
00269   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
00270   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
00271   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
00272   GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */
00273   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
00274   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
00275   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
00276   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
00277   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
00278   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
00279   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
00280   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
00281   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
00282   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
00283 
00284   /* Round 3 */
00285   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
00286   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
00287   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
00288   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
00289   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
00290   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
00291   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
00292   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
00293   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
00294   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
00295   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
00296   HH (b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */
00297   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
00298   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
00299   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
00300   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
00301 
00302   /* Round 4 */
00303   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
00304   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
00305   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
00306   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
00307   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
00308   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
00309   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
00310   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
00311   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
00312   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
00313   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
00314   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
00315   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
00316   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
00317   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
00318   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
00319 
00320   state[0] += a;
00321   state[1] += b;
00322   state[2] += c;
00323   state[3] += d;
00324 
00325   // Zeroize sensitive information.
00326   memset ( (uint8_t* ) x, 0, sizeof(x));
00327 }
00328 
00329 void MD5::encode (uint8_t* output, uint32_t* input, uint32_t len) {
00330   unsigned int i, j;
00331 
00332   for (i = 0, j = 0; j < len; i++, j += 4) {
00333     output[j]   = (uint8_t) (input[i] & 0xff);
00334     output[j+1] = (uint8_t) ((input[i] >> 8) & 0xff);
00335     output[j+2] = (uint8_t) ((input[i] >> 16) & 0xff);
00336     output[j+3] = (uint8_t) ((input[i] >> 24) & 0xff);
00337   }
00338 }
00339 
00340 void MD5::decode (uint32_t* output, uint8_t* input, uint32_t len) {
00341   unsigned int i, j;
00342 
00343   for (i = 0, j = 0; j < len; i++, j += 4) {
00344     output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) | (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
00345   }
00346 }
00347 
00348 // Note: Replace "for loop" with standard memcpy if possible.
00349 void MD5::memcpy (uint8_t* output, uint8_t* input, uint32_t len) {
00350   unsigned int i;
00351 
00352   for (i = 0; i < len; i++) output[i] = input[i];
00353 }
00354 
00355 // Note: Replace "for loop" with standard memset if possible.
00356 void MD5::memset (uint8_t* output, uint8_t value, uint32_t len) {
00357   unsigned int i;
00358 
00359   for (i = 0; i < len; i++) output[i] = value;
00360 }
00361 
00362 inline unsigned int MD5::rotate_left(uint32_t x, uint32_t n) {
00363   return (x << n) | (x >> (32-n));
00364 }
00365 
00366 inline unsigned int MD5::F(uint32_t x, uint32_t y, uint32_t z) {
00367   return (x & y) | (~x & z);
00368 }
00369 
00370 inline unsigned int MD5::G(uint32_t x, uint32_t y, uint32_t z) {
00371   return (x & z) | (y & ~z);
00372 }
00373 
00374 inline unsigned int MD5::H(uint32_t x, uint32_t y, uint32_t z) {
00375   return x ^ y ^ z;
00376 }
00377 
00378 inline unsigned int MD5::I(uint32_t x, uint32_t y, uint32_t z) {
00379   return y ^ (x | ~z);
00380 }
00381 
00382 inline void MD5::FF(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) {
00383   a += F(b, c, d) + x + ac;
00384   a = rotate_left (a, s) +b;
00385 }
00386 
00387 inline void MD5::GG(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) {
00388   a += G(b, c, d) + x + ac;
00389   a = rotate_left (a, s) +b;
00390 }
00391 
00392 inline void MD5::HH(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) {
00393   a += H(b, c, d) + x + ac;
00394   a = rotate_left (a, s) +b;
00395 }
00396 
00397 inline void MD5::II(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) {
00398   a += I(b, c, d) + x + ac;
00399   a = rotate_left (a, s) +b;
00400 }
00401 
00402 /* EOF */

Generated on Mon Jun 9 03:38:16 2014 for SuperTux by  doxygen 1.5.1