1 // Copyright (C) 2003 Davis E. King (davis@dlib.net) 2 // License: Boost Software License See LICENSE.txt for the full license. 3 #ifndef DLIB_MD5_KERNEL_1_CPp_ 4 #define DLIB_MD5_KERNEL_1_CPp_ 5 #include "md5_kernel_1.h" 6 #include "../uintn.h" 7 8 #include <sstream> 9 #include <cstring> 10 11 namespace dlib 12 { 13 14 // ---------------------------------------------------------------------------------------- 15 // ---------------------------------------------------------------------------------------- 16 // ---------------------------------------------------------------------------------------- 17 18 namespace md5_stuff 19 { 20 F(uint32 x,uint32 y,uint32 z)21 inline uint32 F ( 22 uint32 x, 23 uint32 y, 24 uint32 z 25 ) 26 { 27 return ( (x&y) | ((~x)&z) ); 28 } 29 30 // ------------------------------------------------------------------------------------ 31 G(uint32 x,uint32 y,uint32 z)32 inline uint32 G ( 33 uint32 x, 34 uint32 y, 35 uint32 z 36 ) 37 { 38 return ( (x&z) | (y&(~z)) ); 39 } 40 41 // ------------------------------------------------------------------------------------ 42 H(uint32 x,uint32 y,uint32 z)43 inline uint32 H ( 44 uint32 x, 45 uint32 y, 46 uint32 z 47 ) 48 { 49 return ( x^y^z ); 50 } 51 52 // ------------------------------------------------------------------------------------ 53 I(uint32 x,uint32 y,uint32 z)54 inline uint32 I ( 55 uint32 x, 56 uint32 y, 57 uint32 z 58 ) 59 { 60 return ( y ^ (x|(~z)) ); 61 } 62 63 // ------------------------------------------------------------------------------------ 64 rotate_left(uint32 x,uint32 n)65 inline uint32 rotate_left ( 66 uint32 x, 67 uint32 n 68 ) 69 { 70 return ( (x<<n) | (x>>(32-n)) ); 71 } 72 73 // ------------------------------------------------------------------------------------ 74 FF(uint32 & a,uint32 b,uint32 c,uint32 d,uint32 x,uint32 s,uint32 ac)75 inline void FF ( 76 uint32& a, 77 uint32 b, 78 uint32 c, 79 uint32 d, 80 uint32 x, 81 uint32 s, 82 uint32 ac 83 ) 84 { 85 a += F(b, c, d) + x + ac; 86 a = rotate_left(a, s); 87 a += b; 88 } 89 90 // ------------------------------------------------------------------------------------ 91 GG(uint32 & a,uint32 b,uint32 c,uint32 d,uint32 x,uint32 s,uint32 ac)92 inline void GG ( 93 uint32& a, 94 uint32 b, 95 uint32 c, 96 uint32 d, 97 uint32 x, 98 uint32 s, 99 uint32 ac 100 ) 101 { 102 a += G(b, c, d) + x + ac; 103 a = rotate_left(a, s); 104 a += b; 105 } 106 107 // ------------------------------------------------------------------------------------ 108 HH(uint32 & a,uint32 b,uint32 c,uint32 d,uint32 x,uint32 s,uint32 ac)109 inline void HH ( 110 uint32& a, 111 uint32 b, 112 uint32 c, 113 uint32 d, 114 uint32 x, 115 uint32 s, 116 uint32 ac 117 ) 118 { 119 a += H(b, c, d) + x + ac; 120 a = rotate_left(a, s); 121 a += b; 122 } 123 124 // ------------------------------------------------------------------------------------ 125 II(uint32 & a,uint32 b,uint32 c,uint32 d,uint32 x,uint32 s,uint32 ac)126 inline void II ( 127 uint32& a, 128 uint32 b, 129 uint32 c, 130 uint32 d, 131 uint32 x, 132 uint32 s, 133 uint32 ac 134 ) 135 { 136 a += I(b, c, d) + x + ac; 137 a = rotate_left(a, s); 138 a += b; 139 } 140 141 // ------------------------------------------------------------------------------------ 142 scramble_block(uint32 & a,uint32 & b,uint32 & c,uint32 & d,uint32 * x)143 void scramble_block ( 144 uint32& a, 145 uint32& b, 146 uint32& c, 147 uint32& d, 148 uint32* x 149 ) 150 { 151 const uint32 S11 = 7; 152 const uint32 S12 = 12; 153 const uint32 S13 = 17; 154 const uint32 S14 = 22; 155 const uint32 S21 = 5; 156 const uint32 S22 = 9; 157 const uint32 S23 = 14; 158 const uint32 S24 = 20; 159 const uint32 S31 = 4; 160 const uint32 S32 = 11; 161 const uint32 S33 = 16; 162 const uint32 S34 = 23; 163 const uint32 S41 = 6; 164 const uint32 S42 = 10; 165 const uint32 S43 = 15; 166 const uint32 S44 = 21; 167 168 169 // round 1 170 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); // 1 171 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); // 2 172 FF (c, d, a, b, x[ 2], S13, 0x242070db); // 3 173 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); // 4 174 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); // 5 175 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); // 6 176 FF (c, d, a, b, x[ 6], S13, 0xa8304613); // 7 177 FF (b, c, d, a, x[ 7], S14, 0xfd469501); // 8 178 FF (a, b, c, d, x[ 8], S11, 0x698098d8); // 9 179 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); // 10 180 FF (c, d, a, b, x[10], S13, 0xffff5bb1); // 11 181 FF (b, c, d, a, x[11], S14, 0x895cd7be); // 12 182 FF (a, b, c, d, x[12], S11, 0x6b901122); // 13 183 FF (d, a, b, c, x[13], S12, 0xfd987193); // 14 184 FF (c, d, a, b, x[14], S13, 0xa679438e); // 15 185 FF (b, c, d, a, x[15], S14, 0x49b40821); // 16 186 187 // Round 2 188 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); // 17 189 GG (d, a, b, c, x[ 6], S22, 0xc040b340); // 18 190 GG (c, d, a, b, x[11], S23, 0x265e5a51); // 19 191 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); // 20 192 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); // 21 193 GG (d, a, b, c, x[10], S22, 0x2441453); // 22 194 GG (c, d, a, b, x[15], S23, 0xd8a1e681); // 23 195 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); // 24 196 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); // 25 197 GG (d, a, b, c, x[14], S22, 0xc33707d6); // 26 198 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); // 27 199 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); // 28 200 GG (a, b, c, d, x[13], S21, 0xa9e3e905); // 29 201 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); // 30 202 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); // 31 203 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); // 32 204 205 // Round 3 206 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); // 33 207 HH (d, a, b, c, x[ 8], S32, 0x8771f681); // 34 208 HH (c, d, a, b, x[11], S33, 0x6d9d6122); // 35 209 HH (b, c, d, a, x[14], S34, 0xfde5380c); // 36 210 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); // 37 211 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); // 38 212 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); // 39 213 HH (b, c, d, a, x[10], S34, 0xbebfbc70); // 40 214 HH (a, b, c, d, x[13], S31, 0x289b7ec6); // 41 215 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); // 42 216 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); // 43 217 HH (b, c, d, a, x[ 6], S34, 0x4881d05); // 44 218 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); // 45 219 HH (d, a, b, c, x[12], S32, 0xe6db99e5); // 46 220 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); // 47 221 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); // 48 222 223 // Round 4 224 II (a, b, c, d, x[ 0], S41, 0xf4292244); // 49 225 II (d, a, b, c, x[ 7], S42, 0x432aff97); // 50 226 II (c, d, a, b, x[14], S43, 0xab9423a7); // 51 227 II (b, c, d, a, x[ 5], S44, 0xfc93a039); // 52 228 II (a, b, c, d, x[12], S41, 0x655b59c3); // 53 229 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); // 54 230 II (c, d, a, b, x[10], S43, 0xffeff47d); // 55 231 II (b, c, d, a, x[ 1], S44, 0x85845dd1); // 56 232 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); // 57 233 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); // 58 234 II (c, d, a, b, x[ 6], S43, 0xa3014314); // 59 235 II (b, c, d, a, x[13], S44, 0x4e0811a1); // 60 236 II (a, b, c, d, x[ 4], S41, 0xf7537e82); // 61 237 II (d, a, b, c, x[11], S42, 0xbd3af235); // 62 238 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); // 63 239 II (b, c, d, a, x[ 9], S44, 0xeb86d391); // 64 240 } 241 242 } 243 244 // ---------------------------------------------------------------------------------------- 245 // ---------------------------------------------------------------------------------------- 246 // ---------------------------------------------------------------------------------------- 247 248 md5(const std::string & input)249 const std::string md5 ( 250 const std::string& input 251 ) 252 { 253 unsigned char output[16]; 254 md5 ( 255 reinterpret_cast<const unsigned char*>(input.data()), 256 static_cast<unsigned long>(input.size()), 257 output 258 ); 259 260 261 std::stringstream temp; 262 for (int i = 0; i < 16; ++i) 263 { 264 temp.fill('0'); 265 temp.width(2); 266 temp << std::hex << static_cast<unsigned int>(output[i]); 267 } 268 269 return temp.str(); 270 } 271 272 // ---------------------------------------------------------------------------------------- 273 md5(const unsigned char * input,unsigned long len,unsigned char * output)274 void md5 ( 275 const unsigned char* input, 276 unsigned long len, 277 unsigned char* output 278 ) 279 { 280 using namespace md5_stuff; 281 282 283 284 285 // make a temp version of input with enough space for padding and len appended 286 unsigned long extra_len = 64-len%64; 287 if (extra_len <= 8) 288 extra_len += 64; 289 unsigned char* temp = new unsigned char[extra_len + len]; 290 291 // number of 16 word blocks 292 const unsigned long N = (extra_len + len)/64; 293 294 const unsigned char* input2 = input; 295 unsigned char* temp2 = temp; 296 unsigned char* end = temp+len; 297 298 // copy input into temp 299 while (temp2 != end) 300 { 301 *temp2 = *input2; 302 ++temp2; 303 ++input2; 304 } 305 306 // pad temp 307 end += extra_len-8; 308 *temp2 = static_cast<unsigned char>(0x80); 309 ++temp2; 310 while (temp2 != end) 311 { 312 *temp2 = 0; 313 ++temp2; 314 } 315 316 // make len the number of bits in the original message 317 // but first multiply len by 8 and since len is only 32 bits the number might 318 // overflow so we will carry out the multiplication manually and end up with 319 // the result in the base 65536 number with three digits 320 // result = low + high*65536 + upper*65536*65536 321 unsigned long low = len & 0xFFFF; 322 unsigned long high = len >> 16; 323 unsigned long upper; 324 unsigned long tmp; 325 tmp = low * 8; 326 low = tmp & 0xFFFF; 327 tmp = high * 8 + (tmp>>16); 328 high = tmp & 0xFFFF; 329 upper = tmp >> 16; 330 331 332 // append the length 333 *temp2 = static_cast<unsigned char>(low&0xFF); 334 ++temp2; 335 *temp2 = static_cast<unsigned char>((low>>8)&0xFF); 336 ++temp2; 337 *temp2 = static_cast<unsigned char>((high)&0xFF); 338 ++temp2; 339 *temp2 = static_cast<unsigned char>((high>>8)&0xFF); 340 ++temp2; 341 *temp2 = static_cast<unsigned char>((upper)&0xFF);; 342 ++temp2; 343 *temp2 = static_cast<unsigned char>((upper>>8)&0xFF);; 344 ++temp2; 345 *temp2 = 0; 346 ++temp2; 347 *temp2 = 0; 348 349 350 uint32 a = 0x67452301; 351 uint32 b = 0xefcdab89; 352 uint32 c = 0x98badcfe; 353 uint32 d = 0x10325476; 354 355 356 // an array of 16 words 357 uint32 x[16]; 358 359 for (unsigned long i = 0; i < N; ++i) 360 { 361 362 // copy a block of 16 words from m into x 363 for (unsigned long j = 0; j < 16; ++j) 364 { 365 x[j] = ( 366 (static_cast<uint32>(temp[4*(j + 16*i) + 3]) << 24) | 367 (static_cast<uint32>(temp[4*(j + 16*i) + 2]) << 16) | 368 (static_cast<uint32>(temp[4*(j + 16*i) + 1]) << 8 ) | 369 (static_cast<uint32>(temp[4*(j + 16*i) ]) ) 370 ); 371 } 372 373 uint32 aa = a; 374 uint32 bb = b; 375 uint32 cc = c; 376 uint32 dd = d; 377 378 379 scramble_block(a,b,c,d,x); 380 381 382 a = a + aa; 383 b = b + bb; 384 c = c + cc; 385 d = d + dd; 386 387 } 388 389 390 // put a, b, c, and d into output 391 output[0] = static_cast<unsigned char>((a) &0xFF); 392 output[1] = static_cast<unsigned char>((a>>8) &0xFF); 393 output[2] = static_cast<unsigned char>((a>>16)&0xFF); 394 output[3] = static_cast<unsigned char>((a>>24)&0xFF); 395 396 output[4] = static_cast<unsigned char>((b) &0xFF); 397 output[5] = static_cast<unsigned char>((b>>8) &0xFF); 398 output[6] = static_cast<unsigned char>((b>>16)&0xFF); 399 output[7] = static_cast<unsigned char>((b>>24)&0xFF); 400 401 output[8] = static_cast<unsigned char>((c) &0xFF); 402 output[9] = static_cast<unsigned char>((c>>8) &0xFF); 403 output[10] = static_cast<unsigned char>((c>>16)&0xFF); 404 output[11] = static_cast<unsigned char>((c>>24)&0xFF); 405 406 output[12] = static_cast<unsigned char>((d) &0xFF); 407 output[13] = static_cast<unsigned char>((d>>8) &0xFF); 408 output[14] = static_cast<unsigned char>((d>>16)&0xFF); 409 output[15] = static_cast<unsigned char>((d>>24)&0xFF); 410 411 delete [] temp; 412 } 413 414 // ---------------------------------------------------------------------------------------- 415 md5(std::istream & input)416 const std::string md5 ( 417 std::istream& input 418 ) 419 { 420 unsigned char output[16]; 421 md5 ( 422 input, 423 output 424 ); 425 426 427 std::stringstream temp; 428 for (int i = 0; i < 16; ++i) 429 { 430 temp.fill('0'); 431 temp.width(2); 432 temp << std::hex << static_cast<unsigned int>(output[i]); 433 } 434 435 return temp.str(); 436 } 437 438 // ---------------------------------------------------------------------------------------- 439 md5(std::istream & input,unsigned char * output)440 void md5 ( 441 std::istream& input, 442 unsigned char* output 443 ) 444 { 445 using namespace md5_stuff; 446 447 448 449 450 uint32 a = 0x67452301; 451 uint32 b = 0xefcdab89; 452 uint32 c = 0x98badcfe; 453 uint32 d = 0x10325476; 454 455 456 457 std::streamsize len = 0; 458 459 // an array of 16 words 460 uint32 x[16]; 461 unsigned char temp[64]; 462 463 464 465 bool write_length = false; 466 bool at_end = false; 467 std::streambuf& inputbuf = *input.rdbuf(); 468 while(!at_end) 469 { 470 std::streamsize num = inputbuf.sgetn(reinterpret_cast<char*>(temp),64); 471 len += num; 472 473 // if we hit the end of the stream then pad and add length 474 if (num < 64) 475 { 476 at_end = true; 477 unsigned char* temp2 = temp; 478 unsigned char* end; 479 if (num < 56) 480 end = temp+56; 481 else 482 end = temp+64; 483 484 temp2 += num; 485 486 // apply padding 487 *temp2 = 0x80; 488 ++temp2; 489 while (temp2 != end) 490 { 491 *temp2 = 0; 492 ++temp2; 493 } 494 495 496 if (num < 56) 497 { 498 write_length = true; 499 // make len the number of bits in the original message 500 // but first multiply len by 8 and since len is only 32 bits the number might 501 // overflow so we will carry out the multiplication manually and end up with 502 // the result in the base 65536 number with three digits 503 // result = low + high*65536 + upper*65536*65536 504 unsigned long low = len & 0xFFFF; 505 unsigned long high = len >> 16; 506 unsigned long upper; 507 unsigned long tmp; 508 tmp = low * 8; 509 low = tmp & 0xFFFF; 510 tmp = high * 8 + (tmp>>16); 511 high = tmp & 0xFFFF; 512 upper = tmp >> 16; 513 514 515 // append the length 516 *temp2 = static_cast<unsigned char>(low&0xFF); 517 ++temp2; 518 *temp2 = static_cast<unsigned char>((low>>8)&0xFF); 519 ++temp2; 520 *temp2 = static_cast<unsigned char>((high)&0xFF); 521 ++temp2; 522 *temp2 = static_cast<unsigned char>((high>>8)&0xFF); 523 ++temp2; 524 *temp2 = static_cast<unsigned char>((upper)&0xFF);; 525 ++temp2; 526 *temp2 = static_cast<unsigned char>((upper>>8)&0xFF);; 527 ++temp2; 528 *temp2 = 0; 529 ++temp2; 530 *temp2 = 0; 531 } 532 533 534 } 535 536 537 // copy a block of 16 words from m into x 538 for (unsigned long i = 0; i < 16; ++i) 539 { 540 x[i] = ( 541 (static_cast<uint32>(temp[4*i + 3]) << 24) | 542 (static_cast<uint32>(temp[4*i + 2]) << 16) | 543 (static_cast<uint32>(temp[4*i + 1]) << 8 ) | 544 (static_cast<uint32>(temp[4*i ]) ) 545 ); 546 } 547 548 549 uint32 aa = a; 550 uint32 bb = b; 551 uint32 cc = c; 552 uint32 dd = d; 553 554 555 scramble_block(a,b,c,d,x); 556 557 558 a = a + aa; 559 b = b + bb; 560 c = c + cc; 561 d = d + dd; 562 563 } 564 565 if (!write_length) 566 { 567 uint64 temp = len*8; 568 569 uint32 aa = a; 570 uint32 bb = b; 571 uint32 cc = c; 572 uint32 dd = d; 573 574 std::memset(x, 0, sizeof(x)); 575 x[15] = (temp>>32); 576 x[14] = (temp&0xFFFFFFFF); 577 578 scramble_block(a,b,c,d,x); 579 580 581 a = a + aa; 582 b = b + bb; 583 c = c + cc; 584 d = d + dd; 585 586 } 587 588 589 // put a, b, c, and d into output 590 output[0] = static_cast<unsigned char>((a) &0xFF); 591 output[1] = static_cast<unsigned char>((a>>8) &0xFF); 592 output[2] = static_cast<unsigned char>((a>>16)&0xFF); 593 output[3] = static_cast<unsigned char>((a>>24)&0xFF); 594 595 output[4] = static_cast<unsigned char>((b) &0xFF); 596 output[5] = static_cast<unsigned char>((b>>8) &0xFF); 597 output[6] = static_cast<unsigned char>((b>>16)&0xFF); 598 output[7] = static_cast<unsigned char>((b>>24)&0xFF); 599 600 output[8] = static_cast<unsigned char>((c) &0xFF); 601 output[9] = static_cast<unsigned char>((c>>8) &0xFF); 602 output[10] = static_cast<unsigned char>((c>>16)&0xFF); 603 output[11] = static_cast<unsigned char>((c>>24)&0xFF); 604 605 output[12] = static_cast<unsigned char>((d) &0xFF); 606 output[13] = static_cast<unsigned char>((d>>8) &0xFF); 607 output[14] = static_cast<unsigned char>((d>>16)&0xFF); 608 output[15] = static_cast<unsigned char>((d>>24)&0xFF); 609 610 input.clear(std::ios::eofbit); 611 } 612 613 // ---------------------------------------------------------------------------------------- 614 615 } 616 #endif // DLIB_MD5_KERNEL_1_CPp_ 617 618