ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/cbrown/Development/Plotting/Modules/md5/md5.C
Revision: 1.2
Committed: Fri Jun 28 15:01:17 2013 UTC (11 years, 10 months ago) by buchmann
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +1 -1 lines
Error occurred while calculating annotation data.
Log Message:
added newline at end of file

File Contents

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