md5.cpp (10470B)
1 /* MD5 2 converted to C++ class by Frank Thilo (thilo@unix-ag.org) 3 for bzflag (http://www.bzflag.org) 4 5 based on: 6 7 md5.h and md5.c 8 reference implemantion of RFC 1321 9 10 Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 11 rights reserved. 12 13 License to copy and use this software is granted provided that it 14 is identified as the "RSA Data Security, Inc. MD5 Message-Digest 15 Algorithm" in all material mentioning or referencing this software 16 or this function. 17 18 License is also granted to make and use derivative works provided 19 that such works are identified as "derived from the RSA Data 20 Security, Inc. MD5 Message-Digest Algorithm" in all material 21 mentioning or referencing the derived work. 22 23 RSA Data Security, Inc. makes no representations concerning either 24 the merchantability of this software or the suitability of this 25 software for any particular purpose. It is provided "as is" 26 without express or implied warranty of any kind. 27 28 These notices must be retained in any copies of any part of this 29 documentation and/or software. 30 31 */ 32 33 /* interface header */ 34 #include "md5.h" 35 36 /* system implementation headers */ 37 #include <cstdio> 38 39 40 // Constants for MD5Transform routine. 41 #define S11 7 42 #define S12 12 43 #define S13 17 44 #define S14 22 45 #define S21 5 46 #define S22 9 47 #define S23 14 48 #define S24 20 49 #define S31 4 50 #define S32 11 51 #define S33 16 52 #define S34 23 53 #define S41 6 54 #define S42 10 55 #define S43 15 56 #define S44 21 57 58 /////////////////////////////////////////////// 59 60 // F, G, H and I are basic MD5 functions. 61 inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) { 62 return x&y | ~x&z; 63 } 64 65 inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) { 66 return x&z | y&~z; 67 } 68 69 inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) { 70 return x^y^z; 71 } 72 73 inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) { 74 return y ^ (x | ~z); 75 } 76 77 // rotate_left rotates x left n bits. 78 inline MD5::uint4 MD5::rotate_left(uint4 x, int n) { 79 return (x << n) | (x >> (32-n)); 80 } 81 82 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 83 // Rotation is separate from addition to prevent recomputation. 84 inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 85 a = rotate_left(a+ F(b,c,d) + x + ac, s) + b; 86 } 87 88 inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 89 a = rotate_left(a + G(b,c,d) + x + ac, s) + b; 90 } 91 92 inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 93 a = rotate_left(a + H(b,c,d) + x + ac, s) + b; 94 } 95 96 inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 97 a = rotate_left(a + I(b,c,d) + x + ac, s) + b; 98 } 99 100 ////////////////////////////////////////////// 101 102 // default ctor, just initailize 103 MD5::MD5() 104 { 105 init(); 106 } 107 108 ////////////////////////////////////////////// 109 110 // nifty shortcut ctor, compute MD5 for string and finalize it right away 111 MD5::MD5(const std::string &text) 112 { 113 init(); 114 update(text.c_str(), text.length()); 115 finalize(); 116 } 117 118 ////////////////////////////// 119 120 void MD5::init() 121 { 122 finalized=false; 123 124 count[0] = 0; 125 count[1] = 0; 126 127 // load magic initialization constants. 128 state[0] = 0x67452301; 129 state[1] = 0xefcdab89; 130 state[2] = 0x98badcfe; 131 state[3] = 0x10325476; 132 } 133 134 ////////////////////////////// 135 136 // decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4. 137 void MD5::decode(uint4 output[], const uint1 input[], size_type len) 138 { 139 for (unsigned int i = 0, j = 0; j < len; i++, j += 4) 140 output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | 141 (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); 142 } 143 144 ////////////////////////////// 145 146 // encodes input (uint4) into output (unsigned char). Assumes len is 147 // a multiple of 4. 148 void MD5::encode(uint1 output[], const uint4 input[], size_type len) 149 { 150 for (size_type i = 0, j = 0; j < len; i++, j += 4) { 151 output[j] = input[i] & 0xff; 152 output[j+1] = (input[i] >> 8) & 0xff; 153 output[j+2] = (input[i] >> 16) & 0xff; 154 output[j+3] = (input[i] >> 24) & 0xff; 155 } 156 } 157 158 ////////////////////////////// 159 160 // apply MD5 algo on a block 161 void MD5::transform(const uint1 block[blocksize]) 162 { 163 uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 164 decode (x, block, blocksize); 165 166 /* Round 1 */ 167 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ 168 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ 169 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ 170 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ 171 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ 172 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ 173 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ 174 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ 175 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ 176 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ 177 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ 178 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ 179 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ 180 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ 181 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ 182 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ 183 184 /* Round 2 */ 185 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ 186 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ 187 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ 188 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ 189 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ 190 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ 191 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ 192 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ 193 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ 194 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ 195 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ 196 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ 197 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ 198 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ 199 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ 200 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ 201 202 /* Round 3 */ 203 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ 204 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ 205 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ 206 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ 207 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ 208 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ 209 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ 210 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ 211 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ 212 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ 213 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ 214 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ 215 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ 216 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ 217 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ 218 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ 219 220 /* Round 4 */ 221 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ 222 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ 223 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ 224 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ 225 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ 226 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ 227 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ 228 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ 229 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ 230 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ 231 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ 232 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ 233 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ 234 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ 235 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ 236 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ 237 238 state[0] += a; 239 state[1] += b; 240 state[2] += c; 241 state[3] += d; 242 243 // Zeroize sensitive information. 244 memset(x, 0, sizeof x); 245 } 246 247 ////////////////////////////// 248 249 // MD5 block update operation. Continues an MD5 message-digest 250 // operation, processing another message block 251 void MD5::update(const unsigned char input[], size_type length) 252 { 253 // compute number of bytes mod 64 254 size_type index = count[0] / 8 % blocksize; 255 256 // Update number of bits 257 if ((count[0] += (length << 3)) < (length << 3)) 258 count[1]++; 259 count[1] += (length >> 29); 260 261 // number of bytes we need to fill in buffer 262 size_type firstpart = 64 - index; 263 264 size_type i; 265 266 // transform as many times as possible. 267 if (length >= firstpart) 268 { 269 // fill buffer first, transform 270 memcpy(&buffer[index], input, firstpart); 271 transform(buffer); 272 273 // transform chunks of blocksize (64 bytes) 274 for (i = firstpart; i + blocksize <= length; i += blocksize) 275 transform(&input[i]); 276 277 index = 0; 278 } 279 else 280 i = 0; 281 282 // buffer remaining input 283 memcpy(&buffer[index], &input[i], length-i); 284 } 285 286 ////////////////////////////// 287 288 // for convenience provide a verson with signed char 289 void MD5::update(const char input[], size_type length) 290 { 291 update((const unsigned char*)input, length); 292 } 293 294 ////////////////////////////// 295 296 // MD5 finalization. Ends an MD5 message-digest operation, writing the 297 // the message digest and zeroizing the context. 298 MD5& MD5::finalize() 299 { 300 static unsigned char padding[64] = { 301 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 302 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 303 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 304 }; 305 306 if (!finalized) { 307 // Save number of bits 308 unsigned char bits[8]; 309 encode(bits, count, 8); 310 311 // pad out to 56 mod 64. 312 size_type index = count[0] / 8 % 64; 313 size_type padLen = (index < 56) ? (56 - index) : (120 - index); 314 update(padding, padLen); 315 316 // Append length (before padding) 317 update(bits, 8); 318 319 // Store state in digest 320 encode(digest, state, 16); 321 322 // Zeroize sensitive information. 323 memset(buffer, 0, sizeof buffer); 324 memset(count, 0, sizeof count); 325 326 finalized=true; 327 } 328 329 return *this; 330 } 331 332 ////////////////////////////// 333 334 // return hex representation of digest as string 335 std::string MD5::hexdigest() const 336 { 337 if (!finalized) 338 return ""; 339 340 char buf[33]; 341 for (int i=0; i<16; i++) 342 sprintf(buf+i*2, "%02x", digest[i]); 343 buf[32]=0; 344 345 return std::string(buf); 346 } 347 348 ////////////////////////////// 349 350 std::ostream& operator<<(std::ostream& out, MD5 md5) 351 { 352 return out << md5.hexdigest(); 353 } 354 355 ////////////////////////////// 356 357 std::string md5(const std::string str) 358 { 359 MD5 md5 = MD5(str); 360 361 return md5.hexdigest(); 362 }