Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/md5.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (show annotations) (download) (as text)
Wed Mar 9 10:14:40 2011 UTC (13 years, 2 months ago) by okadu
File MIME type: text/x-c++src
File size: 13084 byte(s)
[okadu] Visual Studio 2010 でのビルド環境を暫定設定。
1 // MD5.CC - source code for the C++/object oriented translation and
2 // modification of MD5.
3
4 // Translation and modification (c) 1995 by Mordechai T. Abzug
5
6 // This translation/ modification is provided "as is," without express or
7 // implied warranty of any kind.
8
9 // The translator/ modifier does not claim (1) that MD5 will do what you think
10 // it does; (2) that this translation/ modification is accurate; or (3) that
11 // this software is "merchantible." (Language for this disclaimer partially
12 // copied from the disclaimer below).
13
14 /* based on:
15
16 MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
17 MDDRIVER.C - test driver for MD2, MD4 and MD5
18
19
20 Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
21 rights reserved.
22
23 License to copy and use this software is granted provided that it
24 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
25 Algorithm" in all material mentioning or referencing this software
26 or this function.
27
28 License is also granted to make and use derivative works provided
29 that such works are identified as "derived from the RSA Data
30 Security, Inc. MD5 Message-Digest Algorithm" in all material
31 mentioning or referencing the derived work.
32
33 RSA Data Security, Inc. makes no representations concerning either
34 the merchantability of this software or the suitability of this
35 software for any particular purpose. It is provided "as is"
36 without express or implied warranty of any kind.
37
38 These notices must be retained in any copies of any part of this
39 documentation and/or software.
40
41 */
42
43
44
45
46
47
48 #include "md5.h"
49
50 #include <assert.h>
51 //#include <strings.h>
52 #include <iostream>
53
54 using namespace std;
55
56
57 // MD5 simple initialization method
58
59 MD5::MD5(){
60
61 init();
62
63 }
64
65
66
67
68 // MD5 block update operation. Continues an MD5 message-digest
69 // operation, processing another message block, and updating the
70 // context.
71
72 void MD5::update (uint1 *input, uint4 input_length) {
73
74 uint4 input_index, buffer_index;
75 uint4 buffer_space; // how much space is left in buffer
76
77 if (finalized){ // so we can't update!
78 cerr << "MD5::update: Can't update a finalized digest!" << endl;
79 return;
80 }
81
82 // Compute number of bytes mod 64
83 buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
84
85 // Update number of bits
86 if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
87 count[1]++;
88
89 count[1] += ((uint4)input_length >> 29);
90
91
92 buffer_space = 64 - buffer_index; // how much space is left in buffer
93
94 // Transform as many times as possible.
95 if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
96 // fill the rest of the buffer and transform
97 memcpy (buffer + buffer_index, input, buffer_space);
98 transform (buffer);
99
100 // now, transform each 64-byte piece of the input, bypassing the buffer
101 for (input_index = buffer_space; input_index + 63 < input_length;
102 input_index += 64)
103 transform (input+input_index);
104
105 buffer_index = 0; // so we can buffer remaining
106 }
107 else
108 input_index=0; // so we can buffer the whole input
109
110
111 // and here we do the buffering:
112 memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
113 }
114
115
116
117 // MD5 update for files.
118 // Like above, except that it works on files (and uses above as a primitive.)
119
120 void MD5::update(FILE *file){
121
122 unsigned char buffer[1024];
123 int len;
124
125 while (len=fread(buffer, 1, 1024, file))
126 update(buffer, len);
127
128 fclose (file);
129
130 }
131
132
133
134
135 /*
136
137 // MD5 update for istreams.
138 // Like update for files; see above.
139
140 void MD5::update(istream& stream){
141
142 unsigned char buffer[1024];
143 int len;
144
145 while (stream.good()){
146 stream.read(buffer, 1024); // note that return value of read is unusable.
147 len=stream.gcount();
148 update(buffer, len);
149 }
150
151 }
152
153
154
155
156
157
158 // MD5 update for ifstreams.
159 // Like update for files; see above.
160
161 void MD5::update(ifstream& stream){
162
163 unsigned char buffer[1024];
164 int len;
165
166 while (stream.good()){
167 stream.read(buffer, 1024); // note that return value of read is unusable.
168 len=stream.gcount();
169 update(buffer, len);
170 }
171
172 }
173
174 */
175
176
177
178
179 // MD5 finalization. Ends an MD5 message-digest operation, writing the
180 // the message digest and zeroizing the context.
181
182
183 void MD5::finalize (){
184
185 unsigned char bits[8];
186 unsigned int index, padLen;
187 static uint1 PADDING[64]={
188 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
190 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
191 };
192
193 if (finalized){
194 cerr << "MD5::finalize: Already finalized this digest!" << endl;
195 return;
196 }
197
198 // Save number of bits
199 encode (bits, count, 8);
200
201 // Pad out to 56 mod 64.
202 index = (uint4) ((count[0] >> 3) & 0x3f);
203 padLen = (index < 56) ? (56 - index) : (120 - index);
204 update (PADDING, padLen);
205
206 // Append length (before padding)
207 update (bits, 8);
208
209 // Store state in digest
210 encode (digest, state, 16);
211
212 // Zeroize sensitive information
213 memset (buffer, 0, sizeof(*buffer));
214
215 finalized=1;
216
217 }
218
219
220
221
222 MD5::MD5(FILE *file){
223
224 init(); // must be called be all constructors
225 update(file);
226 finalize ();
227 }
228
229
230 /*
231
232 MD5::MD5(istream& stream){
233
234 init(); // must called by all constructors
235 update (stream);
236 finalize();
237 }
238
239
240
241 MD5::MD5(ifstream& stream){
242
243 init(); // must called by all constructors
244 update (stream);
245 finalize();
246 }
247
248 */
249
250 unsigned char *MD5::raw_digest(){
251
252 uint1 *s = new uint1[16];
253
254 if (!finalized){
255 cerr << "MD5::raw_digest: Can't get digest if you haven't "<<
256 "finalized the digest!" <<endl;
257 return ( (unsigned char*) "");
258 }
259
260 memcpy(s, digest, 16);
261 return s;
262 }
263
264
265
266 char *MD5::hex_digest(){
267
268 int i;
269 char *s= new char[33];
270
271 if (!finalized){
272 cerr << "MD5::hex_digest: Can't get digest if you haven't "<<
273 "finalized the digest!" <<endl;
274 return "";
275 }
276
277 for (i=0; i<16; i++)
278 sprintf(s+i*2, "%02x", digest[i]);
279
280 s[32]='\0';
281
282 return s;
283 }
284
285
286
287
288
289 ostream& operator<<(ostream &stream, MD5 context){
290
291 stream << context.hex_digest();
292 return stream;
293 }
294
295
296
297
298 // PRIVATE METHODS:
299
300
301
302 void MD5::init(){
303 finalized=0; // we just started!
304
305 // Nothing counted, so count=0
306 count[0] = 0;
307 count[1] = 0;
308
309 // Load magic initialization constants.
310 state[0] = 0x67452301;
311 state[1] = 0xefcdab89;
312 state[2] = 0x98badcfe;
313 state[3] = 0x10325476;
314 }
315
316
317
318 // Constants for MD5Transform routine.
319 // Although we could use C++ style constants, defines are actually better,
320 // since they let us easily evade scope clashes.
321
322 #define S11 7
323 #define S12 12
324 #define S13 17
325 #define S14 22
326 #define S21 5
327 #define S22 9
328 #define S23 14
329 #define S24 20
330 #define S31 4
331 #define S32 11
332 #define S33 16
333 #define S34 23
334 #define S41 6
335 #define S42 10
336 #define S43 15
337 #define S44 21
338
339
340
341
342 // MD5 basic transformation. Transforms state based on block.
343 void MD5::transform (uint1 block[64]){
344
345 uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
346
347 decode (x, block, 64);
348
349 assert(!finalized); // not just a user error, since the method is private
350
351 /* Round 1 */
352 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
353 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
354 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
355 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
356 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
357 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
358 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
359 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
360 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
361 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
362 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
363 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
364 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
365 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
366 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
367 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
368
369 /* Round 2 */
370 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
371 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
372 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
373 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
374 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
375 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
376 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
377 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
378 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
379 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
380 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
381 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
382 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
383 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
384 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
385 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
386
387 /* Round 3 */
388 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
389 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
390 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
391 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
392 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
393 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
394 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
395 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
396 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
397 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
398 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
399 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
400 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
401 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
402 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
403 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
404
405 /* Round 4 */
406 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
407 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
408 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
409 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
410 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
411 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
412 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
413 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
414 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
415 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
416 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
417 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
418 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
419 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
420 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
421 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
422
423 state[0] += a;
424 state[1] += b;
425 state[2] += c;
426 state[3] += d;
427
428 // Zeroize sensitive information.
429 memset ( (uint1 *) x, 0, sizeof(x));
430
431 }
432
433
434
435 // Encodes input (UINT4) into output (unsigned char). Assumes len is
436 // a multiple of 4.
437 void MD5::encode (uint1 *output, uint4 *input, uint4 len) {
438
439 unsigned int i, j;
440
441 for (i = 0, j = 0; j < len; i++, j += 4) {
442 output[j] = (uint1) (input[i] & 0xff);
443 output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
444 output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
445 output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
446 }
447 }
448
449
450
451
452 // Decodes input (unsigned char) into output (UINT4). Assumes len is
453 // a multiple of 4.
454 void MD5::decode (uint4 *output, uint1 *input, uint4 len){
455
456 unsigned int i, j;
457
458 for (i = 0, j = 0; j < len; i++, j += 4)
459 output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
460 (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
461 }
462
463
464
465
466
467 // Note: Replace "for loop" with standard memcpy if possible.
468 void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){
469
470 unsigned int i;
471
472 for (i = 0; i < len; i++)
473 output[i] = input[i];
474 }
475
476
477
478 // Note: Replace "for loop" with standard memset if possible.
479 void MD5::memset (uint1 *output, uint1 value, uint4 len){
480
481 unsigned int i;
482
483 for (i = 0; i < len; i++)
484 output[i] = value;
485 }
486
487
488
489 // ROTATE_LEFT rotates x left n bits.
490
491 inline unsigned int MD5::rotate_left (uint4 x, uint4 n){
492 return (x << n) | (x >> (32-n)) ;
493 }
494
495
496
497
498 // F, G, H and I are basic MD5 functions.
499
500 inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){
501 return (x & y) | (~x & z);
502 }
503
504 inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){
505 return (x & z) | (y & ~z);
506 }
507
508 inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){
509 return x ^ y ^ z;
510 }
511
512 inline unsigned int MD5::I (uint4 x, uint4 y, uint4 z){
513 return y ^ (x | ~z);
514 }
515
516
517
518 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
519 // Rotation is separate from addition to prevent recomputation.
520
521
522 inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
523 uint4 s, uint4 ac){
524 a += F(b, c, d) + x + ac;
525 a = rotate_left (a, s) +b;
526 }
527
528 inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
529 uint4 s, uint4 ac){
530 a += G(b, c, d) + x + ac;
531 a = rotate_left (a, s) +b;
532 }
533
534 inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
535 uint4 s, uint4 ac){
536 a += H(b, c, d) + x + ac;
537 a = rotate_left (a, s) +b;
538 }
539
540 inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
541 uint4 s, uint4 ac){
542 a += I(b, c, d) + x + ac;
543 a = rotate_left (a, s) +b;
544 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26