Main MRPT website > C++ reference for MRPT 1.9.9
md5.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 /* MD5
11  converted to C++ class by Frank Thilo (thilo@unix-ag.org)
12  for bzflag (http://www.bzflag.org)
13 
14  based on:
15 
16  md5.h and md5.c
17  reference implemantion of RFC 1321
18 
19  Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
20 rights reserved.
21 
22 License to copy and use this software is granted provided that it
23 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
24 Algorithm" in all material mentioning or referencing this software
25 or this function.
26 
27 License is also granted to make and use derivative works provided
28 that such works are identified as "derived from the RSA Data
29 Security, Inc. MD5 Message-Digest Algorithm" in all material
30 mentioning or referencing the derived work.
31 
32 RSA Data Security, Inc. makes no representations concerning either
33 the merchantability of this software or the suitability of this
34 software for any particular purpose. It is provided "as is"
35 without express or implied warranty of any kind.
36 
37 These notices must be retained in any copies of any part of this
38 documentation and/or software.
39 
40 */
41 
42 #include "base-precomp.h" // Precompiled headers
43 
44 #include <mrpt/utils/md5.h>
45 
46 using namespace mrpt::utils;
47 using namespace std;
48 
49 #include <string>
50 #include <cstring>
51 #include <iostream>
52 #include <stdio.h>
53 
54 // a small class for calculating MD5 hashes of strings or byte arrays
55 // it is not meant to be fast or secure
56 //
57 // usage: 1) feed it blocks of uchars with update()
58 // 2) finalize()
59 // 3) get hexdigest() string
60 // or
61 // MD5(std::string).hexdigest()
62 //
63 // assumes that char is 8 bit and int is 32 bit
64 class MD5
65 {
66  public:
67  typedef unsigned int size_type; // must be 32bit
68 
69  MD5();
70  MD5(const std::string& text);
71  void update(const unsigned char* buf, size_type length);
72  void update(const char* buf, size_type length);
73  MD5& finalize();
74  std::string hexdigest() const;
75  friend std::ostream& operator<<(std::ostream&, MD5 md5);
76 
77  private:
78  void init();
79  typedef unsigned char uint1; // 8bit
80  typedef unsigned int uint4; // 32bit
81  enum
82  {
83  blocksize = 64
84  }; // VC6 won't eat a const static int here
85 
86  void transform(const uint1 block[blocksize]);
87  static void decode(uint4 output[], const uint1 input[], size_type len);
88  static void encode(uint1 output[], const uint4 input[], size_type len);
89 
90  bool finalized;
91  uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk
92  uint4 count[2]; // 64bit counter for number of bits (lo, hi)
93  uint4 state[4]; // digest so far
94  uint1 digest[16]; // the result
95 
96  // low level logic operations
97  static inline uint4 F(uint4 x, uint4 y, uint4 z);
98  static inline uint4 G(uint4 x, uint4 y, uint4 z);
99  static inline uint4 H(uint4 x, uint4 y, uint4 z);
100  static inline uint4 I(uint4 x, uint4 y, uint4 z);
101  static inline uint4 rotate_left(uint4 x, int n);
102  static inline void FF(
103  uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
104  static inline void GG(
105  uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
106  static inline void HH(
107  uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
108  static inline void II(
109  uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
110 };
111 
112 // Constants for MD5Transform routine.
113 #define S11 7
114 #define S12 12
115 #define S13 17
116 #define S14 22
117 #define S21 5
118 #define S22 9
119 #define S23 14
120 #define S24 20
121 #define S31 4
122 #define S32 11
123 #define S33 16
124 #define S34 23
125 #define S41 6
126 #define S42 10
127 #define S43 15
128 #define S44 21
129 
130 ///////////////////////////////////////////////
131 
132 // F, G, H and I are basic MD5 functions.
134 {
135  return (x & y) | (~x & z);
136 }
137 
139 {
140  return (x & z) | (y & ~z);
141 }
142 
143 inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) { return x ^ y ^ z; }
144 inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) { return y ^ (x | ~z); }
145 // rotate_left rotates x left n bits.
147 {
148  return (x << n) | (x >> (32 - n));
149 }
150 
151 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
152 // Rotation is separate from addition to prevent recomputation.
153 inline void MD5::FF(
154  uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
155 {
156  a = rotate_left(a + F(b, c, d) + x + ac, s) + b;
157 }
158 
159 inline void MD5::GG(
160  uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
161 {
162  a = rotate_left(a + G(b, c, d) + x + ac, s) + b;
163 }
164 
165 inline void MD5::HH(
166  uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
167 {
168  a = rotate_left(a + H(b, c, d) + x + ac, s) + b;
169 }
170 
171 inline void MD5::II(
172  uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
173 {
174  a = rotate_left(a + I(b, c, d) + x + ac, s) + b;
175 }
176 
177 //////////////////////////////////////////////
178 
179 // default ctor, just initailize
180 MD5::MD5() { init(); }
181 //////////////////////////////////////////////
182 
183 // nifty shortcut ctor, compute MD5 for string and finalize it right away
184 MD5::MD5(const std::string& text)
185 {
186  init();
187  update(text.c_str(), text.length());
188  finalize();
189 }
190 
191 //////////////////////////////
192 
193 void MD5::init()
194 {
195  finalized = false;
196 
197  count[0] = 0;
198  count[1] = 0;
199 
200  // load magic initialization constants.
201  state[0] = 0x67452301;
202  state[1] = 0xefcdab89;
203  state[2] = 0x98badcfe;
204  state[3] = 0x10325476;
205 }
206 
207 //////////////////////////////
208 
209 // decodes input (unsigned char) into output (uint4). Assumes len is a multiple
210 // of 4.
211 void MD5::decode(uint4 output[], const uint1 input[], size_type len)
212 {
213  for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
214  output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) |
215  (((uint4)input[j + 2]) << 16) |
216  (((uint4)input[j + 3]) << 24);
217 }
218 
219 //////////////////////////////
220 
221 // encodes input (uint4) into output (unsigned char). Assumes len is
222 // a multiple of 4.
223 void MD5::encode(uint1 output[], const uint4 input[], size_type len)
224 {
225  for (size_type i = 0, j = 0; j < len; i++, j += 4)
226  {
227  output[j] = input[i] & 0xff;
228  output[j + 1] = (input[i] >> 8) & 0xff;
229  output[j + 2] = (input[i] >> 16) & 0xff;
230  output[j + 3] = (input[i] >> 24) & 0xff;
231  }
232 }
233 
234 //////////////////////////////
235 
236 // apply MD5 algo on a block
237 void MD5::transform(const uint1 block[blocksize])
238 {
239  uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
240  decode(x, block, blocksize);
241 
242  /* Round 1 */
243  FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
244  FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
245  FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
246  FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
247  FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
248  FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
249  FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
250  FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
251  FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
252  FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
253  FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
254  FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
255  FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
256  FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
257  FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
258  FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
259 
260  /* Round 2 */
261  GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
262  GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
263  GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
264  GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
265  GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
266  GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
267  GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
268  GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
269  GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
270  GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
271  GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
272  GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
273  GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
274  GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
275  GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
276  GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
277 
278  /* Round 3 */
279  HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
280  HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
281  HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
282  HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
283  HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
284  HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
285  HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
286  HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
287  HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
288  HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
289  HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
290  HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
291  HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
292  HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
293  HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
294  HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
295 
296  /* Round 4 */
297  II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
298  II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
299  II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
300  II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
301  II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
302  II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
303  II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
304  II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
305  II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
306  II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
307  II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
308  II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
309  II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
310  II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
311  II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
312  II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
313 
314  state[0] += a;
315  state[1] += b;
316  state[2] += c;
317  state[3] += d;
318 
319  // Zeroize sensitive information.
320  memset(x, 0, sizeof x);
321 }
322 
323 //////////////////////////////
324 
325 // MD5 block update operation. Continues an MD5 message-digest
326 // operation, processing another message block
327 void MD5::update(const unsigned char input[], size_type length)
328 {
329  // compute number of bytes mod 64
330  size_type index = count[0] / 8 % blocksize;
331 
332  // Update number of bits
333  if ((count[0] += (length << 3)) < (length << 3)) count[1]++;
334  count[1] += (length >> 29);
335 
336  // number of bytes we need to fill in buffer
337  size_type firstpart = 64 - index;
338 
339  size_type i;
340 
341  // transform as many times as possible.
342  if (length >= firstpart)
343  {
344  // fill buffer first, transform
345  memcpy(&buffer[index], input, firstpart);
346  transform(buffer);
347 
348  // transform chunks of blocksize (64 bytes)
349  for (i = firstpart; i + blocksize <= length; i += blocksize)
350  transform(&input[i]);
351 
352  index = 0;
353  }
354  else
355  i = 0;
356 
357  // buffer remaining input
358  memcpy(&buffer[index], &input[i], length - i);
359 }
360 
361 //////////////////////////////
362 
363 // for convenience provide a verson with signed char
364 void MD5::update(const char input[], size_type length)
365 {
366  update((const unsigned char*)input, length);
367 }
368 
369 //////////////////////////////
370 
371 // MD5 finalization. Ends an MD5 message-digest operation, writing the
372 // the message digest and zeroizing the context.
374 {
375  static unsigned char padding[64] = {
376  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
377  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
378  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
379 
380  if (!finalized)
381  {
382  // Save number of bits
383  unsigned char bits[8];
384  encode(bits, count, 8);
385 
386  // pad out to 56 mod 64.
387  size_type index = count[0] / 8 % 64;
388  size_type padLen = (index < 56) ? (56 - index) : (120 - index);
389  update(padding, padLen);
390 
391  // Append length (before padding)
392  update(bits, 8);
393 
394  // Store state in digest
395  encode(digest, state, 16);
396 
397  // Zeroize sensitive information.
398  memset(buffer, 0, sizeof buffer);
399  memset(count, 0, sizeof count);
400 
401  finalized = true;
402  }
403 
404  return *this;
405 }
406 
407 //////////////////////////////
408 
409 // return hex representation of digest as string
411 {
412  if (!finalized) return "";
413 
414  char buf[33];
415  for (int i = 0; i < 16; i++) sprintf(buf + i * 2, "%02x", digest[i]);
416  buf[32] = 0;
417 
418  return std::string(buf);
419 }
420 
421 //////////////////////////////
422 
423 std::ostream& operator<<(std::ostream& out, MD5 md5)
424 {
425  return out << md5.hexdigest();
426 }
427 
428 //////////////////////////////
429 
431 {
432  MD5 md5 = MD5(str);
433  return md5.hexdigest();
434 }
435 
436 std::string mrpt::utils::md5(const unsigned char* data, const size_t len)
437 {
438  ASSERT_(data)
439  MD5 md5;
440  md5.update(data, len);
441  md5.finalize();
442 
443  return md5.hexdigest();
444 }
445 
447 {
448  return mrpt::utils::md5(&str[0], str.size());
449 }
GLuint GLuint GLsizei count
Definition: glext.h:3528
#define S43
Definition: md5.cpp:127
#define S34
Definition: md5.cpp:124
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
GLdouble GLdouble z
Definition: glext.h:3872
std::string md5(const std::string &str)
Computes the md5 of a block of data.
Definition: md5.cpp:430
GLuint buffer
Definition: glext.h:3917
void update(const unsigned char *buf, size_type length)
#define S22
Definition: md5.cpp:118
#define S11
Definition: md5.cpp:113
GLenum GLsizei n
Definition: glext.h:5074
Definition: md5.cpp:64
static void encode(uint1 output[], const uint4 input[], size_type len)
Definition: md5.cpp:223
STL namespace.
GLdouble s
Definition: glext.h:3676
GLenum GLsizei len
Definition: glext.h:4712
#define S44
Definition: md5.cpp:128
void transform(const uint1 block[blocksize])
Definition: md5.cpp:237
#define S42
Definition: md5.cpp:126
void init()
Definition: md5.cpp:193
#define S14
Definition: md5.cpp:116
GLuint index
Definition: glext.h:4054
#define S31
Definition: md5.cpp:121
const GLubyte * c
Definition: glext.h:6313
unsigned int uint4
Definition: md5.cpp:80
static uint4 G(uint4 x, uint4 y, uint4 z)
Definition: md5.cpp:138
GLubyte GLubyte b
Definition: glext.h:6279
static void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
Definition: md5.cpp:153
#define S13
Definition: md5.cpp:115
CStream & operator<<(mrpt::utils::CStream &s, const char *a)
Definition: CStream.cpp:123
GLsizei const GLchar ** string
Definition: glext.h:4101
static void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
Definition: md5.cpp:171
#define S21
Definition: md5.cpp:117
static void decode(uint4 output[], const uint1 input[], size_type len)
Definition: md5.cpp:211
#define S23
Definition: md5.cpp:119
static uint4 H(uint4 x, uint4 y, uint4 z)
Definition: md5.cpp:143
std::string hexdigest() const
Definition: md5.cpp:410
#define S12
Definition: md5.cpp:114
static uint4 rotate_left(uint4 x, int n)
Definition: md5.cpp:146
MD5 & finalize()
Definition: md5.cpp:373
bool finalized
Definition: md5.cpp:90
MD5()
Definition: md5.cpp:180
GLuint GLsizei GLsizei * length
Definition: glext.h:4064
GLenum GLenum GLenum input
Definition: glext.h:6499
static uint4 I(uint4 x, uint4 y, uint4 z)
Definition: md5.cpp:144
#define ASSERT_(f)
static void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
Definition: md5.cpp:165
GLenum GLint GLint y
Definition: glext.h:3538
#define S32
Definition: md5.cpp:122
#define S41
Definition: md5.cpp:125
GLenum GLint x
Definition: glext.h:3538
std::vector< uint8_t > vector_byte
GLuint GLenum GLenum transform
Definition: glext.h:6975
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3546
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
#define S24
Definition: md5.cpp:120
unsigned int size_type
Definition: md5.cpp:67
unsigned char uint1
Definition: md5.cpp:79
static uint4 F(uint4 x, uint4 y, uint4 z)
Definition: md5.cpp:133
int sprintf(char *buf, size_t bufSize, const char *format,...) noexcept MRPT_printf_format_check(3
An OS-independent version of sprintf (Notice the bufSize param, which may be ignored in some compiler...
Definition: os.cpp:188
static void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
Definition: md5.cpp:159
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
Definition: os.cpp:355
#define S33
Definition: md5.cpp:123



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019