RSB  0.7.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MD5.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is a part of the RSB project.
4  *
5  * Copyright (C) 2011 by Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de>
6  *
7  * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu> and heavily modified
8  * for GnuPG by <werner.koch@guug.de> and adapted for the need of FPM Blowfish
9  * Plugin
10  *
11  * Latest author:
12  * Frederic RUAUDEL <grumz@users.sf.net>
13  * FPMBlowfishPlugin
14  * Copyleft (c) 2003 Frederic RUAUDEL, all rights reversed
15  * Copyleft (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
16  *
17  * This file may be licensed under the terms of the
18  * GNU Lesser General Public License Version 3 (the ``LGPL''),
19  * or (at your option) any later version.
20  *
21  * Software distributed under the License is distributed
22  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
23  * express or implied. See the LGPL for the specific language
24  * governing rights and limitations.
25  *
26  * You should have received a copy of the LGPL along with this
27  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
28  * or write to the Free Software Foundation, Inc.,
29  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30  *
31  * The development of this software was supported by:
32  * CoR-Lab, Research Institute for Cognition and Robotics
33  * Bielefeld University
34  *
35  * ============================================================ */
36 
37 #include "MD5.h"
38 
39 #include <sstream>
40 #include <iomanip>
41 #include <ios>
42 
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 
47 using namespace std;
48 
49 namespace rsb {
50 namespace util {
51 
55 #if defined(__GNUC__) && defined(__i386__)
56 static inline unsigned int rol(unsigned int x, int n)
57 {
58  __asm__("roll %%cl,%0"
59  :"=r" (x)
60  :"0" (x),"c" (n));
61  return x;
62 }
63 #else
64 #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
65 #endif
66 
67 /* These are the four functions used in the four steps of the MD5 algorithm
68  and defined in the RFC 1321. The first function is a little bit optimized
69  (as found in Colin Plumbs public domain implementation). */
70 /* #define FF(b, c, d) ((b & c) | (~b & d)) */
71 #define FF(b, c, d) (d ^ (b & (c ^ d)))
72 #define FG(b, c, d) FF (d, b, c)
73 #define FH(b, c, d) (b ^ c ^ d)
74 #define FI(b, c, d) (c ^ (b | ~d))
75 
76 class MD5Hasher {
77 public:
78 
79  typedef unsigned int u32;
80  typedef unsigned char byte;
81 
83  this->init();
84  }
85 
87  }
88 
93  byte* hash(byte* buf, size_t nbytes) {
94  byte* ret_val;
95 
96  this->init();
97  this->write(buf, nbytes);
98  this->final();
99 
100  ret_val = (byte*) malloc(16);
101  memset(ret_val, 0, 16);
102  memcpy(ret_val, this->read(), 16);
103 
104  return (ret_val);
105  }
106 
107 private:
108 
109  void init() {
110  this->A = 0x67452301;
111  this->B = 0xefcdab89;
112  this->C = 0x98badcfe;
113  this->D = 0x10325476;
114 
115  this->nblocks = 0;
116  this->count = 0;
117 
118  memset(buf, 0, 64);
119  }
120 
124  void transform(byte* data) {
125  u32 correct_words[16];
126  u32 A = this->A;
127  u32 B = this->B;
128  u32 C = this->C;
129  u32 D = this->D;
130  u32* cwp = correct_words;
131 
132 #ifdef BIG_ENDIAN_HOST
133  {
134  int i;
135  byte *p2, *p1;
136 
137  for (i = 0, p1 = data, p2 = (byte*)correct_words; i < 16; i++, p2 += 4)
138  {
139  p2[3] = *p1++;
140  p2[2] = *p1++;
141  p2[1] = *p1++;
142  p2[0] = *p1++;
143  }
144  }
145 #else
146  memcpy(correct_words, data, 64);
147 #endif
148 
149 #define OP(a, b, c, d, s, T) \
150  do \
151  { \
152  a += FF (b, c, d) + (*cwp++) + T; \
153  a = rol(a, s); \
154  a += b; \
155  } while (0)
156 
157  /* Before we start, one word about the strange constants.
158  They are defined in RFC 1321 as
159 
160  T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
161  */
162 
163  /* Round 1. */OP (A, B, C, D, 7, 0xd76aa478);
164  OP (D, A, B, C, 12, 0xe8c7b756);
165  OP (C, D, A, B, 17, 0x242070db);
166  OP (B, C, D, A, 22, 0xc1bdceee);
167  OP (A, B, C, D, 7, 0xf57c0faf);
168  OP (D, A, B, C, 12, 0x4787c62a);
169  OP (C, D, A, B, 17, 0xa8304613);
170  OP (B, C, D, A, 22, 0xfd469501);
171  OP (A, B, C, D, 7, 0x698098d8);
172  OP (D, A, B, C, 12, 0x8b44f7af);
173  OP (C, D, A, B, 17, 0xffff5bb1);
174  OP (B, C, D, A, 22, 0x895cd7be);
175  OP (A, B, C, D, 7, 0x6b901122);
176  OP (D, A, B, C, 12, 0xfd987193);
177  OP (C, D, A, B, 17, 0xa679438e);
178  OP (B, C, D, A, 22, 0x49b40821);
179 
180 #undef OP
181 #define OP(f, a, b, c, d, k, s, T) \
182  do \
183  { \
184  a += f (b, c, d) + correct_words[k] + T; \
185  a = rol(a, s); \
186  a += b; \
187  } while (0)
188 
189  // Round 2.
190  OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
191  OP (FG, D, A, B, C, 6, 9, 0xc040b340);
192  OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
193  OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
194  OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
195  OP (FG, D, A, B, C, 10, 9, 0x02441453);
196  OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
197  OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
198  OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
199  OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
200  OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
201  OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
202  OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
203  OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
204  OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
205  OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
206 
207  // Round 3.
208  OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
209  OP (FH, D, A, B, C, 8, 11, 0x8771f681);
210  OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
211  OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
212  OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
213  OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
214  OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
215  OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
216  OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
217  OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
218  OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
219  OP (FH, B, C, D, A, 6, 23, 0x04881d05);
220  OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
221  OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
222  OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
223  OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
224 
225  // Round 4.
226  OP (FI, A, B, C, D, 0, 6, 0xf4292244);
227  OP (FI, D, A, B, C, 7, 10, 0x432aff97);
228  OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
229  OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
230  OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
231  OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
232  OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
233  OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
234  OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
235  OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
236  OP (FI, C, D, A, B, 6, 15, 0xa3014314);
237  OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
238  OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
239  OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
240  OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
241  OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
242 
243  // Put checksum in context given as argument.
244  this->A += A;
245  this->B += B;
246  this->C += C;
247  this->D += D;
248  }
249 
255  void write(byte* inbuf, size_t inlen) {
256  if (this->count == 64) /* flush the buffer */
257  {
258  this->transform(this->buf);
259  this->count = 0;
260  this->nblocks++;
261  }
262 
263  if (!inbuf) {
264  return;
265  }
266 
267  if (this->count) {
268  for (; inlen && this->count < 64; inlen--) {
269  this->buf[this->count++] = *inbuf++;
270  }
271 
272  this->write(NULL, 0);
273  if (!inlen) {
274  return;
275  }
276  }
277 
278  while (inlen >= 64) {
279  this->transform(inbuf);
280  this->count = 0;
281  this->nblocks++;
282  inlen -= 64;
283  inbuf += 64;
284  }
285 
286  for (; inlen && this->count < 64; inlen--) {
287  this->buf[this->count++] = *inbuf++;
288  }
289  }
290 
297  void final() {
298  u32 t, msb, lsb;
299  byte* p;
300 
301  this->write(NULL, 0);
302 
303  msb = 0;
304  t = this->nblocks;
305 
306  if ((lsb = t << 6) < t) /* multiply by 64 to make a byte count */
307  {
308  msb++;
309  }
310 
311  msb += t >> 26;
312  t = lsb;
313 
314  if ((lsb = t + this->count) < t) /* add the count */
315  {
316  msb++;
317  }
318 
319  t = lsb;
320 
321  if ((lsb = t << 3) < t) /* multiply by 8 to make a bit count */
322  {
323  msb++;
324  }
325 
326  msb += t >> 29;
327 
328  if (this->count < 56) /* enough room */
329  {
330  this->buf[this->count++] = 0x80; /* pad */
331 
332  while (this->count < 56) {
333  this->buf[this->count++] = 0; /* pad */
334  }
335  } else /* need one extra block */
336  {
337  this->buf[this->count++] = 0x80; /* pad character */
338 
339  while (this->count < 64) {
340  this->buf[this->count++] = 0;
341  }
342 
343  this->write(NULL, 0); /* flush */
344 
345  memset(this->buf, 0, 56); /* fill next block with zeroes */
346  }
347 
348  /* append the 64 bit count */
349  this->buf[56] = lsb;
350  this->buf[57] = lsb >> 8;
351  this->buf[58] = lsb >> 16;
352  this->buf[59] = lsb >> 24;
353  this->buf[60] = msb;
354  this->buf[61] = msb >> 8;
355  this->buf[62] = msb >> 16;
356  this->buf[63] = msb >> 24;
357 
358  this->transform(this->buf);
359 
360  p = this->buf;
361 
362 #ifdef BIG_ENDIAN_HOST
363 #define X(a) do { *p++ = this->##a ; *p++ = this->##a >> 8; \
364  *p++ = this->##a >> 16; *p++ = this->##a >> 24; } while(0)
365 #else /* little endian */
366  /*#define X(a) do { *(u32*)p = this->##a ; p += 4; } while(0)*/
367  /* Unixware's cpp doesn't like the above construct so we do it his way:
368  * (reported by Allan Clark) */
369 #define X(a) do { *(u32*)p = (*this).a ; p += 4; } while(0)
370 #endif
371 
372  X(A);
373  X(B);
374  X(C);
375  X(D);
376 
377 #undef X
378  }
379 
380  byte* read() {
381  return this->buf;
382  }
383 
389  byte buf[64];
390  int count;
391 
392 };
393 
394 void freeMd5Hash(void* hash) {
395  free((unsigned char*) hash);
396 }
397 
398 MD5::MD5(const string& s) :
399  hasher(new MD5Hasher),
400  hash(hasher->hash((unsigned char*) s.c_str(), strlen(s.c_str())),
401  freeMd5Hash) {
402 }
403 
405 }
406 
407 string MD5::toHexString(const bool& pretty) const {
408 
409  stringstream s;
410  s << hex;
411 
412  for (int i = 0; i < 16; ++i) {
413  if (pretty && ((i % 4) == 0) && i != 0) {
414  s << " ";
415  }
416  s << setw(2) << setfill('0') << (int) hash[i];
417  }
418 
419  return s.str();
420 
421 }
422 
423 ostream& operator<<(ostream& stream, const MD5& sum) {
424  return stream << sum.toHexString(true);
425 }
426 
427 }
428 }