1/* MD5
2converted to C++ class by Frank Thilo (thilo@unix-ag.org)
3for bzflag (http://www.bzflag.org)
4
5based on:
6
7md5.h and md5.c
8reference implemantion of RFC 1321
9
10Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
11rights reserved.
12
13License to copy and use this software is granted provided that it
14is identified as the "RSA Data Security, Inc. MD5 Message-Digest
15Algorithm" in all material mentioning or referencing this software
16or this function.
17
18License is also granted to make and use derivative works provided
19that such works are identified as "derived from the RSA Data
20Security, Inc. MD5 Message-Digest Algorithm" in all material
21mentioning or referencing the derived work.
22
23RSA Data Security, Inc. makes no representations concerning either
24the merchantability of this software or the suitability of this
25software for any particular purpose. It is provided "as is"
26without express or implied warranty of any kind.
27
28These notices must be retained in any copies of any part of this
29documentation and/or software.
30
31*/
32
33/* interface header */
34#include "ThirdParty/md5.h"
35
36/* system implementation headers */
37#include <cstdio>
38#include <assert.h>
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.
61inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
62 return (x&y) | (~x&z);
63}
64
65inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
66 return (x&z) | (y&~z);
67}
68
69inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
70 return x^y^z;
71}
72
73inline 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.
78inline 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.
84inline 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
88inline 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
92inline 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
96inline 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
103MD5::MD5()
104{
105 init();
106}
107
108//////////////////////////////////////////////
109
110// nifty shortcut ctor, compute MD5 for string and finalize it right away
111MD5::MD5(const std::string &text)
112{
113 init();
114 update(text.c_str(), (size_type)text.length());
115 finalize();
116}
117
118//////////////////////////////
119
120void 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.
137void 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.
148void 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
161void 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
251void 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
289void 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.
298MD5& 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#ifdef _MSC_VER
335# pragma warning(push)
336# pragma warning(disable: 4996)
337#endif
338
339// return hex representation of digest as string
340std::string MD5::hexdigest() const
341{
342 if (!finalized)
343 return "";
344
345 char buf[33];
346 for (int i = 0; i<16; i++)
347 sprintf(buf + i * 2, "%02x", digest[i]);
348 buf[32] = 0;
349
350 return std::string(buf);
351}
352
353#ifdef _MSC_VER
354# pragma warning(pop)
355#endif
356
357// return a copy of the digest in the provided buffer
358void MD5::decdigest(unsigned char* buf, size_type length)
359{
360 assert(length == 16);
361
362 memcpy(buf, digest, length);
363}
364
365//////////////////////////////
366
367std::string md5(const std::string str)
368{
369 MD5 md5 = MD5(str);
370
371 return md5.hexdigest();
372}