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