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



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at lun oct 28 00:14:14 CET 2019