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 "md5.hpp"
00049 
00050 #include <assert.h>
00051 #include <iostream>
00052 #include <string.h> // Edit: needed for strlen() (strings.h should
00053                     // include it but apparently does not for me)
00054 
00055 #include "global.hpp"
00056 
00057 
00058 
00059 // MD5 simple initialization method
00060 
00061 MD5::MD5()
00062     : state()
00063     , count()
00064     , buffer()
00065     , digest()
00066     , finalized(0)
00067 {
00068   init();
00069 }
00070 
00071 // MD5 block update operation. Continues an MD5 message-digest
00072 // operation, processing another message block, and updating the
00073 // context.
00074 
00075 void MD5::update (uint1 *input, uint4 input_length) {
00076 
00077   uint4 input_index, buffer_index;
00078   uint4 buffer_space;                // how much space is left in buffer
00079 
00080   if (finalized){  // so we can't update!
00081     std::cerr << "MD5::update:  Can't update a finalized digest!" << std::endl;
00082     return;
00083   }
00084 
00085   // Compute number of bytes mod 64
00086   buffer_index = static_cast<uint4>(((count[0] >> 3) & 0x3F));
00087 
00088   // Update number of bits
00089   if (  (count[0] += (static_cast<uint4>(input_length) << 3))<(static_cast<uint4>(input_length) << 3) )
00090     count[1]++;
00091 
00092   count[1] += (static_cast<uint4>(input_length) >> 29);
00093 
00094 
00095   buffer_space = 64 - buffer_index;  // how much space is left in buffer
00096 
00097   // Transform as many times as possible.
00098   if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
00099     // fill the rest of the buffer and transform
00100     memcpy (buffer + buffer_index, input, buffer_space);
00101     transform (buffer);
00102 
00103     // now, transform each 64-byte piece of the input, bypassing the buffer
00104     for (input_index = buffer_space; input_index + 63 < input_length;
00105      input_index += 64)
00106       transform (input+input_index);
00107 
00108     buffer_index = 0;  // so we can buffer remaining
00109   }
00110   else
00111     input_index=0;     // so we can buffer the whole input
00112 
00113 
00114   // and here we do the buffering:
00115   memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
00116 }
00117 
00118 // MD5 finalization. Ends an MD5 message-digest operation, writing the
00119 // the message digest and zeroizing the context.
00120 
00121 
00122 void MD5::finalize (){
00123 
00124   uint1 bits[8];
00125   uint4 index, padLen;
00126   static uint1 PADDING[64]={
00127     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00128     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00129     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00130     };
00131 
00132   if (finalized){
00133     std::cerr << "MD5::finalize:  Already finalized this digest!" << std::endl;
00134     return;
00135   }
00136 
00137   // Save number of bits
00138   encode (bits, count, 8);
00139 
00140   // Pad out to 56 mod 64.
00141   index = static_cast<uint4>((count[0] >> 3) & 0x3f);
00142   padLen = (index < 56) ? (56 - index) : (120 - index);
00143   update (PADDING, padLen);
00144 
00145   // Append length (before padding)
00146   update (bits, 8);
00147 
00148   // Store state in digest
00149   encode (digest, state, 16);
00150 
00151   // Zeroize sensitive information
00152   memset (buffer, 0, sizeof(*buffer));
00153 
00154   finalized=1;
00155 
00156 }
00157 
00158 
00159 MD5::uint1 *MD5::raw_digest()
00160 {
00161   static uint1 s[16];
00162 
00163   if (!finalized){
00164     std::cerr << "MD5::raw_digest:  Can't get digest if you haven't "<<
00165       "finalized the digest!" <<std::endl;
00166     return ( const_cast<uint1*>(reinterpret_cast<const uint1*>("")));
00167   }
00168 
00169   memcpy(s, digest, 16);
00170   return s;
00171 }
00172 
00173 // PRIVATE METHODS:
00174 
00175 void MD5::init(){
00176   finalized=0;  // we just started!
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 
00190 
00191 // Constants for MD5Transform routine.
00192 // Although we could use C++ style constants, defines are actually better,
00193 // since they let us easily evade scope clashes.
00194 
00195 #define S11 7
00196 #define S12 12
00197 #define S13 17
00198 #define S14 22
00199 #define S21 5
00200 #define S22 9
00201 #define S23 14
00202 #define S24 20
00203 #define S31 4
00204 #define S32 11
00205 #define S33 16
00206 #define S34 23
00207 #define S41 6
00208 #define S42 10
00209 #define S43 15
00210 #define S44 21
00211 
00212 
00213 
00214 
00215 // MD5 basic transformation. Transforms state based on block.
00216 void MD5::transform (uint1 block[64]){
00217 
00218   uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00219 
00220   decode (x, block, 64);
00221 
00222   assert(!finalized);  // not just a user error, since the method is private
00223 
00224   /* Round 1 */
00225   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
00226   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
00227   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
00228   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
00229   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
00230   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
00231   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
00232   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
00233   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
00234   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
00235   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
00236   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
00237   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
00238   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
00239   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
00240   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
00241 
00242  /* Round 2 */
00243   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
00244   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
00245   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
00246   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
00247   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
00248   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
00249   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
00250   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
00251   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
00252   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
00253   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
00254   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
00255   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
00256   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
00257   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
00258   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
00259 
00260   /* Round 3 */
00261   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
00262   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
00263   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
00264   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
00265   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
00266   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
00267   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
00268   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
00269   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
00270   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
00271   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
00272   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
00273   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
00274   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
00275   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
00276   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
00277 
00278   /* Round 4 */
00279   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
00280   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
00281   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
00282   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
00283   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
00284   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
00285   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
00286   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
00287   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
00288   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
00289   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
00290   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
00291   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
00292   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
00293   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
00294   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
00295 
00296   state[0] += a;
00297   state[1] += b;
00298   state[2] += c;
00299   state[3] += d;
00300 
00301   // Zeroize sensitive information.
00302   memset ( reinterpret_cast<uint1*>(x), 0, sizeof(x));
00303 
00304 }
00305 
00306 
00307 
00308 // Encodes input (UINT4) into output (uint1). Assumes len is
00309 // a multiple of 4.
00310 void MD5::encode (uint1 *output, uint4 *input, uint4 len) {
00311 
00312   uint4 i, j;
00313 
00314   for (i = 0, j = 0; j < len; i++, j += 4) {
00315     output[j]   = static_cast<uint1> (input[i] & 0xff);
00316     output[j+1] = static_cast<uint1>((input[i] >> 8) & 0xff);
00317     output[j+2] = static_cast<uint1>((input[i] >> 16) & 0xff);
00318     output[j+3] = static_cast<uint1>((input[i] >> 24) & 0xff);
00319   }
00320 }
00321 
00322 
00323 
00324 
00325 // Decodes input (uint1) into output (UINT4). Assumes len is
00326 // a multiple of 4.
00327 void MD5::decode (uint4 *output, uint1 *input, uint4 len){
00328 
00329   uint4 i, j;
00330 
00331   for (i = 0, j = 0; j < len; i++, j += 4)
00332     output[i] = (static_cast<uint4>(input[j]))
00333             | ((static_cast<uint4>(input[j+1])) << 8)
00334             | ((static_cast<uint4>(input[j+2])) << 16)
00335             | ((static_cast<uint4>(input[j+3])) << 24);
00336 }
00337 
00338 
00339 
00340 
00341 // ROTATE_LEFT rotates x left n bits.
00342 
00343 inline MD5::uint4 MD5::rotate_left  (uint4 x, uint4 n){
00344   return (x << n) | (x >> (32-n))  ;
00345 }
00346 
00347 
00348 
00349 
00350 // F, G, H and I are basic MD5 functions.
00351 
00352 inline MD5::uint4 MD5::F            (uint4 x, uint4 y, uint4 z){
00353   return (x & y) | (~x & z);
00354 }
00355 
00356 inline MD5::uint4 MD5::G            (uint4 x, uint4 y, uint4 z){
00357   return (x & z) | (y & ~z);
00358 }
00359 
00360 inline MD5::uint4 MD5::H            (uint4 x, uint4 y, uint4 z){
00361   return x ^ y ^ z;
00362 }
00363 
00364 inline MD5::uint4 MD5::I            (uint4 x, uint4 y, uint4 z){
00365   return y ^ (x | ~z);
00366 }
00367 
00368 
00369 
00370 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
00371 // Rotation is separate from addition to prevent recomputation.
00372 
00373 
00374 inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
00375             uint4  s, uint4 ac){
00376  a += F(b, c, d) + x + ac;
00377  a = rotate_left (a, s) +b;
00378 }
00379 
00380 inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
00381             uint4 s, uint4 ac){
00382  a += G(b, c, d) + x + ac;
00383  a = rotate_left (a, s) +b;
00384 }
00385 
00386 inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
00387             uint4 s, uint4 ac){
00388  a += H(b, c, d) + x + ac;
00389  a = rotate_left (a, s) +b;
00390 }
00391 
00392 inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
00393                  uint4 s, uint4 ac){
00394  a += I(b, c, d) + x + ac;
00395  a = rotate_left (a, s) +b;
00396 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:05 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs