Slightly modified MD5 lib. Allows access to raw binary instead of hexadecimal ascii.
Embed:
(wiki syntax)
Show/hide line numbers
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 }
Generated on Thu Sep 8 2022 01:08:55 by
![doxygen](doxygen.png)