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



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 6e6d28d09 Wed Nov 13 18:58:42 2019 +0100 at miƩ nov 13 19:00:09 CET 2019