Slightly modified MD5 lib. Allows access to raw binary instead of hexadecimal ascii.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers md5.c Source File

md5.c

00001 /* MD5
00002  converted to C++ class by Frank Thilo (thilo@unix-ag.org)
00003  for bzflag (http://www.bzflag.org)
00004 
00005    based on:
00006 
00007    md5.h and md5.c
00008    reference implemantion of RFC 1321
00009 
00010    Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
00011 rights reserved.
00012 
00013 License to copy and use this software is granted provided that it
00014 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
00015 Algorithm" in all material mentioning or referencing this software
00016 or this function.
00017 
00018 License is also granted to make and use derivative works provided
00019 that such works are identified as "derived from the RSA Data
00020 Security, Inc. MD5 Message-Digest Algorithm" in all material
00021 mentioning or referencing the derived work.
00022 
00023 RSA Data Security, Inc. makes no representations concerning either
00024 the merchantability of this software or the suitability of this
00025 software for any particular purpose. It is provided "as is"
00026 without express or implied warranty of any kind.
00027 
00028 These notices must be retained in any copies of any part of this
00029 documentation and/or software.
00030 
00031 */
00032 
00033 /* interface header */
00034 #include "md5.h"
00035 
00036 /* system implementation headers */
00037 #include <stdio.h>
00038 #include <string.h>
00039 
00040 
00041 // Constants for MD5Transform routine.
00042 #define S11 7
00043 #define S12 12
00044 #define S13 17
00045 #define S14 22
00046 #define S21 5
00047 #define S22 9
00048 #define S23 14
00049 #define S24 20
00050 #define S31 4
00051 #define S32 11
00052 #define S33 16
00053 #define S34 23
00054 #define S41 6
00055 #define S42 10
00056 #define S43 15
00057 #define S44 21
00058 
00059 ///////////////////////////////////////////////
00060 
00061 // F, G, H and I are basic MD5 functions.
00062 inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
00063   return x&y | ~x&z;
00064 }
00065 
00066 inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
00067   return x&z | y&~z;
00068 }
00069 
00070 inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
00071   return x^y^z;
00072 }
00073 
00074 inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {
00075   return y ^ (x | ~z);
00076 }
00077 
00078 // rotate_left rotates x left n bits.
00079 inline MD5::uint4 MD5::rotate_left(uint4 x, int n) {
00080   return (x << n) | (x >> (32-n));
00081 }
00082 
00083 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
00084 // Rotation is separate from addition to prevent recomputation.
00085 inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
00086   a = rotate_left(a+ F(b,c,d) + x + ac, s) + b;
00087 }
00088 
00089 inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
00090   a = rotate_left(a + G(b,c,d) + x + ac, s) + b;
00091 }
00092 
00093 inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
00094   a = rotate_left(a + H(b,c,d) + x + ac, s) + b;
00095 }
00096 
00097 inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
00098   a = rotate_left(a + I(b,c,d) + x + ac, s) + b;
00099 }
00100 
00101 //////////////////////////////////////////////
00102 
00103 // default ctor, just initailize
00104 MD5::MD5()
00105 {
00106   init();
00107 }
00108 
00109 //////////////////////////////////////////////
00110 
00111 // nifty shortcut ctor, compute MD5 for string and finalize it right away
00112 MD5::MD5(const std::string &text)
00113 {
00114   init();
00115   update(text.c_str(), text.length());
00116   finalize();
00117 }
00118 
00119 //////////////////////////////
00120 
00121 void MD5::init()
00122 {
00123   finalized=false;
00124 
00125   count[0] = 0;
00126   count[1] = 0;
00127 
00128   // load magic initialization constants.
00129   state[0] = 0x67452301;
00130   state[1] = 0xefcdab89;
00131   state[2] = 0x98badcfe;
00132   state[3] = 0x10325476;
00133 }
00134 
00135 //////////////////////////////
00136 
00137 // decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
00138 void MD5::decode(uint4 output[], const uint1 input[], size_type len)
00139 {
00140   for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
00141     output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
00142       (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
00143 }
00144 
00145 //////////////////////////////
00146 
00147 // encodes input (uint4) into output (unsigned char). Assumes len is
00148 // a multiple of 4.
00149 void MD5::encode(uint1 output[], const uint4 input[], size_type len)
00150 {
00151   for (size_type i = 0, j = 0; j < len; i++, j += 4) {
00152     output[j] = input[i] & 0xff;
00153     output[j+1] = (input[i] >> 8) & 0xff;
00154     output[j+2] = (input[i] >> 16) & 0xff;
00155     output[j+3] = (input[i] >> 24) & 0xff;
00156   }
00157 }
00158 
00159 //////////////////////////////
00160 
00161 // apply MD5 algo on a block
00162 void MD5::transform(const uint1 block[blocksize])
00163 {
00164   uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00165   decode (x, block, blocksize);
00166 
00167   /* Round 1 */
00168   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
00169   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
00170   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
00171   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
00172   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
00173   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
00174   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
00175   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
00176   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
00177   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
00178   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
00179   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
00180   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
00181   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
00182   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
00183   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
00184 
00185   /* Round 2 */
00186   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
00187   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
00188   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
00189   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
00190   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
00191   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
00192   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
00193   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
00194   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
00195   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
00196   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
00197   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
00198   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
00199   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
00200   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
00201   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
00202 
00203   /* Round 3 */
00204   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
00205   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
00206   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
00207   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
00208   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
00209   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
00210   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
00211   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
00212   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
00213   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
00214   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
00215   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
00216   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
00217   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
00218   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
00219   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
00220 
00221   /* Round 4 */
00222   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
00223   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
00224   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
00225   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
00226   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
00227   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
00228   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
00229   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
00230   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
00231   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
00232   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
00233   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
00234   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
00235   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
00236   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
00237   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
00238 
00239   state[0] += a;
00240   state[1] += b;
00241   state[2] += c;
00242   state[3] += d;
00243 
00244   // Zeroize sensitive information.
00245   memset(x, 0, sizeof x);
00246 }
00247 
00248 //////////////////////////////
00249 
00250 // MD5 block update operation. Continues an MD5 message-digest
00251 // operation, processing another message block
00252 void MD5::update(const unsigned char input[], size_type length)
00253 {
00254   // compute number of bytes mod 64
00255   size_type index = count[0] / 8 % blocksize;
00256 
00257   // Update number of bits
00258   if ((count[0] += (length << 3)) < (length << 3))
00259     count[1]++;
00260   count[1] += (length >> 29);
00261 
00262   // number of bytes we need to fill in buffer
00263   size_type firstpart = 64 - index;
00264 
00265   size_type i;
00266 
00267   // transform as many times as possible.
00268   if (length >= firstpart)
00269   {
00270     // fill buffer first, transform
00271     memcpy(&buffer[index], input, firstpart);
00272     transform(buffer);
00273 
00274     // transform chunks of blocksize (64 bytes)
00275     for (i = firstpart; i + blocksize <= length; i += blocksize)
00276       transform(&input[i]);
00277 
00278     index = 0;
00279   }
00280   else
00281     i = 0;
00282 
00283   // buffer remaining input
00284   memcpy(&buffer[index], &input[i], length-i);
00285 }
00286 
00287 //////////////////////////////
00288 
00289 // for convenience provide a verson with signed char
00290 void MD5::update(const char input[], size_type length)
00291 {
00292   update((const unsigned char*)input, length);
00293 }
00294 
00295 //////////////////////////////
00296 
00297 // MD5 finalization. Ends an MD5 message-digest operation, writing the
00298 // the message digest and zeroizing the context.
00299 MD5& MD5::finalize()
00300 {
00301   static unsigned char padding[64] = {
00302     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00303     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00304     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00305   };
00306 
00307   if (!finalized) {
00308     // Save number of bits
00309     unsigned char bits[8];
00310     encode(bits, count, 8);
00311 
00312     // pad out to 56 mod 64.
00313     size_type index = count[0] / 8 % 64;
00314     size_type padLen = (index < 56) ? (56 - index) : (120 - index);
00315     update(padding, padLen);
00316 
00317     // Append length (before padding)
00318     update(bits, 8);
00319 
00320     // Store state in digest
00321     encode(digest, state, 16);
00322 
00323     // Zeroize sensitive information.
00324     memset(buffer, 0, sizeof buffer);
00325     memset(count, 0, sizeof count);
00326 
00327     finalized=true;
00328   }
00329 
00330   return *this;
00331 }
00332 
00333 //////////////////////////////
00334 
00335 // return hex representation of digest as string
00336 std::string MD5::hexdigest () const
00337 {
00338   if (!finalized)
00339     return "";
00340 
00341   char buf[33];
00342   for (int i=0; i<16; i++)
00343     sprintf(buf+i*2, "%02x", digest[i]);
00344   buf[32]=0;
00345 
00346   return std::string(buf);
00347 }
00348 
00349 //////////////////////////////
00350 
00351 std::string md5(const std::string str)
00352 {
00353     MD5 md5 = MD5(str);
00354 
00355     return md5.hexdigest ();
00356 }