YAPOG  0.0.1
Yet Another Pokemon Online Game
Md5.cpp
Go to the documentation of this file.
2 
3 namespace yap
4 {
5  typedef struct {
6  Int64 state[4];
7  Int64 count[2];
8  uchar buffer[64];
9  } sMd5CTX;
10 
11  void MD5Init (sMd5CTX *);
12  void MD5Update (sMd5CTX *,
13  const uchar *,
14  Int32);
15  void MD5Final (uchar [16],
16  sMd5CTX *);
17 
19  {
20  }
21 
22  Md5::Md5(const String& source)
23  {
24  Calculate(source);
25  }
26 
27  Md5::Md5(const uchar* source,
28  Int32 len)
29  {
30  Calculate(source, len);
31  }
32 
34  {
35  Calculate(file);
36  }
37 
38  String Md5::Calculate(const String& source)
39  {
40  return Calculate((const uchar*)source.c_str(), source.size());
41  }
42 
44  {
45  file.seekg(0, std::ios::end);
46 
47  Int32 length = file.tellg();
48 
49  file.seekg(0, std::ios::beg);
50 
51  char* buffer = new char [length];
52 
53  file.read(buffer, length);
54  Calculate((uchar*) buffer, length);
55  delete [] buffer;
56  return msHash_;
57  }
58 
59  String Md5::Calculate(const uchar* source,
60  Int32 len)
61  {
62  sMd5CTX context;
63 
64  MD5Init(&context);
65  MD5Update(&context, source, len);
66  MD5Final(mrawHash_, &context);
67 
68  msHash_.clear();
69  msHash_.reserve(32);
70  char buffer[3];
71  buffer[2] = '\0';
72  for (Int32 i = 0; i < 16; ++i)
73  {
74  sprintf(buffer, "%02x", mrawHash_[i]);
75  msHash_ += buffer;
76  }
77  return msHash_;
78  }
79 
81  {
82  return msHash_;
83  }
84 
85  const uchar* Md5::GetRawHash() const
86  {
87  return mrawHash_;
88  }
89 
90 #pragma region Definition
91 #define S11 7
92 #define S12 12
93 #define S13 17
94 #define S14 22
95 #define S21 5
96 #define S22 9
97 #define S23 14
98 #define S24 20
99 #define S31 4
100 #define S32 11
101 #define S33 16
102 #define S34 23
103 #define S41 6
104 #define S42 10
105 #define S43 15
106 #define S44 21
107 
108  static void MD5Transform (Int64 [4], const uchar [64]);
109  static void Encode (uchar *, const Int64 *, Int32);
110  static void Decode (Int64 *, const uchar *, Int32);
111  static void MD5Memcpy (uchar*, uchar*, Int32);
112  static void MD5Memset (uchar*, Int32, Int32);
113 
114  static uchar PADDING[64] = {
115  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
116  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
117  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
118  };
119 
120  /* F, G, H and I are basic MD5 functions.
121  */
122 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
123 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
124 #define H(x, y, z) ((x) ^ (y) ^ (z))
125 #define I(x, y, z) ((y) ^ ((x) | (~z)))
126 
127  /* ROTATE_LEFT rotates x left n bits.
128  15-April-2003 Sony: use MSVC intrinsic to save some cycles
129  */
130 #ifdef _MSC_VER
131 #pragma intrinsic(_rotl)
132 #define ROTATE_LEFT(x, n) _rotl((x), (n))
133 #else
134 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
135 #endif
136 
137  /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
138  Rotation is separate from addition to prevent recomputation.
139  */
140 #define FF(a, b, c, d, x, s, ac) { \
141  (a) += F ((b), (c), (d)) + (x) + (Int64)(ac); \
142  (a) = ROTATE_LEFT ((a), (s)); \
143  (a) += (b); \
144  }
145 #define GG(a, b, c, d, x, s, ac) { \
146  (a) += G ((b), (c), (d)) + (x) + (Int64)(ac); \
147  (a) = ROTATE_LEFT ((a), (s)); \
148  (a) += (b); \
149  }
150 #define HH(a, b, c, d, x, s, ac) { \
151  (a) += H ((b), (c), (d)) + (x) + (Int64)(ac); \
152  (a) = ROTATE_LEFT ((a), (s)); \
153  (a) += (b); \
154  }
155 #define II(a, b, c, d, x, s, ac) { \
156  (a) += I ((b), (c), (d)) + (x) + (Int64)(ac); \
157  (a) = ROTATE_LEFT ((a), (s)); \
158  (a) += (b); \
159  }
160 #pragma endregion
161 
162  /* MD5 initialization. Begins an MD5 operation, writing a new context. */
163  void MD5Init (sMd5CTX *context)
164  {
165  context->count[0] = context->count[1] = 0;
166  /* Load magic initialization constants. */
167  context->state[0] = 0x67452301;
168  context->state[1] = 0xefcdab89;
169  context->state[2] = 0x98badcfe;
170  context->state[3] = 0x10325476;
171  }
172 
173  /* MD5 block update operation. Continues an MD5 message-digest
174  operation, processing another message block, and updating the
175  context. */
176  void MD5Update (sMd5CTX *context,
177  const uchar *input,
178  Int32 inputLen)
179  {
180  Int32 i = 0;
181  Int32 index = 0;
182  Int32 partLen = 0;
183 
184  /* Compute number of bytes mod 64 */
185  index = (Int32)((context->count[0] >> 3) & 0x3F);
186 
187  /* Update number of bits */
188  if ((context->count[0] += ((Int64)inputLen << 3))
189  < ((Int64)inputLen << 3))
190  context->count[1]++;
191  context->count[1] += ((Int64)inputLen >> 29);
192 
193  partLen = 64 - index;
194 
195  /* Transform as many times as possible. */
196  if (inputLen >= partLen) {
197  MD5Memcpy
198  ((uchar*)&context->buffer[index], (uchar*)input, partLen);
199  MD5Transform (context->state, context->buffer);
200 
201  for (i = partLen; i + 63 < inputLen; i += 64)
202  MD5Transform (context->state, &input[i]);
203 
204  index = 0;
205  }
206 
207  /* Buffer remaining input */
208  MD5Memcpy
209  ((uchar*)&context->buffer[index], (uchar*)&input[i],
210  inputLen-i);
211  }
212 
213  /* MD5 finalization. Ends an MD5 message-digest operation, writing the
214  the message digest and zeroizing the context. */
215  void MD5Final (uchar digest[16],
216  sMd5CTX *context)
217  {
218  uchar bits[8];
219  Int32 index = 0;
220  Int32 padLen = 0;
221 
222  /* Save number of bits */
223  Encode (bits, context->count, 8);
224 
225  /* Pad out to 56 mod 64.
226  */
227  index = (Int32)((context->count[0] >> 3) & 0x3f);
228  padLen = (index < 56) ? (56 - index) : (120 - index);
229  MD5Update (context, PADDING, padLen);
230 
231  /* Append length (before padding) */
232  MD5Update (context, bits, 8);
233  /* Store state in digest */
234  Encode (digest, context->state, 16);
235 
236  /* Zeroize sensitive information.
237  */
238  MD5Memset ((uchar*)context, 0, sizeof (*context));
239  }
240 
241  /* MD5 basic transformation. Transforms state based on block. */
242  static void MD5Transform (Int64 state[4],
243  const uchar block[64])
244  {
245  Int64 a = state[0];
246  Int64 b = state[1];
247  Int64 c = state[2];
248  Int64 d = state[3];
249  Int64 x[16];
250 
251  Decode (x, block, 64);
252 
253  /* Round 1 */
254  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
255  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
256  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
257  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
258  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
259  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
260  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
261  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
262  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
263  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
264  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
265  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
266  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
267  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
268  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
269  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
270 
271  /* Round 2 */
272  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
273  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
274  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
275  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
276  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
277  GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
278  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
279  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
280  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
281  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
282  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
283  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
284  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
285  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
286  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
287  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
288 
289  /* Round 3 */
290  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
291  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
292  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
293  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
294  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
295  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
296  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
297  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
298  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
299  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
300  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
301  HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
302  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
303  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
304  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
305  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
306 
307  /* Round 4 */
308  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
309  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
310  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
311  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
312  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
313  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
314  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
315  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
316  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
317  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
318  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
319  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
320  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
321  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
322  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
323  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
324 
325  state[0] += a;
326  state[1] += b;
327  state[2] += c;
328  state[3] += d;
329 
330  /* Zeroize sensitive information. */
331  MD5Memset ((uchar*)x, 0, sizeof (x));
332  }
333 
334  /* Encodes input (Int64) into output (uchar). Assumes len is
335  a multiple of 4. */
336  static void Encode (uchar *output,
337  const Int64 *input,
338  Int32 len)
339  {
340  Int32 i, j;
341 
342  for (i = 0, j = 0; j < len; i++, j += 4) {
343  output[j] = (uchar)(input[i] & 0xff);
344  output[j+1] = (uchar)((input[i] >> 8) & 0xff);
345  output[j+2] = (uchar)((input[i] >> 16) & 0xff);
346  output[j+3] = (uchar)((input[i] >> 24) & 0xff);
347  }
348  }
349 
350  /* Decodes input (uchar) into output (Int64). Assumes len is
351  a multiple of 4. */
352  static void Decode (Int64 *output,
353  const uchar *input,
354  Int32 len)
355  {
356  Int32 i, j;
357 
358  for (i = 0, j = 0; j < len; i++, j += 4)
359  output[i] = ((Int64)input[j]) | (((Int64)input[j+1]) << 8) |
360  (((Int64)input[j+2]) << 16) | (((Int64)input[j+3]) << 24);
361  }
362 
363  /* Note: Replace "for loop" with standard memcpy if possible. */
364  static void MD5Memcpy (uchar* output,
365  uchar* input,
366  Int32 len)
367  {
368  Int32 i;
369 
370  for (i = 0; i < len; i++)
371  output[i] = input[i];
372  }
373 
374  /* Note: Replace "for loop" with standard memset if possible. */
375  static void MD5Memset (uchar* output,
376  Int32 value,
377  Int32 len)
378  {
379  Int32 i;
380 
381  for (i = 0; i < len; i++)
382  ((char *)output)[i] = (char)value;
383  }
384 }