00001
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
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #include "stdmisc.h"
00051
00052 #include "nel/misc/md5.h"
00053
00054 #include "nel/misc/types_nl.h"
00055 #include "nel/misc/debug.h"
00056 #include "nel/misc/file.h"
00057 #include "nel/misc/path.h"
00058 #include "nel/misc/stream.h"
00059
00060 using namespace std;
00061
00062 namespace NLMISC
00063 {
00064
00065
00066
00067
00068
00069
00070
00071 CHashKeyMD5 getMD5(const std::string &filename)
00072 {
00073 CMD5Context md5ctx;
00074 CHashKeyMD5 Message_Digest;
00075 Message_Digest.clear();
00076
00077 CIFile ifile;
00078 if (!ifile.open(CPath::lookup(filename)))
00079 {
00080 nlwarning ("MD5: Can't open the file '%s'", filename.c_str());
00081 return Message_Digest;
00082 }
00083
00084 md5ctx.init();
00085
00086 uint8 buffer[1024];
00087 int bufferSize = 1024;
00088 sint fs = ifile.getFileSize();
00089 sint n, read = 0;
00090 do
00091 {
00092
00093 n = std::min (bufferSize, fs-read);
00094
00095 ifile.serialBuffer((uint8 *)buffer, n);
00096
00097 md5ctx.update(buffer, n);
00098
00099 read += n;
00100 }
00101 while (!ifile.eof());
00102
00103 ifile.close ();
00104
00105 md5ctx.final(Message_Digest);
00106
00107 return Message_Digest;
00108 }
00109
00110
00111 CHashKeyMD5 getMD5(const uint8 *buffer, uint32 size)
00112 {
00113 CMD5Context md5ctx;
00114 CHashKeyMD5 Message_Digest;
00115 Message_Digest.clear();
00116
00117 md5ctx.init();
00118 md5ctx.update(buffer, size);
00119 md5ctx.final(Message_Digest);
00120
00121 return Message_Digest;
00122 }
00123
00124
00125
00126
00127 static bool fromHex(char c, uint8 &x)
00128 {
00129 if (c >= '0' && c <= '9')
00130 {
00131 x = c - '0';
00132 return true;
00133 }
00134 else if (c >= 'A' && c <= 'F')
00135 {
00136 x = c - 'A' + 10;
00137 return true;
00138 }
00139 else if (c >= 'a' && c <= 'f')
00140 {
00141 x = c - 'a' + 10;
00142 return true;
00143 }
00144
00145 nlwarning("cannot convert to hexa");
00146 return false;
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156 void CHashKeyMD5::clear()
00157 {
00158 for (uint32 i = 0; i < 16; ++i)
00159 Data[i] = 0;
00160 }
00161
00162
00163 string CHashKeyMD5::toString() const
00164 {
00165 string sTmp;
00166 for (uint32 i = 0; i < 16; ++i)
00167 sTmp += NLMISC::toString("%02x", Data[i]);
00168 return sTmp;
00169 }
00170
00171
00172 bool CHashKeyMD5::fromString(const std::string &in)
00173 {
00174 if (in.size() != 32)
00175 {
00176 nlwarning("bad string size");
00177 return false;
00178 }
00179
00180 for (uint32 i = 0; i < 16; ++i)
00181 {
00182 char c1 = in[2*i];
00183 char c2 = in[2*i+1];
00184 uint8 x1, x2;
00185 if (!fromHex(c1, x1)) return false;
00186 if (!fromHex(c2, x2)) return false;
00187 Data[i] = (x1 << 4) | x2;
00188 }
00189 return true;
00190 }
00191
00192
00193 bool CHashKeyMD5::operator!=(const CHashKeyMD5 &in) const
00194 {
00195 for (uint32 i = 0; i < 16; ++i)
00196 if (Data[i] != in.Data[i])
00197 return true;
00198 return false;
00199 }
00200
00201
00202 bool CHashKeyMD5::operator==(const CHashKeyMD5 &in) const
00203 {
00204 return !operator!=(in);
00205 }
00206
00207
00208 bool CHashKeyMD5::operator<(const CHashKeyMD5 &in) const
00209 {
00210 for (uint32 i = 0; i < 16; ++i)
00211 if (Data[i] >= in.Data[i])
00212 return false;
00213 return true;
00214 }
00215
00216
00217 void CHashKeyMD5::serial (NLMISC::IStream &s)
00218 {
00219 s.serialBuffer(Data,16);
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229 uint8 CMD5Context::Padding[64] = {
00230 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00231 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00233 };
00234
00235
00236 void CMD5Context::init()
00237 {
00238 Count[0] = Count[1] = 0;
00239
00240 State[0] = 0x67452301;
00241 State[1] = 0xefcdab89;
00242 State[2] = 0x98badcfe;
00243 State[3] = 0x10325476;
00244 }
00245
00246
00247 void CMD5Context::update (const uint8 *pBufIn, uint32 nBufLength)
00248 {
00249 uint i, index, partLen;
00250
00251
00252 index = (uint)((Count[0] >> 3) & 0x3F);
00253
00254
00255 if ((Count[0] += (nBufLength << 3)) < (nBufLength << 3))
00256 Count[1]++;
00257 Count[1] += (nBufLength >> 29);
00258
00259 partLen = 64 - index;
00260
00261
00262 if (nBufLength >= partLen)
00263 {
00264 memcpy((uint8*)&Buffer[index], pBufIn, partLen);
00265 transform (State, Buffer);
00266
00267 for (i = partLen; i + 63 < nBufLength; i += 64)
00268 transform (State, &pBufIn[i]);
00269
00270 index = 0;
00271 }
00272 else
00273 {
00274 i = 0;
00275 }
00276
00277
00278 memcpy((uint8*)&Buffer[index], &pBufIn[i], nBufLength-i);
00279 }
00280
00281
00282 void CMD5Context::final (CHashKeyMD5 &out)
00283 {
00284 uint8 bits[8];
00285 uint index, padLen;
00286
00287
00288 encode (&bits[0], Count, 8);
00289
00290
00291 index = (unsigned int)((Count[0] >> 3) & 0x3f);
00292 padLen = (index < 56) ? (56 - index) : (120 - index);
00293 update (Padding, padLen);
00294
00295
00296 update (&bits[0], 8);
00297
00298 encode (out.Data, State, 16);
00299
00300
00301 uint i;
00302 for (i = 0; i < 4; ++i) State[i] = 0;
00303 for (i = 0; i < 2; ++i) Count[i] = 0;
00304 for (i = 0; i < 64; ++i) Buffer[i] = 0;
00305 }
00306
00307
00308
00309 #define S11 7
00310 #define S12 12
00311 #define S13 17
00312 #define S14 22
00313 #define S21 5
00314 #define S22 9
00315 #define S23 14
00316 #define S24 20
00317 #define S31 4
00318 #define S32 11
00319 #define S33 16
00320 #define S34 23
00321 #define S41 6
00322 #define S42 10
00323 #define S43 15
00324 #define S44 21
00325
00326
00327 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
00328 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
00329 #define H(x, y, z) ((x) ^ (y) ^ (z))
00330 #define I(x, y, z) ((y) ^ ((x) | (~z)))
00331
00332
00333 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
00334
00335
00336
00337 #define FF(a, b, c, d, x, s, ac) { \
00338 (a) += F ((b), (c), (d)) + (x) + (uint32)(ac); \
00339 (a) = ROTATE_LEFT ((a), (s)); \
00340 (a) += (b); \
00341 }
00342 #define GG(a, b, c, d, x, s, ac) { \
00343 (a) += G ((b), (c), (d)) + (x) + (uint32)(ac); \
00344 (a) = ROTATE_LEFT ((a), (s)); \
00345 (a) += (b); \
00346 }
00347 #define HH(a, b, c, d, x, s, ac) { \
00348 (a) += H ((b), (c), (d)) + (x) + (uint32)(ac); \
00349 (a) = ROTATE_LEFT ((a), (s)); \
00350 (a) += (b); \
00351 }
00352 #define II(a, b, c, d, x, s, ac) { \
00353 (a) += I ((b), (c), (d)) + (x) + (uint32)(ac); \
00354 (a) = ROTATE_LEFT ((a), (s)); \
00355 (a) += (b); \
00356 }
00357
00358
00359
00360
00361 void CMD5Context::transform (uint32 state[4], const uint8 block[64])
00362 {
00363 uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00364
00365 decode (&x[0], &block[0], 64);
00366
00367
00368 FF (a, b, c, d, x[ 0], S11, 0xd76aa478);
00369 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756);
00370 FF (c, d, a, b, x[ 2], S13, 0x242070db);
00371 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee);
00372 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf);
00373 FF (d, a, b, c, x[ 5], S12, 0x4787c62a);
00374 FF (c, d, a, b, x[ 6], S13, 0xa8304613);
00375 FF (b, c, d, a, x[ 7], S14, 0xfd469501);
00376 FF (a, b, c, d, x[ 8], S11, 0x698098d8);
00377 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af);
00378 FF (c, d, a, b, x[10], S13, 0xffff5bb1);
00379 FF (b, c, d, a, x[11], S14, 0x895cd7be);
00380 FF (a, b, c, d, x[12], S11, 0x6b901122);
00381 FF (d, a, b, c, x[13], S12, 0xfd987193);
00382 FF (c, d, a, b, x[14], S13, 0xa679438e);
00383 FF (b, c, d, a, x[15], S14, 0x49b40821);
00384
00385
00386 GG (a, b, c, d, x[ 1], S21, 0xf61e2562);
00387 GG (d, a, b, c, x[ 6], S22, 0xc040b340);
00388 GG (c, d, a, b, x[11], S23, 0x265e5a51);
00389 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa);
00390 GG (a, b, c, d, x[ 5], S21, 0xd62f105d);
00391 GG (d, a, b, c, x[10], S22, 0x2441453);
00392 GG (c, d, a, b, x[15], S23, 0xd8a1e681);
00393 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8);
00394 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6);
00395 GG (d, a, b, c, x[14], S22, 0xc33707d6);
00396 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87);
00397 GG (b, c, d, a, x[ 8], S24, 0x455a14ed);
00398 GG (a, b, c, d, x[13], S21, 0xa9e3e905);
00399 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8);
00400 GG (c, d, a, b, x[ 7], S23, 0x676f02d9);
00401 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a);
00402
00403
00404 HH (a, b, c, d, x[ 5], S31, 0xfffa3942);
00405 HH (d, a, b, c, x[ 8], S32, 0x8771f681);
00406 HH (c, d, a, b, x[11], S33, 0x6d9d6122);
00407 HH (b, c, d, a, x[14], S34, 0xfde5380c);
00408 HH (a, b, c, d, x[ 1], S31, 0xa4beea44);
00409 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9);
00410 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60);
00411 HH (b, c, d, a, x[10], S34, 0xbebfbc70);
00412 HH (a, b, c, d, x[13], S31, 0x289b7ec6);
00413 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa);
00414 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085);
00415 HH (b, c, d, a, x[ 6], S34, 0x4881d05);
00416 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039);
00417 HH (d, a, b, c, x[12], S32, 0xe6db99e5);
00418 HH (c, d, a, b, x[15], S33, 0x1fa27cf8);
00419 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665);
00420
00421
00422 II (a, b, c, d, x[ 0], S41, 0xf4292244);
00423 II (d, a, b, c, x[ 7], S42, 0x432aff97);
00424 II (c, d, a, b, x[14], S43, 0xab9423a7);
00425 II (b, c, d, a, x[ 5], S44, 0xfc93a039);
00426 II (a, b, c, d, x[12], S41, 0x655b59c3);
00427 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92);
00428 II (c, d, a, b, x[10], S43, 0xffeff47d);
00429 II (b, c, d, a, x[ 1], S44, 0x85845dd1);
00430 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f);
00431 II (d, a, b, c, x[15], S42, 0xfe2ce6e0);
00432 II (c, d, a, b, x[ 6], S43, 0xa3014314);
00433 II (b, c, d, a, x[13], S44, 0x4e0811a1);
00434 II (a, b, c, d, x[ 4], S41, 0xf7537e82);
00435 II (d, a, b, c, x[11], S42, 0xbd3af235);
00436 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb);
00437 II (b, c, d, a, x[ 9], S44, 0xeb86d391);
00438
00439 state[0] += a;
00440 state[1] += b;
00441 state[2] += c;
00442 state[3] += d;
00443 }
00444
00445
00446
00447 void CMD5Context::encode (uint8 *output, const uint32 *input, uint len)
00448 {
00449 uint i, j;
00450
00451 for (i = 0, j = 0; j < len; i++, j += 4)
00452 {
00453 output[j] = (uint8)(input[i] & 0xff);
00454 output[j+1] = (uint8)((input[i] >> 8) & 0xff);
00455 output[j+2] = (uint8)((input[i] >> 16) & 0xff);
00456 output[j+3] = (uint8)((input[i] >> 24) & 0xff);
00457 }
00458 }
00459
00460
00461
00462 void CMD5Context::decode (uint32 *output, const uint8 *input, uint len)
00463 {
00464 uint i, j;
00465
00466 for (i = 0, j = 0; j < len; i++, j += 4)
00467 output[i] = ((uint32)input[j]) | (((uint32)input[j+1]) << 8) |
00468 (((uint32)input[j+2]) << 16) | (((uint32)input[j+3]) << 24);
00469 }
00470
00471
00472 }
00473