Show bonus/malus timer text if available
[ryzomcore.git] / nel / src / misc / md5.cpp
blob052bfa0b228a7df504d1afae6b38a91122146d76
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
21 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
22 rights reserved.
24 License to copy and use this software is granted provided that it
25 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
26 Algorithm" in all material mentioning or referencing this software
27 or this function.
29 License is also granted to make and use derivative works provided
30 that such works are identified as "derived from the RSA Data
31 Security, Inc. MD5 Message-Digest Algorithm" in all material
32 mentioning or referencing the derived work.
34 RSA Data Security, Inc. makes no representations concerning either
35 the merchantability of this software or the suitability of this
36 software for any particular purpose. It is provided "as is"
37 without express or implied warranty of any kind.
39 These notices must be retained in any copies of any part of this
40 documentation and/or software.
43 #include "stdmisc.h"
45 #include "nel/misc/md5.h"
47 #include "nel/misc/types_nl.h"
48 #include "nel/misc/debug.h"
49 #include "nel/misc/file.h"
50 #include "nel/misc/path.h"
51 #include "nel/misc/stream.h"
53 using namespace std;
55 #ifdef DEBUG_NEW
56 #define new DEBUG_NEW
57 #endif
59 namespace NLMISC
61 // ****************************************************************************
62 // ****************************************************************************
63 // High Level Routines
64 // ****************************************************************************
65 // ****************************************************************************
67 // ****************************************************************************
68 CHashKeyMD5 getMD5(const std::string &filename)
70 CMD5Context md5ctx;
71 CHashKeyMD5 Message_Digest;
72 Message_Digest.clear();
74 CIFile ifile;
75 if (!ifile.open(CPath::lookup(filename)))
77 nlwarning ("MD5: Can't open the file '%s'", filename.c_str());
78 return Message_Digest;
81 md5ctx.init();
83 uint8 buffer[1024];
84 int bufferSize = 1024;
85 sint fs = ifile.getFileSize();
86 sint n, read = 0;
89 //bs = (int)fread (buffer, 1, bufferSize, fp);
90 n = std::min (bufferSize, fs-read);
91 //nlinfo ("read %d bytes", n);
92 ifile.serialBuffer((uint8 *)buffer, n);
94 md5ctx.update(buffer, n);
96 read += n;
98 while (!ifile.eof());
100 ifile.close ();
102 md5ctx.final(Message_Digest);
104 return Message_Digest;
107 // ****************************************************************************
108 CHashKeyMD5 getMD5(const uint8 *buffer, uint32 size)
110 CMD5Context md5ctx;
111 CHashKeyMD5 Message_Digest;
112 Message_Digest.clear();
114 md5ctx.init();
115 md5ctx.update(buffer, size);
116 md5ctx.final(Message_Digest);
118 return Message_Digest;
121 // ****************************************************************************
122 // ****************************************************************************
123 // CHashKeyMD5
124 // ****************************************************************************
125 // ****************************************************************************
127 // ****************************************************************************
128 void CHashKeyMD5::clear()
130 for (uint32 i = 0; i < 16; ++i)
131 Data[i] = 0;
134 // ****************************************************************************
135 string CHashKeyMD5::toString() const
137 return toHexa(Data, 16);
140 // ****************************************************************************
141 bool CHashKeyMD5::fromString(const std::string &in)
143 if (in.size() != 32)
145 nlwarning("bad string size");
146 return false;
149 return fromHexa(in, Data);
152 // ****************************************************************************
153 bool CHashKeyMD5::operator!=(const CHashKeyMD5 &in) const
155 for (uint32 i = 0; i < 16; ++i)
156 if (Data[i] != in.Data[i])
157 return true;
158 return false;
161 // ****************************************************************************
162 bool CHashKeyMD5::operator==(const CHashKeyMD5 &in) const
164 return !operator!=(in);
167 // ****************************************************************************
168 bool CHashKeyMD5::operator<(const CHashKeyMD5 &in) const
170 for (uint32 i = 0; i < 16; ++i)
171 if (Data[i] >= in.Data[i])
172 return false;
173 return true;
176 // ****************************************************************************
177 void CHashKeyMD5::serial (NLMISC::IStream &s)
179 s.serialBuffer(Data,16);
183 // ****************************************************************************
184 // ****************************************************************************
185 // CMD5Context
186 // ****************************************************************************
187 // ****************************************************************************
189 uint8 CMD5Context::Padding[64] = {
190 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
195 // ****************************************************************************
196 void CMD5Context::init()
198 Count[0] = Count[1] = 0;
199 // Load magic initialization constants.
200 State[0] = 0x67452301;
201 State[1] = 0xefcdab89;
202 State[2] = 0x98badcfe;
203 State[3] = 0x10325476;
206 // ****************************************************************************
207 void CMD5Context::update (const uint8 *pBufIn, uint32 nBufLength)
209 uint i, index, partLen;
211 // Compute number of bytes mod 64
212 index = (uint)((Count[0] >> 3) & 0x3F);
214 // Update number of bits
215 if ((Count[0] += (nBufLength << 3)) < (nBufLength << 3))
216 Count[1]++;
217 Count[1] += (nBufLength >> 29);
219 partLen = 64 - index;
221 // Transform as many times as possible.
222 if (nBufLength >= partLen)
224 memcpy((uint8*)&Buffer[index], pBufIn, partLen);
225 transform (State, Buffer);
227 for (i = partLen; i + 63 < nBufLength; i += 64)
228 transform (State, &pBufIn[i]);
230 index = 0;
232 else
234 i = 0;
237 // Buffer remaining input
238 memcpy((uint8*)&Buffer[index], &pBufIn[i], nBufLength-i);
241 // ****************************************************************************
242 void CMD5Context::final (CHashKeyMD5 &out)
244 uint8 bits[8];
245 uint index, padLen;
247 // Save number of bits
248 encode (&bits[0], Count, 8);
250 // Pad out to 56 mod 64.
251 index = (unsigned int)((Count[0] >> 3) & 0x3f);
252 padLen = (index < 56) ? (56 - index) : (120 - index);
253 update (Padding, padLen);
255 // Append length (before padding)
256 update (&bits[0], 8);
257 // Store state in digest
258 encode (out.Data, State, 16);
260 // Zeroize sensitive information.
261 uint i;
262 for (i = 0; i < 4; ++i) State[i] = 0;
263 for (i = 0; i < 2; ++i) Count[i] = 0;
264 for (i = 0; i < 64; ++i) Buffer[i] = 0;
267 // Constants for MD5Transform routine.
268 // ****************************************************************************
269 #define S11 7
270 #define S12 12
271 #define S13 17
272 #define S14 22
273 #define S21 5
274 #define S22 9
275 #define S23 14
276 #define S24 20
277 #define S31 4
278 #define S32 11
279 #define S33 16
280 #define S34 23
281 #define S41 6
282 #define S42 10
283 #define S43 15
284 #define S44 21
286 // F, G, H and I are basic MD5 functions.
287 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
288 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
289 #define H(x, y, z) ((x) ^ (y) ^ (z))
290 #define I(x, y, z) ((y) ^ ((x) | (~z)))
292 // ROTATE_LEFT rotates x left n bits.
293 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
295 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
296 // Rotation is separate from addition to prevent recomputation.
297 #define FF(a, b, c, d, x, s, ac) { \
298 (a) += F ((b), (c), (d)) + (x) + (uint32)(ac); \
299 (a) = ROTATE_LEFT ((a), (s)); \
300 (a) += (b); \
302 #define GG(a, b, c, d, x, s, ac) { \
303 (a) += G ((b), (c), (d)) + (x) + (uint32)(ac); \
304 (a) = ROTATE_LEFT ((a), (s)); \
305 (a) += (b); \
307 #define HH(a, b, c, d, x, s, ac) { \
308 (a) += H ((b), (c), (d)) + (x) + (uint32)(ac); \
309 (a) = ROTATE_LEFT ((a), (s)); \
310 (a) += (b); \
312 #define II(a, b, c, d, x, s, ac) { \
313 (a) += I ((b), (c), (d)) + (x) + (uint32)(ac); \
314 (a) = ROTATE_LEFT ((a), (s)); \
315 (a) += (b); \
319 // MD5 basic transformation. Transforms state based on block.
320 // ****************************************************************************
321 void CMD5Context::transform (uint32 state[4], const uint8 block[64])
323 uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
325 decode (&x[0], &block[0], 64);
327 // Round 1
328 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); // 1
329 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); // 2
330 FF (c, d, a, b, x[ 2], S13, 0x242070db); // 3
331 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); // 4
332 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); // 5
333 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); // 6
334 FF (c, d, a, b, x[ 6], S13, 0xa8304613); // 7
335 FF (b, c, d, a, x[ 7], S14, 0xfd469501); // 8
336 FF (a, b, c, d, x[ 8], S11, 0x698098d8); // 9
337 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); // 10
338 FF (c, d, a, b, x[10], S13, 0xffff5bb1); // 11
339 FF (b, c, d, a, x[11], S14, 0x895cd7be); // 12
340 FF (a, b, c, d, x[12], S11, 0x6b901122); // 13
341 FF (d, a, b, c, x[13], S12, 0xfd987193); // 14
342 FF (c, d, a, b, x[14], S13, 0xa679438e); // 15
343 FF (b, c, d, a, x[15], S14, 0x49b40821); // 16
345 // Round 2
346 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); // 17
347 GG (d, a, b, c, x[ 6], S22, 0xc040b340); // 18
348 GG (c, d, a, b, x[11], S23, 0x265e5a51); // 19
349 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); // 20
350 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); // 21
351 GG (d, a, b, c, x[10], S22, 0x2441453); // 22
352 GG (c, d, a, b, x[15], S23, 0xd8a1e681); // 23
353 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); // 24
354 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); // 25
355 GG (d, a, b, c, x[14], S22, 0xc33707d6); // 26
356 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); // 27
357 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); // 28
358 GG (a, b, c, d, x[13], S21, 0xa9e3e905); // 29
359 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); // 30
360 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); // 31
361 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); // 32
363 // Round 3
364 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); // 33
365 HH (d, a, b, c, x[ 8], S32, 0x8771f681); // 34
366 HH (c, d, a, b, x[11], S33, 0x6d9d6122); // 35
367 HH (b, c, d, a, x[14], S34, 0xfde5380c); // 36
368 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); // 37
369 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); // 38
370 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); // 39
371 HH (b, c, d, a, x[10], S34, 0xbebfbc70); // 40
372 HH (a, b, c, d, x[13], S31, 0x289b7ec6); // 41
373 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); // 42
374 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); // 43
375 HH (b, c, d, a, x[ 6], S34, 0x4881d05); // 44
376 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); // 45
377 HH (d, a, b, c, x[12], S32, 0xe6db99e5); // 46
378 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); // 47
379 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); // 48
381 // Round 4
382 II (a, b, c, d, x[ 0], S41, 0xf4292244); // 49
383 II (d, a, b, c, x[ 7], S42, 0x432aff97); // 50
384 II (c, d, a, b, x[14], S43, 0xab9423a7); // 51
385 II (b, c, d, a, x[ 5], S44, 0xfc93a039); // 52
386 II (a, b, c, d, x[12], S41, 0x655b59c3); // 53
387 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); // 54
388 II (c, d, a, b, x[10], S43, 0xffeff47d); // 55
389 II (b, c, d, a, x[ 1], S44, 0x85845dd1); // 56
390 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); // 57
391 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); // 58
392 II (c, d, a, b, x[ 6], S43, 0xa3014314); // 59
393 II (b, c, d, a, x[13], S44, 0x4e0811a1); // 60
394 II (a, b, c, d, x[ 4], S41, 0xf7537e82); // 61
395 II (d, a, b, c, x[11], S42, 0xbd3af235); // 62
396 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); // 63
397 II (b, c, d, a, x[ 9], S44, 0xeb86d391); // 64
399 state[0] += a;
400 state[1] += b;
401 state[2] += c;
402 state[3] += d;
405 // Encodes input (guint32) into output (unsigned char). Assumes len is a multiple of 4.
406 // ****************************************************************************
407 void CMD5Context::encode (uint8 *output, const uint32 *input, uint len)
409 uint i, j;
411 for (i = 0, j = 0; j < len; i++, j += 4)
413 output[j] = (uint8)(input[i] & 0xff);
414 output[j+1] = (uint8)((input[i] >> 8) & 0xff);
415 output[j+2] = (uint8)((input[i] >> 16) & 0xff);
416 output[j+3] = (uint8)((input[i] >> 24) & 0xff);
420 // Decodes input (unsigned char) into output (guint32). Assumes len is a multiple of 4.
421 // ****************************************************************************
422 void CMD5Context::decode (uint32 *output, const uint8 *input, uint len)
424 uint i, j;
426 for (i = 0, j = 0; j < len; i++, j += 4)
427 output[i] = ((uint32)input[j]) | (((uint32)input[j+1]) << 8) |
428 (((uint32)input[j+2]) << 16) | (((uint32)input[j+3]) << 24);
432 } // namespace NLMISC