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
32rights reserved.
33
34License to copy and use this software is granted provided that it
35is identified as the "RSA Data Security, Inc. MD5 Message-Digest
36Algorithm" in all material mentioning or referencing this software
37or this function.
38
39License is also granted to make and use derivative works provided
40that such works are identified as "derived from the RSA Data
41Security, Inc. MD5 Message-Digest Algorithm" in all material
42mentioning or referencing the derived work.
43
44RSA Data Security, Inc. makes no representations concerning either
45the merchantability of this software or the suitability of this
46software for any particular purpose. It is provided "as is"
47without express or implied warranty of any kind.
48
49These notices must be retained in any copies of any part of this
50documentation 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
71void 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);
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
119void 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
145void 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
166void 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
227MD5::MD5(FILE *file){
228
229 init(); // must be called be all constructors
230 update(file);
231 finalize ();
232}
233
234
235
236
237MD5::MD5(std::istream& stream){
238
239 init(); // must called by all constructors
240 update (stream);
241 finalize();
242}
243
244
245
246MD5::MD5(std::ifstream& stream){
247
248 init(); // must called by all constructors
249 update (stream);
250 finalize();
251}
252
253
254
255unsigned 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
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
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.
338void 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.
432void 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.
449void 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.
463void 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.
474void 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
486inline 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
495inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){
496 return (x & y) | (~x & z);
497}
498
499inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){
500 return (x & z) | (y & ~z);
501}
502
503inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){
504 return x ^ y ^ z;
505}
506
507inline 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
517inline 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
523inline 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
529inline 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
535inline 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
542QString 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
549bool filesMatch(std::ifstream& stream, QString oldMD5)
550{
551 MD5 obj( stream );
552 return (obj.hex_digest() == oldMD5);
553}
554//--------------------------------------------------
MD5 Support allows checksums to be computed for images, determing if they have changed since the albu...
Definition md5.h:65
void update(unsigned char *input, unsigned int input_length)
Definition md5.cpp:71
void transform(uint1 *buffer)
Definition md5.cpp:338
static uint4 F(uint4 x, uint4 y, uint4 z)
Definition md5.cpp:495
uint1 buffer[64]
Definition md5.h:98
uint1 digest[16]
Definition md5.h:99
static void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
Definition md5.cpp:517
uint1 finalized
Definition md5.h:100
uint4 count[2]
Definition md5.h:97
static uint4 rotate_left(uint4 x, uint4 n)
Definition md5.cpp:486
void init()
Definition md5.cpp:297
QString hex_digest()
Definition md5.cpp:271
unsigned char uint1
Definition md5.h:93
static void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
Definition md5.cpp:535
static void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
Definition md5.cpp:523
static uint4 G(uint4 x, uint4 y, uint4 z)
Definition md5.cpp:499
static void encode(uint1 *dest, uint4 *src, uint4 length)
Definition md5.cpp:432
static void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
Definition md5.cpp:529
uint4 state[4]
Definition md5.h:96
unsigned char * raw_digest()
Definition md5.cpp:255
static uint4 I(uint4 x, uint4 y, uint4 z)
Definition md5.cpp:507
unsigned int uint4
Definition md5.h:91
void finalize()
Definition md5.cpp:188
static void memset(uint1 *start, uint1 val, uint4 length)
Definition md5.cpp:474
static uint4 H(uint4 x, uint4 y, uint4 z)
Definition md5.cpp:503
static void decode(uint4 *dest, uint1 *src, uint4 length)
Definition md5.cpp:449
MD5()
Definition md5.cpp:62
static void memcpy(uint1 *dest, uint1 *src, uint4 length)
Definition md5.cpp:463
long b
#define S24
Definition md5.cpp:324
#define S33
Definition md5.cpp:327
#define S32
Definition md5.cpp:326
#define S12
Definition md5.cpp:318
#define S42
Definition md5.cpp:330
#define S11
Definition md5.cpp:317
#define S43
Definition md5.cpp:331
#define S23
Definition md5.cpp:323
#define S44
Definition md5.cpp:332
#define S14
Definition md5.cpp:320
QString getMD5(std::ifstream &stream)
Definition md5.cpp:542
bool filesMatch(std::ifstream &stream, QString oldMD5)
Definition md5.cpp:549
#define S13
Definition md5.cpp:319
#define S41
Definition md5.cpp:329
#define S21
Definition md5.cpp:321
#define S22
Definition md5.cpp:322
#define S31
Definition md5.cpp:325
#define S34
Definition md5.cpp:328