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