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
Log Message:
added newline at end of file

File Contents

# User Rev Content
1 buchmann 1.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 buchmann 1.2 }