00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00038 #include "blocxx/BLOCXX_config.h"
00039 #include "blocxx/MD5.hpp"
00040 #include "blocxx/String.hpp"
00041 #include "blocxx/ExceptionIds.hpp"
00042
00043 #include <string.h>
00044
00045 #ifdef BLOCXX_WIN32
00046 #pragma warning (push)
00047 #pragma warning (disable: 4355)
00048 #endif
00049
00050 namespace BLOCXX_NAMESPACE
00051 {
00052
00053 const int MD5HASHHEXLEN = 32;
00054
00055 BLOCXX_DEFINE_EXCEPTION_WITH_ID(MD5);
00057 MD5OStreamBase::MD5OStreamBase(MD5* md5): _buf(md5) {}
00059 MD5StreamBuffer::MD5StreamBuffer(MD5* md5): _md5(md5) {}
00061 int
00062 MD5StreamBuffer::overflow(int c)
00063 {
00064 unsigned char lc = c;
00065 MD5::MD5Update(&(_md5->m_ctx), &lc, 1);
00066 return c;
00067 }
00069 std::streamsize
00070 MD5StreamBuffer::xsputn(const char* s, std::streamsize num)
00071 {
00072 MD5::MD5Update(&(_md5->m_ctx),
00073 reinterpret_cast<const unsigned char*>(s), num);
00074 return num;
00075 }
00077 MD5::MD5()
00078 : MD5OStreamBase(this), std::ostream(&_buf), m_ctx(), m_finished(false)
00079 {
00080 MD5Init(&m_ctx);
00081 }
00083 void
00084 MD5::init(const String& input)
00085 {
00086 m_finished = false;
00087 MD5Init(&m_ctx);
00088 update(input);
00089 }
00091 MD5::MD5(const String& input)
00092 : MD5OStreamBase(this), std::ostream(&_buf), m_ctx(), m_finished(false)
00093 {
00094 MD5Init(&m_ctx);
00095 update(input);
00096 }
00098 void
00099 MD5::update(const String& input)
00100 {
00101 if (m_finished)
00102 {
00103 BLOCXX_THROW(MD5Exception, "Cannot update after a call to toString()");
00104 }
00105 MD5Update(&m_ctx, reinterpret_cast<const unsigned char*>(input.c_str()),
00106 input.length());
00107 }
00109 String
00110 MD5::toString()
00111 {
00112 return convertBinToHex(getDigest());
00113 }
00115 unsigned char*
00116 MD5::getDigest()
00117 {
00118 if (!m_finished)
00119 {
00120 MD5Final(m_digest, &m_ctx);
00121 m_finished = true;
00122 }
00123 return m_digest;
00124 }
00126 String
00127 MD5::convertBinToHex( const unsigned char* sBin)
00128 {
00129 unsigned short i;
00130 unsigned char j;
00131 char Hex[ MD5HASHHEXLEN + 1 ];
00132 for ( i = 0; i < MD5HASHLEN; i++ )
00133 {
00134 j = (sBin[i] >> 4) & 0xf;
00135 if ( j <= 9 )
00136 {
00137 Hex[i*2] = (j + '0');
00138 }
00139 else
00140 {
00141 Hex[i*2] = (j + 'a' - 10);
00142 }
00143 j = sBin[i] & 0xf;
00144 if ( j <= 9 )
00145 {
00146 Hex[i*2+1] = (j + '0');
00147 }
00148 else
00149 {
00150 Hex[i*2+1] = (j + 'a' - 10);
00151 }
00152 };
00153 Hex[MD5HASHHEXLEN] = '\0';
00154 return String(Hex);
00155 };
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 typedef unsigned char *POINTER;
00178
00179
00180 #define S11 7
00181 #define S12 12
00182 #define S13 17
00183 #define S14 22
00184 #define S21 5
00185 #define S22 9
00186 #define S23 14
00187 #define S24 20
00188 #define S31 4
00189 #define S32 11
00190 #define S33 16
00191 #define S34 23
00192 #define S41 6
00193 #define S42 10
00194 #define S43 15
00195 #define S44 21
00196 static void MD5Transform(UInt32*, const unsigned char*);
00197 static void Encode(unsigned char *, UInt32 *, UInt32);
00198 static void Decode(UInt32 *, const unsigned char *, UInt32);
00199
00200
00201 static unsigned char PADDING[64] = {
00202 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00203 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00204 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00205 };
00206
00207
00208 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
00209 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
00210 #define H(x, y, z) ((x) ^ (y) ^ (z))
00211 #define I(x, y, z) ((y) ^ ((x) | (~z)))
00212
00213
00214 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
00215
00216
00217
00218 #define FF(a, b, c, d, x, s, ac) { \
00219 (a) += F ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \
00220 (a) = ROTATE_LEFT ((a), (s)); \
00221 (a) += (b); \
00222 }
00223 #define GG(a, b, c, d, x, s, ac) { \
00224 (a) += G ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \
00225 (a) = ROTATE_LEFT ((a), (s)); \
00226 (a) += (b); \
00227 }
00228 #define HH(a, b, c, d, x, s, ac) { \
00229 (a) += H ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \
00230 (a) = ROTATE_LEFT ((a), (s)); \
00231 (a) += (b); \
00232 }
00233 #define II(a, b, c, d, x, s, ac) { \
00234 (a) += I ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \
00235 (a) = ROTATE_LEFT ((a), (s)); \
00236 (a) += (b); \
00237 }
00238
00239
00240 void
00241 MD5::MD5Init(MD5_CTX* context)
00242 {
00243 context->count[0] = context->count[1] = 0;
00244
00245
00246 context->state[0] = 0x67452301;
00247 context->state[1] = 0xefcdab89;
00248 context->state[2] = 0x98badcfe;
00249 context->state[3] = 0x10325476;
00250 }
00251
00252
00253
00254
00255 void
00256 MD5::MD5Update(MD5_CTX* context, const unsigned char* input,
00257 UInt32 inputLen)
00258 {
00259 UInt32 i, index, partLen;
00260
00261 index = ((context->count[0] >> 3) & 0x3F);
00262
00263 if ((context->count[0] += (inputLen << 3)) < (inputLen << 3))
00264 {
00265 context->count[1]++;
00266 }
00267 context->count[1] += (inputLen >> 29);
00268 partLen = 64 - index;
00269
00270
00271 if (inputLen >= partLen)
00272 {
00273 memcpy(static_cast<POINTER>(&context->buffer[index]),
00274 static_cast<const unsigned char*>(input), partLen);
00275 MD5Transform (context->state, context->buffer);
00276 for (i = partLen; i + 63 < inputLen; i += 64)
00277 MD5Transform (context->state, &input[i]);
00278 index = 0;
00279 }
00280 else
00281 i = 0;
00282
00283 memcpy
00284 (static_cast<POINTER>(&context->buffer[index]),
00285 static_cast<const unsigned char*>(&input[i]),
00286 inputLen-i);
00287 }
00288
00289
00290
00291 void
00292 MD5::MD5Final (unsigned char* digest, MD5_CTX* context)
00293 {
00294 unsigned char bits[8];
00295 UInt32 index, padLen;
00296
00297 Encode (bits, context->count, 8);
00298
00299
00300 index = ((context->count[0] >> 3) & 0x3f);
00301 padLen = (index < 56) ? (56 - index) : (120 - index);
00302 MD5Update (context, PADDING, padLen);
00303
00304 MD5Update (context, bits, 8);
00305
00306 Encode (digest, context->state, 16);
00307
00308
00309 memset (reinterpret_cast<POINTER>(context), 0, sizeof (*context));
00310 }
00311
00312
00313 static void MD5Transform (UInt32* state, const unsigned char* block)
00314 {
00315 UInt32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00316 Decode (x, block, 64);
00317
00318 FF (a, b, c, d, x[ 0], S11, 0xd76aa478);
00319 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756);
00320 FF (c, d, a, b, x[ 2], S13, 0x242070db);
00321 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee);
00322 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf);
00323 FF (d, a, b, c, x[ 5], S12, 0x4787c62a);
00324 FF (c, d, a, b, x[ 6], S13, 0xa8304613);
00325 FF (b, c, d, a, x[ 7], S14, 0xfd469501);
00326 FF (a, b, c, d, x[ 8], S11, 0x698098d8);
00327 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af);
00328 FF (c, d, a, b, x[10], S13, 0xffff5bb1);
00329 FF (b, c, d, a, x[11], S14, 0x895cd7be);
00330 FF (a, b, c, d, x[12], S11, 0x6b901122);
00331 FF (d, a, b, c, x[13], S12, 0xfd987193);
00332 FF (c, d, a, b, x[14], S13, 0xa679438e);
00333 FF (b, c, d, a, x[15], S14, 0x49b40821);
00334
00335 GG (a, b, c, d, x[ 1], S21, 0xf61e2562);
00336 GG (d, a, b, c, x[ 6], S22, 0xc040b340);
00337 GG (c, d, a, b, x[11], S23, 0x265e5a51);
00338 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa);
00339 GG (a, b, c, d, x[ 5], S21, 0xd62f105d);
00340 GG (d, a, b, c, x[10], S22, 0x2441453);
00341 GG (c, d, a, b, x[15], S23, 0xd8a1e681);
00342 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8);
00343 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6);
00344 GG (d, a, b, c, x[14], S22, 0xc33707d6);
00345 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87);
00346 GG (b, c, d, a, x[ 8], S24, 0x455a14ed);
00347 GG (a, b, c, d, x[13], S21, 0xa9e3e905);
00348 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8);
00349 GG (c, d, a, b, x[ 7], S23, 0x676f02d9);
00350 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a);
00351
00352 HH (a, b, c, d, x[ 5], S31, 0xfffa3942);
00353 HH (d, a, b, c, x[ 8], S32, 0x8771f681);
00354 HH (c, d, a, b, x[11], S33, 0x6d9d6122);
00355 HH (b, c, d, a, x[14], S34, 0xfde5380c);
00356 HH (a, b, c, d, x[ 1], S31, 0xa4beea44);
00357 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9);
00358 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60);
00359 HH (b, c, d, a, x[10], S34, 0xbebfbc70);
00360 HH (a, b, c, d, x[13], S31, 0x289b7ec6);
00361 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa);
00362 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085);
00363 HH (b, c, d, a, x[ 6], S34, 0x4881d05);
00364 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039);
00365 HH (d, a, b, c, x[12], S32, 0xe6db99e5);
00366 HH (c, d, a, b, x[15], S33, 0x1fa27cf8);
00367 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665);
00368
00369 II (a, b, c, d, x[ 0], S41, 0xf4292244);
00370 II (d, a, b, c, x[ 7], S42, 0x432aff97);
00371 II (c, d, a, b, x[14], S43, 0xab9423a7);
00372 II (b, c, d, a, x[ 5], S44, 0xfc93a039);
00373 II (a, b, c, d, x[12], S41, 0x655b59c3);
00374 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92);
00375 II (c, d, a, b, x[10], S43, 0xffeff47d);
00376 II (b, c, d, a, x[ 1], S44, 0x85845dd1);
00377 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f);
00378 II (d, a, b, c, x[15], S42, 0xfe2ce6e0);
00379 II (c, d, a, b, x[ 6], S43, 0xa3014314);
00380 II (b, c, d, a, x[13], S44, 0x4e0811a1);
00381 II (a, b, c, d, x[ 4], S41, 0xf7537e82);
00382 II (d, a, b, c, x[11], S42, 0xbd3af235);
00383 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb);
00384 II (b, c, d, a, x[ 9], S44, 0xeb86d391);
00385 state[0] += a;
00386 state[1] += b;
00387 state[2] += c;
00388 state[3] += d;
00389
00390 memset (reinterpret_cast<POINTER>(x), 0, sizeof (x));
00391 }
00392
00393
00394
00395 static void Encode (unsigned char* output, UInt32* input, UInt32 len)
00396 {
00397 UInt32 i, j;
00398 for (i = 0, j = 0; j < len; i++, j += 4)
00399 {
00400 output[j] = (input[i] & 0xff);
00401 output[j+1] = ((input[i] >> 8) & 0xff);
00402 output[j+2] = ((input[i] >> 16) & 0xff);
00403 output[j+3] = ((input[i] >> 24) & 0xff);
00404 }
00405 }
00406
00407
00408
00409 static void Decode (UInt32* output, const unsigned char* input, UInt32 len)
00410 {
00411 UInt32 i, j;
00412 for (i = 0, j = 0; j < len; i++, j += 4)
00413 output[i] = (static_cast<UInt32>(input[j])) | ((static_cast<UInt32>(input[j+1])) << 8) |
00414 ((static_cast<UInt32>(input[j+2])) << 16) | ((static_cast<UInt32>(input[j+3])) << 24);
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 }
00433
00434
00435 #ifdef BLOCXX_WIN32
00436 #pragma warning (pop)
00437 #endif
00438