PEBL 2.2
Psychology Experiment Building Language - Cross-platform psychological experiment development system
md5.cpp
Go to the documentation of this file.
1//md5.cpp
2
3/* MD5
4 converted to C++ class by Frank Thilo (thilo@unix-ag.org)
5 for bzflag (http://www.bzflag.org)
6
7 based on:
8
9 md5.h and md5.c
10 reference implemantion of RFC 1321
11
12 Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
13rights reserved.
14
15License to copy and use this software is granted provided that it
16is identified as the "RSA Data Security, Inc. MD5 Message-Digest
17Algorithm" in all material mentioning or referencing this software
18or this function.
19
20License is also granted to make and use derivative works provided
21that such works are identified as "derived from the RSA Data
22Security, Inc. MD5 Message-Digest Algorithm" in all material
23mentioning or referencing the derived work.
24
25RSA Data Security, Inc. makes no representations concerning either
26the merchantability of this software or the suitability of this
27software for any particular purpose. It is provided "as is"
28without express or implied warranty of any kind.
29
30These notices must be retained in any copies of any part of this
31documentation and/or software.
32
33*/
34
35/* interface header */
36#include "md5.h"
37
38/* system implementation headers */
39#include <cstdio>
40
41
42// Constants for MD5Transform routine.
43#define S11 7
44#define S12 12
45#define S13 17
46#define S14 22
47#define S21 5
48#define S22 9
49#define S23 14
50#define S24 20
51#define S31 4
52#define S32 11
53#define S33 16
54#define S34 23
55#define S41 6
56#define S42 10
57#define S43 15
58#define S44 21
59
61
62// F, G, H and I are basic MD5 functions.
63inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
64 return (x&y) | (~x&z);
65}
66
67inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
68 return (x&z) | (y&~z);
69}
70
71inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
72 return x^y^z;
73}
74
75inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {
76 return y ^ (x | ( ~z));
77}
78
79// rotate_left rotates x left n bits.
80inline MD5::uint4 MD5::rotate_left(uint4 x, int n) {
81 return (x << n) | (x >> (32-n));
82}
83
84// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
85// Rotation is separate from addition to prevent recomputation.
86inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
87 a = rotate_left(a+ F(b,c,d) + x + ac, s) + b;
88}
89
90inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
91 a = rotate_left(a + G(b,c,d) + x + ac, s) + b;
92}
93
94inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
95 a = rotate_left(a + H(b,c,d) + x + ac, s) + b;
96}
97
98inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
99 a = rotate_left(a + I(b,c,d) + x + ac, s) + b;
100}
101
103
104// default ctor, just initailize
106{
107 init();
108}
109
111
112// nifty shortcut ctor, compute MD5 for string and finalize it right away
113MD5::MD5(const std::string &text)
114{
115 init();
116 update(text.c_str(), (unsigned int)(text.length()));
117 finalize();
118}
119
120
122
123void MD5::init()
124{
125 finalized=false;
126
127 count[0] = 0;
128 count[1] = 0;
129
130 // load magic initialization constants.
131 state[0] = 0x67452301;
132 state[1] = 0xefcdab89;
133 state[2] = 0x98badcfe;
134 state[3] = 0x10325476;
135}
136
138
139// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
140void MD5::decode(uint4 output[], const uint1 input[], size_type len)
141{
142 for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
143 output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
144 (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
145}
146
148
149// encodes input (uint4) into output (unsigned char). Assumes len is
150// a multiple of 4.
151void MD5::encode(uint1 output[], const uint4 input[], size_type len)
152{
153 for (size_type i = 0, j = 0; j < len; i++, j += 4) {
154 output[j] = input[i] & 0xff;
155 output[j+1] = (input[i] >> 8) & 0xff;
156 output[j+2] = (input[i] >> 16) & 0xff;
157 output[j+3] = (input[i] >> 24) & 0xff;
158 }
159}
160
162
163// apply MD5 algo on a block
164void MD5::transform(const uint1 block[blocksize])
165{
166 uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
167 decode (x, block, blocksize);
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 state[0] += a;
242 state[1] += b;
243 state[2] += c;
244 state[3] += d;
245
246 // Zeroize sensitive information.
247 memset(x, 0, sizeof x);
248}
249
251
252// MD5 block update operation. Continues an MD5 message-digest
253// operation, processing another message block
254void MD5::update(const unsigned char input[], size_type length)
255{
256 // compute number of bytes mod 64
257 size_type index = count[0] / 8 % blocksize;
258
259 // Update number of bits
260 if ((count[0] += (length << 3)) < (length << 3))
261 count[1]++;
262 count[1] += (length >> 29);
263
264 // number of bytes we need to fill in buffer
265 size_type firstpart = 64 - index;
266
267 size_type i;
268
269 // transform as many times as possible.
270 if (length >= firstpart)
271 {
272 // fill buffer first, transform
273 memcpy(&buffer[index], input, firstpart);
274 transform(buffer);
275
276 // transform chunks of blocksize (64 bytes)
277 for (i = firstpart; i + blocksize <= length; i += blocksize)
278 transform(&input[i]);
279
280 index = 0;
281 }
282 else
283 i = 0;
284
285 // buffer remaining input
286 memcpy(&buffer[index], &input[i], length-i);
287}
288
290
291// for convenience provide a verson with signed char
292void MD5::update(const char input[], size_type length)
293{
294 update((const unsigned char*)input, length);
295}
296
298
299// MD5 finalization. Ends an MD5 message-digest operation, writing the
300// the message digest and zeroizing the context.
302{
303 static unsigned char padding[64] = {
304 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
307 };
308
309 if (!finalized) {
310 // Save number of bits
311 unsigned char bits[8];
312 encode(bits, count, 8);
313
314 // pad out to 56 mod 64.
315 size_type index = count[0] / 8 % 64;
316 size_type padLen = (index < 56) ? (56 - index) : (120 - index);
317 update(padding, padLen);
318
319 // Append length (before padding)
320 update(bits, 8);
321
322 // Store state in digest
323 encode(digest, state, 16);
324
325 // Zeroize sensitive information.
326 memset(buffer, 0, sizeof buffer);
327 memset(count, 0, sizeof count);
328
329 finalized=true;
330 }
331
332 return *this;
333}
334
336
337// return hex representation of digest as string
338std::string MD5::hexdigest() const
339{
340 if (!finalized)
341 return "";
342
343 char buf[33];
344 for (int i=0; i<16; i++)
345 sprintf(buf+i*2, "%02x", digest[i]);
346 buf[32]=0;
347
348 return std::string(buf);
349}
350
352
353std::ostream& operator<<(std::ostream& out, MD5 md5)
354{
355 return out << md5.hexdigest();
356}
357
359
360std::string md5(const std::string str)
361{
362 MD5 md5 = MD5(str);
363
364 return md5.hexdigest();
365}
366
367
Definition md5.h:54
MD5 & finalize()
Definition md5.cpp:301
unsigned int size_type
Definition md5.h:56
std::string hexdigest() const
Definition md5.cpp:338
void update(const unsigned char *buf, size_type length)
MD5()
Definition md5.cpp:105
#define S24
Definition md5.cpp:50
#define S33
Definition md5.cpp:53
#define S32
Definition md5.cpp:52
#define S12
Definition md5.cpp:44
#define S42
Definition md5.cpp:56
#define S11
Definition md5.cpp:43
#define S43
Definition md5.cpp:57
#define S23
Definition md5.cpp:49
#define S44
Definition md5.cpp:58
#define S14
Definition md5.cpp:46
std::string md5(const std::string str)
Definition md5.cpp:360
std::ostream & operator<<(std::ostream &out, MD5 md5)
Definition md5.cpp:353
#define S13
Definition md5.cpp:45
#define S41
Definition md5.cpp:55
#define S21
Definition md5.cpp:47
#define S22
Definition md5.cpp:48
#define S31
Definition md5.cpp:51
#define S34
Definition md5.cpp:54