1 #include "lib.h"
2 #include "md5.h"
3
add_hexword(Str * str,Word32 w)4 static void add_hexword(Str *str, Word32 w) {
5 static char hexdigits[] = "0123456789abcdef";
6 char buf[8];
7 for (int i = 0; i < 4; i++) {
8 buf[2*i] = hexdigits[(w >> 4) & 0xf];
9 buf[2*i+1] = hexdigits[w &0xf];
10 w >>= 8;
11 }
12 str->add(buf, sizeof(buf));
13 }
14
add_word(Str * str,Word32 w)15 static void add_word(Str *str, Word32 w) {
16 char buf[4];
17 for (int i = 0; i < 4; i++) {
18 buf[i] = w & 0xff;
19 w >>= 8;
20 }
21 str->add(buf, sizeof(buf));
22 }
23
digest()24 MD5Digest MD5::digest() {
25 return state;
26 }
27
hexdigest()28 Str *MD5::hexdigest() {
29 Str *result = new Str(32);
30 finish();
31 add_hexword(result, state.a);
32 add_hexword(result, state.b);
33 add_hexword(result, state.c);
34 add_hexword(result, state.d);
35 return result;
36 }
37
bytedigest()38 Str *MD5::bytedigest() {
39 Str *result = new Str(16);
40 finish();
41 add_word(result, state.a);
42 add_word(result, state.b);
43 add_word(result, state.c);
44 add_word(result, state.d);
45 return result;
46 }
47
digest(Str * str)48 MD5Digest MD5::digest(Str *str) {
49 MD5 digest;
50 digest.update(str);
51 return digest.state;
52 }
53
hexdigest(Str * str)54 Str *MD5::hexdigest(Str *str) {
55 MD5 digest;
56 digest.update(str);
57 return digest.hexdigest();
58 }
59
bytedigest(Str * str)60 Str *MD5::bytedigest(Str *str) {
61 MD5 digest;
62 digest.update(str);
63 return digest.bytedigest();
64 }
65
update(const void * data,Int len)66 void MD5::update(const void *data, Int len) {
67 require(len >= 0, "negative length");
68 const unsigned char *ptr = (const unsigned char *) data;
69 total_length += len;
70 if (len + fragment_length < sizeof(fragment)) {
71 memcpy(fragment + fragment_length, ptr, len);
72 fragment_length += len;
73 return;
74 }
75 if (fragment_length != 0) {
76 memcpy(fragment + fragment_length, ptr, 64 - fragment_length);
77 update_block(fragment);
78 len -= (64 - fragment_length);
79 ptr += (64 - fragment_length);
80 fragment_length = 0;
81 }
82 while (len >= 64) {
83 update_block(ptr);
84 ptr += 64;
85 len -= 64;
86 }
87 memcpy(fragment, ptr, len);
88 fragment_length = len;
89 }
90
finish()91 void MD5::finish() {
92 if (finished)
93 return;
94 fragment[fragment_length++] = 0x80;
95 if (fragment_length > 56) {
96 memset(fragment + fragment_length, 0, 64 - fragment_length);
97 update_block(fragment);
98 fragment_length = 0;
99 }
100 memset(fragment + fragment_length, 0, 56 - fragment_length);
101 unsigned char * p = fragment + 56;
102 Word n = total_length * 8;
103 for (int i = 0; i < 8; i++) {
104 *p++ = (unsigned char) n;
105 n >>= 8;
106 }
107 update_block(fragment);
108 finished = true;
109 }
110
update_block(const unsigned char * data)111 void MD5::update_block(const unsigned char *data) {
112 Word32 buf[16];
113 Word32 a = state.a;
114 Word32 b = state.b;
115 Word32 c = state.c;
116 Word32 d = state.d;
117 for (int i = 0; i < 16; i++) {
118 Word32 t = *data++;
119 t |= (*data++) << 8;
120 t |= (*data++) << 16;
121 t |= (*data++) << 24;
122 buf[i] = t;
123 }
124 #include "md5block.h"
125 state.a += a;
126 state.b += b;
127 state.c += c;
128 state.d += d;
129 }
130