00001
00002
00003
00004
00005
00040 #ifndef HMD5_H
00041 #define HMD5_H
00042
00077 class HMD5 : public HObj
00078 {
00079 typedef HObj base_class;
00080 static StringPtr ClassName(void) { return "HMD5"; }
00081 public:
00082 enum {
00083 kInputLen = 64,
00084 kDigestLen = 16,
00085 } bogus;
00086
00087 typedef uint8 Digest[kDigestLen];
00088
00089
00090
00091 protected:
00092 Digest m_digest;
00093 uint32 m_uBits[2],
00094 m_uBuffer[4];
00095 uint8 m_cInput[kInputLen];
00096
00097
00098
00099 public:
00100 HMD5(void)
00101 { (void) Start(); }
00102 ~HMD5(void)
00103 { }
00104
00105
00106
00107 public:
00116 static ErrCode
00117 Compute(PtrConst pData, uint32 uBytes, HMD5::Digest & digest)
00118 {
00119 ErrCode ec = HError::NoError();
00120 HMD5 md5;
00121
00122 MEM_ZERO(&digest, sizeof(HMD5::Digest));
00123
00124 if (md5.Start() == NO_ERROR &&
00125 md5.Update(pData, uBytes) == NO_ERROR &&
00126 md5.Stop() == NO_ERROR)
00127 {
00128 md5.GetDigest(digest);
00129 }
00130 else
00131 ec = ErrCode(HError::GetLastError());
00132
00133 return ec;
00134 }
00142 static ErrCode
00143 ConvertToDigest(StringPtr pstr, HMD5::Digest & digest)
00144 {
00145 const int32 kDigestStrLen = kDigestLen * 2;
00146 ErrCode ec = HError::NoError();
00147
00148 if (STR_LEN(pstr) != kDigestStrLen)
00149 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00150 else
00151 {
00152 int32 nByte;
00153
00154 #define HEX2VAL(c) int8(((c)>='0'&&(c)<='9')?((c)-'0'):((toupper(c)-'A')+ 10))
00155
00156 for (nByte = 0; nByte < kDigestLen; ++nByte)
00157 {
00158 if (!(isxdigit(pstr[0]) && isxdigit(pstr[1])))
00159 break;
00160
00161 digest[nByte] = (HEX2VAL(pstr[0]) << 4) + HEX2VAL(pstr[1]);
00162 pstr += 2;
00163 }
00164
00165 if (nByte != kDigestLen)
00166 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00167
00168 #undef HEX2VAL
00169 }
00170
00171 return ec;
00172 }
00184 static StringPtr
00185 ConvertToString(const HMD5::Digest & digest, const bool bAllCaps = true)
00186 {
00187 const int32 kDigestStrLen = kDigestLen * 2;
00188 static Text szDigest[kDigestStrLen+1];
00189
00190 int32 nLen = 0;
00191 StringPtr pstrFormat = (bAllCaps) ? "%02lX" : "%02lx";
00192
00193 MEM_ZERO(szDigest, sizeof(szDigest));
00194
00195 for (uint32 ndx = 0; ndx < kDigestLen; ++ndx)
00196 {
00197 ASSERT(nLen < kDigestStrLen);
00198 nLen += STR_SPRINTF(&szDigest[nLen], kDigestStrLen - nLen,
00199 pstrFormat,
00200 digest[ndx]);
00201 }
00202
00203 return szDigest;
00204 }
00210 ErrCode
00211 Start(void)
00212 {
00213 MEM_ZERO(m_digest, sizeof(Digest));
00214
00215 m_uBits[0] = m_uBits[1] = 0L;
00216
00217 m_uBuffer[0] = 0x67452301L;
00218 m_uBuffer[1] = 0xEFCDAB89L;
00219 m_uBuffer[2] = 0x98BADCFEL;
00220 m_uBuffer[3] = 0x10325476L;
00221
00222 return HError::NoError();
00223 }
00232 ErrCode
00233 Stop(void)
00234 {
00235 const uint8 cPadding[] = {
00236 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00244 };
00245
00246 ErrCode ec = HError::NoError();
00247 uint32 uBits,
00248 uPadding,
00249 uScratch[16];
00250
00251 ASSERT( ARRAY_DIM(cPadding) == kInputLen );
00252
00253 uScratch[14] = m_uBits[0];
00254 uScratch[15] = m_uBits[1];
00255 uBits = (m_uBits[0] >> 3) & 0x3F;
00256 uPadding = ((uBits < 56) ? 56 : 120) - uBits;
00257
00258 if ((ec = Update(cPadding, uPadding)) == NO_ERROR)
00259 {
00260 int32 ndx1,
00261 ndx2;
00262
00263
00264
00265 for (ndx1 = ndx2 = 0; ndx1 < 14; ndx1++, ndx2 += 4)
00266 {
00267 uScratch[ndx1] = (uint32(m_cInput[ndx2 + 3]) << 24) |
00268 (uint32(m_cInput[ndx2 + 2]) << 16) |
00269 (uint32(m_cInput[ndx2 + 1]) << 8) |
00270 uint32(m_cInput[ndx2]);
00271 }
00272
00273 transform(uScratch);
00274
00275
00276
00277 for (ndx1 = ndx2 = 0; ndx1 < 4; ndx1++, ndx2 += 4)
00278 {
00279 m_digest[ndx2] = uint8(m_uBuffer[ndx1] & 0xFF);
00280 m_digest[ndx2 + 1] = uint8((m_uBuffer[ndx1] >> 8) & 0xFF);
00281 m_digest[ndx2 + 2] = uint8((m_uBuffer[ndx1] >> 16) & 0xFF);
00282 m_digest[ndx2 + 3] = uint8((m_uBuffer[ndx1] >> 24) & 0xFF);
00283 }
00284 }
00285
00286 return ec;
00287 }
00299 ErrCode
00300 Update(PtrConst pData, uint32 uBytes)
00301 {
00302 ErrCode ec = HError::NoError();
00303 PtrDataConst pc = reinterpret_cast<PtrDataConst>( pData );
00304
00305 if (GOOD_PTR(pc) && uBytes > 0)
00306 {
00307 int32 ndx1,
00308 ndx2,
00309 nBits;
00310 uint32 uScratch[16];
00311
00312
00313
00314 nBits = int32((m_uBits[0] >> 3) & 0x3F);
00315 if ((m_uBits[0] + (uBytes << 3)) < m_uBits[0])
00316 m_uBits[1] += 1;
00317
00318 m_uBits[0] += uBytes << 3;
00319 m_uBits[1] += uBytes >> 29;
00320
00321
00322
00323
00324 while (uBytes--)
00325 {
00326 m_cInput[nBits++] = *pc++;
00327 if (nBits >= kInputLen)
00328 {
00329 for (ndx1 = ndx2 = 0; ndx1 < 16; ndx1++, ndx2 += 4)
00330 {
00331 uScratch[ndx1] = (uint32(m_cInput[ndx2 + 3]) << 24) |
00332 (uint32(m_cInput[ndx2 + 2]) << 16) |
00333 (uint32(m_cInput[ndx2 + 1]) << 8) |
00334 uint32(m_cInput[ndx2]);
00335 }
00336
00337 transform(uScratch);
00338 nBits = 0;
00339 }
00340 }
00341 }
00342 else if (uBytes > 0 && NULL_PTR(pData))
00343 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00344
00345 return ec;
00346 }
00347 protected:
00353 void
00354 transform(const uint32 uScratch[])
00355 {
00356 uint32 a = m_uBuffer[0],
00357 b = m_uBuffer[1],
00358 c = m_uBuffer[2],
00359 d = m_uBuffer[3];
00360
00361
00362
00363
00364 #define ROTATE_LEFT(x,n) (((x) << (n)) | ((x) >> (32 - (n))))
00365
00366
00367
00368 #define S11 7
00369 #define S12 12
00370 #define S13 17
00371 #define S14 22
00372
00373 #define F(x,y,z) (((x) & (y)) | ((~x) & (z)))
00374 #define FF(a, b, c, d, x, s, ac) { \
00375 (a) += F((b), (c), (d)) + (x) + uint32(ac); \
00376 (a) = ROTATE_LEFT((a), (s)); \
00377 (a) += (b); }
00378
00379 FF( a, b, c, d, uScratch[ 0], S11, 0xD76AA478L);
00380 FF( d, a, b, c, uScratch[ 1], S12, 0xE8C7B756L);
00381 FF( c, d, a, b, uScratch[ 2], S13, 0x242070DBL);
00382 FF( b, c, d, a, uScratch[ 3], S14, 0xC1BDCEEEL);
00383 FF( a, b, c, d, uScratch[ 4], S11, 0xF57C0FAFL);
00384 FF( d, a, b, c, uScratch[ 5], S12, 0x4787C62AL);
00385 FF( c, d, a, b, uScratch[ 6], S13, 0xA8304613L);
00386 FF( b, c, d, a, uScratch[ 7], S14, 0xFD469501L);
00387 FF( a, b, c, d, uScratch[ 8], S11, 0x698098D8L);
00388 FF( d, a, b, c, uScratch[ 9], S12, 0x8B44F7AFL);
00389 FF( c, d, a, b, uScratch[10], S13, 0xFFFF5BB1L);
00390 FF( b, c, d, a, uScratch[11], S14, 0x895CD7BEL);
00391 FF( a, b, c, d, uScratch[12], S11, 0x6B901122L);
00392 FF( d, a, b, c, uScratch[13], S12, 0xFD987193L);
00393 FF( c, d, a, b, uScratch[14], S13, 0xA679438EL);
00394 FF( b, c, d, a, uScratch[15], S14, 0x49B40821L);
00395
00396
00397
00398 #define S21 5
00399 #define S22 9
00400 #define S23 14
00401 #define S24 20
00402
00403 #define G(x,y,z) (((x) & (z)) | ((y) & (~z)))
00404 #define GG(a, b, c, d, x, s, ac) { \
00405 (a) += G((b), (c), (d)) + (x) + uint32(ac); \
00406 (a) = ROTATE_LEFT((a), (s)); \
00407 (a) += (b); }
00408
00409 GG( a, b, c, d, uScratch[ 1], S21, 0xF61E2562L);
00410 GG( d, a, b, c, uScratch[ 6], S22, 0xC040B340L);
00411 GG( c, d, a, b, uScratch[11], S23, 0x265E5A51L);
00412 GG( b, c, d, a, uScratch[ 0], S24, 0xE9B6C7AAL);
00413 GG( a, b, c, d, uScratch[ 5], S21, 0xD62F105DL);
00414 GG( d, a, b, c, uScratch[10], S22, 0x02441453L);
00415 GG( c, d, a, b, uScratch[15], S23, 0xD8A1E681L);
00416 GG( b, c, d, a, uScratch[ 4], S24, 0xE7D3FBC8L);
00417 GG( a, b, c, d, uScratch[ 9], S21, 0x21E1CDE6L);
00418 GG( d, a, b, c, uScratch[14], S22, 0xC33707D6L);
00419 GG( c, d, a, b, uScratch[ 3], S23, 0xF4D50D87L);
00420 GG( b, c, d, a, uScratch[ 8], S24, 0x455A14EDL);
00421 GG( a, b, c, d, uScratch[13], S21, 0xA9E3E905L);
00422 GG( d, a, b, c, uScratch[ 2], S22, 0xFCEFA3F8L);
00423 GG( c, d, a, b, uScratch[ 7], S23, 0x676F02D9L);
00424 GG( b, c, d, a, uScratch[12], S24, 0x8D2A4C8AL);
00425
00426
00427
00428 #define S31 4
00429 #define S32 11
00430 #define S33 16
00431 #define S34 23
00432
00433 #define H(x,y,z) ((x) ^ (y) ^ (z))
00434 #define HH(a, b, c, d, x, s, ac) { \
00435 (a) += H((b), (c), (d)) + (x) + uint32(ac); \
00436 (a) = ROTATE_LEFT((a), (s)); \
00437 (a) += (b); }
00438
00439 HH( a, b, c, d, uScratch[ 5], S31, 0xFFFA3942L);
00440 HH( d, a, b, c, uScratch[ 8], S32, 0x8771F681L);
00441 HH( c, d, a, b, uScratch[11], S33, 0x6D9D6122L);
00442 HH( b, c, d, a, uScratch[14], S34, 0xFDE5380CL);
00443 HH( a, b, c, d, uScratch[ 1], S31, 0xA4BEEA44L);
00444 HH( d, a, b, c, uScratch[ 4], S32, 0x4BDECFA9L);
00445 HH( c, d, a, b, uScratch[ 7], S33, 0xF6BB4B60L);
00446 HH( b, c, d, a, uScratch[10], S34, 0xBEBFBC70L);
00447 HH( a, b, c, d, uScratch[13], S31, 0x289B7EC6L);
00448 HH( d, a, b, c, uScratch[ 0], S32, 0xEAA127FAL);
00449 HH( c, d, a, b, uScratch[ 3], S33, 0xD4EF3085L);
00450 HH( b, c, d, a, uScratch[ 6], S34, 0x04881D05L);
00451 HH( a, b, c, d, uScratch[ 9], S31, 0xD9D4D039L);
00452 HH( d, a, b, c, uScratch[12], S32, 0xE6DB99E5L);
00453 HH( c, d, a, b, uScratch[15], S33, 0x1FA27CF8L);
00454 HH( b, c, d, a, uScratch[ 2], S34, 0xC4AC5665L);
00455
00456
00457
00458 #define S41 6
00459 #define S42 10
00460 #define S43 15
00461 #define S44 21
00462 #define I(x,y,z) ((y) ^ ((x) | (~z)))
00463
00464 #define II(a, b, c, d, x, s, ac) { \
00465 (a) += I((b), (c), (d)) + (x) + uint32(ac); \
00466 (a) = ROTATE_LEFT((a), (s)); \
00467 (a) += (b); }
00468
00469 II( a, b, c, d, uScratch[ 0], S41, 0xF4292244L);
00470 II( d, a, b, c, uScratch[ 7], S42, 0x432AFF97L);
00471 II( c, d, a, b, uScratch[14], S43, 0xAB9423A7L);
00472 II( b, c, d, a, uScratch[ 5], S44, 0xFC93A039L);
00473 II( a, b, c, d, uScratch[12], S41, 0x655B59C3L);
00474 II( d, a, b, c, uScratch[ 3], S42, 0x8F0CCC92L);
00475 II( c, d, a, b, uScratch[10], S43, 0xFFEFF47DL);
00476 II( b, c, d, a, uScratch[ 1], S44, 0x85845DD1L);
00477 II( a, b, c, d, uScratch[ 8], S41, 0x6FA87E4FL);
00478 II( d, a, b, c, uScratch[15], S42, 0xFE2CE6E0L);
00479 II( c, d, a, b, uScratch[ 6], S43, 0xA3014314L);
00480 II( b, c, d, a, uScratch[13], S44, 0x4E0811A1L);
00481 II( a, b, c, d, uScratch[ 4], S41, 0xF7537E82L);
00482 II( d, a, b, c, uScratch[11], S42, 0xBD3AF235L);
00483 II( c, d, a, b, uScratch[ 2], S43, 0x2AD7D2BBL);
00484 II( b, c, d, a, uScratch[ 9], S44, 0xEB86D391L);
00485
00486 m_uBuffer[0] += a;
00487 m_uBuffer[1] += b;
00488 m_uBuffer[2] += c;
00489 m_uBuffer[3] += d;
00490 }
00491
00492
00493
00494 public:
00499 void GetDigest(HMD5::Digest & digest) const
00500 { MEM_COPY(&digest, &m_digest, sizeof(Digest)); }
00511 StringPtr GetDigestStr(const bool bUppercase = true) const
00512 { return ConvertToString(m_digest, bUppercase); }
00513
00514
00515
00516 public:
00522 inline static int32 Compare(const HMD5::Digest & lhs, const HMD5::Digest & rhs)
00523 { return MEM_CMP(lhs, rhs, sizeof(Digest)); }
00529 inline static int32 Compare(const HMD5::Digest & digest, StringPtr pstrDigest)
00530 { return STR_ICMP(pstrDigest, ConvertToString(digest)); }
00531
00532
00533
00534 bool operator == (const HMD5 & rhs) const
00535 { return (Compare(m_digest, rhs.m_digest) == 0); }
00536
00537 bool operator != (const HMD5 & rhs) const
00538 { return (Compare(m_digest, rhs.m_digest) != 0); }
00539 };
00540
00541 #endif // HMD5_H
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567