49 fBits(), fIn(), fString(), fDigest(), fFinalized(kFALSE)
60 TMD5::TMD5(
const UChar_t *digest):
61 fBuf(), fBits(), fIn(), fString(), fFinalized(kTRUE)
64 memcpy(fDigest, digest, 16);
66 memset(fDigest, 0, 16);
67 Error(
"TMD5::TMD5",
"digest is 0");
75 TMD5::TMD5(
const TMD5 &md5):
78 memcpy(fBuf, md5.fBuf, 4*
sizeof(UInt_t));
79 memcpy(fBits, md5.fBits, 2*
sizeof(UInt_t));
80 memcpy(fIn, md5.fIn, 64);
82 memcpy(fDigest, md5.fDigest, 16);
83 fFinalized = md5.fFinalized;
90 TMD5 &TMD5::operator=(
const TMD5 &rhs)
93 memcpy(fBuf, rhs.fBuf, 4*
sizeof(UInt_t));
94 memcpy(fBits, rhs.fBits, 2*
sizeof(UInt_t));
95 memcpy(fIn, rhs.fIn, 64);
97 memcpy(fDigest, rhs.fDigest, 16);
98 fFinalized = rhs.fFinalized;
99 memcpy(fString, rhs.fString,
sizeof(fString));
108 void TMD5::Update(
const UChar_t *buf, UInt_t len)
111 Error(
"TMD5::Update",
"Final() has already been called");
119 if ((fBits[0] = t + (len << 3)) < t)
121 fBits[1] += len >> 29;
127 UChar_t *p = (UChar_t *) fIn + t;
135 Transform(fBuf, fIn);
142 memcpy(fIn, buf, 64);
143 Transform(fBuf, fIn);
149 memcpy(fIn, buf, len);
157 void TMD5::Final(UChar_t digest[16])
160 memcpy(digest, fDigest, 16);
172 UInt_t count, padLen;
175 static UChar_t padding[64] = {
176 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
182 Encode(bits, fBits, 8);
185 count = (fBits[0] >> 3) & 0x3f;
186 padLen = (count < 56) ? (56 - count) : (120 - count);
187 Update(padding, padLen);
193 Encode(fDigest, fBuf, 16);
196 memset(fBuf, 0, 4*
sizeof(UInt_t));
197 memset(fBits, 0, 2*
sizeof(UInt_t));
206 void TMD5::Print()
const
209 Error(
"TMD5::Print",
"Final() has not yet been called");
213 printf(
"%s\n", AsString());
220 const char *TMD5::AsString()
const
223 Error(
"TMD5::AsString",
"Final() has not yet been called");
228 static const char hexdig[] =
"0123456789abcdef";
229 for (
int i = 0; i < 16; ++i) {
230 fString[i * 2] = hexdig[fDigest[i] / 16];
231 fString[i * 2 + 1] = hexdig[fDigest[i] % 16];
240 void TMD5::Encode(UChar_t *out,
const UInt_t *in, UInt_t len)
244 for (i = 0, j = 0; j < len; i++, j += 4) {
245 out[j] = (UChar_t)(in[i] & 0xff);
246 out[j+1] = (UChar_t)((in[i] >> 8) & 0xff);
247 out[j+2] = (UChar_t)((in[i] >> 16) & 0xff);
248 out[j+3] = (UChar_t)((in[i] >> 24) & 0xff);
255 void TMD5::Decode(UInt_t *out,
const UChar_t *in, UInt_t len)
259 for (i = 0, j = 0; j < len; i++, j += 4)
260 out[i] = ((UInt_t)in[j]) | (((UInt_t)in[j+1]) << 8) |
261 (((UInt_t)in[j+2]) << 16) | (((UInt_t)in[j+3]) << 24);
267 #define F1(x, y, z) (z ^ (x & (y ^ z)))
268 #define F2(x, y, z) F1(z, x, y)
269 #define F3(x, y, z) (x ^ y ^ z)
270 #define F4(x, y, z) (y ^ (x | ~z))
273 #define MD5STEP(f, w, x, y, z, data, s) \
274 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
281 void TMD5::Transform(UInt_t buf[4],
const UChar_t in[64])
283 UInt_t a, b, c, d, x[16];
292 MD5STEP(F1, a, b, c, d, x[0] + 0xd76aa478, 7);
293 MD5STEP(F1, d, a, b, c, x[1] + 0xe8c7b756, 12);
294 MD5STEP(F1, c, d, a, b, x[2] + 0x242070db, 17);
295 MD5STEP(F1, b, c, d, a, x[3] + 0xc1bdceee, 22);
296 MD5STEP(F1, a, b, c, d, x[4] + 0xf57c0faf, 7);
297 MD5STEP(F1, d, a, b, c, x[5] + 0x4787c62a, 12);
298 MD5STEP(F1, c, d, a, b, x[6] + 0xa8304613, 17);
299 MD5STEP(F1, b, c, d, a, x[7] + 0xfd469501, 22);
300 MD5STEP(F1, a, b, c, d, x[8] + 0x698098d8, 7);
301 MD5STEP(F1, d, a, b, c, x[9] + 0x8b44f7af, 12);
302 MD5STEP(F1, c, d, a, b, x[10] + 0xffff5bb1, 17);
303 MD5STEP(F1, b, c, d, a, x[11] + 0x895cd7be, 22);
304 MD5STEP(F1, a, b, c, d, x[12] + 0x6b901122, 7);
305 MD5STEP(F1, d, a, b, c, x[13] + 0xfd987193, 12);
306 MD5STEP(F1, c, d, a, b, x[14] + 0xa679438e, 17);
307 MD5STEP(F1, b, c, d, a, x[15] + 0x49b40821, 22);
309 MD5STEP(F2, a, b, c, d, x[1] + 0xf61e2562, 5);
310 MD5STEP(F2, d, a, b, c, x[6] + 0xc040b340, 9);
311 MD5STEP(F2, c, d, a, b, x[11] + 0x265e5a51, 14);
312 MD5STEP(F2, b, c, d, a, x[0] + 0xe9b6c7aa, 20);
313 MD5STEP(F2, a, b, c, d, x[5] + 0xd62f105d, 5);
314 MD5STEP(F2, d, a, b, c, x[10] + 0x02441453, 9);
315 MD5STEP(F2, c, d, a, b, x[15] + 0xd8a1e681, 14);
316 MD5STEP(F2, b, c, d, a, x[4] + 0xe7d3fbc8, 20);
317 MD5STEP(F2, a, b, c, d, x[9] + 0x21e1cde6, 5);
318 MD5STEP(F2, d, a, b, c, x[14] + 0xc33707d6, 9);
319 MD5STEP(F2, c, d, a, b, x[3] + 0xf4d50d87, 14);
320 MD5STEP(F2, b, c, d, a, x[8] + 0x455a14ed, 20);
321 MD5STEP(F2, a, b, c, d, x[13] + 0xa9e3e905, 5);
322 MD5STEP(F2, d, a, b, c, x[2] + 0xfcefa3f8, 9);
323 MD5STEP(F2, c, d, a, b, x[7] + 0x676f02d9, 14);
324 MD5STEP(F2, b, c, d, a, x[12] + 0x8d2a4c8a, 20);
326 MD5STEP(F3, a, b, c, d, x[5] + 0xfffa3942, 4);
327 MD5STEP(F3, d, a, b, c, x[8] + 0x8771f681, 11);
328 MD5STEP(F3, c, d, a, b, x[11] + 0x6d9d6122, 16);
329 MD5STEP(F3, b, c, d, a, x[14] + 0xfde5380c, 23);
330 MD5STEP(F3, a, b, c, d, x[1] + 0xa4beea44, 4);
331 MD5STEP(F3, d, a, b, c, x[4] + 0x4bdecfa9, 11);
332 MD5STEP(F3, c, d, a, b, x[7] + 0xf6bb4b60, 16);
333 MD5STEP(F3, b, c, d, a, x[10] + 0xbebfbc70, 23);
334 MD5STEP(F3, a, b, c, d, x[13] + 0x289b7ec6, 4);
335 MD5STEP(F3, d, a, b, c, x[0] + 0xeaa127fa, 11);
336 MD5STEP(F3, c, d, a, b, x[3] + 0xd4ef3085, 16);
337 MD5STEP(F3, b, c, d, a, x[6] + 0x04881d05, 23);
338 MD5STEP(F3, a, b, c, d, x[9] + 0xd9d4d039, 4);
339 MD5STEP(F3, d, a, b, c, x[12] + 0xe6db99e5, 11);
340 MD5STEP(F3, c, d, a, b, x[15] + 0x1fa27cf8, 16);
341 MD5STEP(F3, b, c, d, a, x[2] + 0xc4ac5665, 23);
343 MD5STEP(F4, a, b, c, d, x[0] + 0xf4292244, 6);
344 MD5STEP(F4, d, a, b, c, x[7] + 0x432aff97, 10);
345 MD5STEP(F4, c, d, a, b, x[14] + 0xab9423a7, 15);
346 MD5STEP(F4, b, c, d, a, x[5] + 0xfc93a039, 21);
347 MD5STEP(F4, a, b, c, d, x[12] + 0x655b59c3, 6);
348 MD5STEP(F4, d, a, b, c, x[3] + 0x8f0ccc92, 10);
349 MD5STEP(F4, c, d, a, b, x[10] + 0xffeff47d, 15);
350 MD5STEP(F4, b, c, d, a, x[1] + 0x85845dd1, 21);
351 MD5STEP(F4, a, b, c, d, x[8] + 0x6fa87e4f, 6);
352 MD5STEP(F4, d, a, b, c, x[15] + 0xfe2ce6e0, 10);
353 MD5STEP(F4, c, d, a, b, x[6] + 0xa3014314, 15);
354 MD5STEP(F4, b, c, d, a, x[13] + 0x4e0811a1, 21);
355 MD5STEP(F4, a, b, c, d, x[4] + 0xf7537e82, 6);
356 MD5STEP(F4, d, a, b, c, x[11] + 0xbd3af235, 10);
357 MD5STEP(F4, c, d, a, b, x[2] + 0x2ad7d2bb, 15);
358 MD5STEP(F4, b, c, d, a, x[9] + 0xeb86d391, 21);
366 memset(x, 0,
sizeof(x));
372 Bool_t operator==(
const TMD5 &m1,
const TMD5 &m2)
375 if (!m1.fFinalized || !m2.fFinalized) {
377 Error(
"TMD5::operator==(const TMD5&, const TMD5&)",
"arg1.Final() not yet called");
379 Error(
"TMD5::operator==(const TMD5&, const TMD5&)",
"arg2.Final() not yet called");
383 for (
int i = 0; i < 16; i++)
384 if (m1.fDigest[i] != m2.fDigest[i])
395 Int_t TMD5::SetDigest(
const char *md5ascii)
397 if (!md5ascii || strlen(md5ascii) < 32) {
402 char *buf = (
char *) md5ascii;
403 for (
int i = 0; i < 16; i++) {
407 sscanf(buf+2*i,
"%hx", &d);
409 fDigest[i] = (UChar_t) d;
422 TMD5 *TMD5::ReadChecksum(
const char *file)
424 FILE *fid = fopen(file,
"r");
432 if (!fgets(buf, 33, fid)) {
433 SysError(
"TMD5::ReadChecksum",
"error reading checksum from %s", file);
440 TMD5 *md5 =
new TMD5;
452 Int_t TMD5::WriteChecksum(
const char *file,
const TMD5 *md5)
454 FILE *fid = fopen(file,
"w");
460 fputs(md5->AsString(), fid);
474 TMD5 *TMD5::FileChecksum(
const char *file)
477 Long_t id, flags, modtime;
478 if (gSystem->GetPathInfo(file, &
id, &size, &flags, &modtime) == 0) {
480 Error(
"TMD5::FileChecksum",
"%s not a regular file (%ld)", file, flags);
489 Int_t fd = open(file, O_RDONLY);
491 Int_t fd = open(file, O_RDONLY | O_BINARY);
494 Error(
"TMD5::FileChecksum",
"cannot open %s in read mode", file);
498 TMD5 *md5 =
new TMD5;
501 const Int_t bufSize = 8192;
502 UChar_t buf[bufSize];
505 Long64_t left = Long64_t(size - pos);
509 while ((siz = read(fd, buf, left)) < 0 && TSystem::GetErrno() == EINTR)
510 TSystem::ResetErrno();
511 if (siz < 0 || siz != left) {
512 Error(
"TMD5::FileChecksum",
"error reading from file %s", file);
518 md5->Update(buf, left);
527 gSystem->Utime(file, modtime, modtime);
538 Int_t TMD5::FileChecksum(
const char *file, UChar_t digest[16])
540 TMD5 *md5 = FileChecksum(file);
542 memcpy(digest, md5->fDigest, 16);
546 memset(digest, 0, 16);
554 TBuffer &operator<<(TBuffer &buf,
const TMD5 &uuid)
556 R__ASSERT( buf.IsWriting() );
558 const_cast<TMD5&
>(uuid).Streamer(buf);