Md5Sum.cc
Go to the documentation of this file.
1 
8 #include <utl/Md5Sum.h>
9 #include <string>
10 #include <sstream>
11 #include <utility>
12 #include <algorithm>
13 
14 using namespace std;
15 
16 
17 namespace utl {
18 
19  // details that are in defines in the original RSA code. They are mostly
20  // copied literally to reduce the risk of bugs.
21  namespace {
22 
23  const unsigned char gPadding[Md5Sum::kBufferSize] = { 0x80 };
24 
25  const unsigned int s11 = 7;
26  const unsigned int s12 = 12;
27  const unsigned int s13 = 17;
28  const unsigned int s14 = 22;
29  const unsigned int s21 = 5;
30  const unsigned int s22 = 9;
31  const unsigned int s23 = 14;
32  const unsigned int s24 = 20;
33  const unsigned int s31 = 4;
34  const unsigned int s32 = 11;
35  const unsigned int s33 = 16;
36  const unsigned int s34 = 23;
37  const unsigned int s41 = 6;
38  const unsigned int s42 = 10;
39  const unsigned int s43 = 15;
40  const unsigned int s44 = 21;
41 
42 
43  inline
44  unsigned int
45  F(const unsigned int x, const unsigned int y, const unsigned int z)
46  {
47  return (x & y) | (~x & z);
48  }
49 
50 
51  inline
52  unsigned int
53  G(const unsigned int x, const unsigned int y, const unsigned int z)
54  {
55  return (x & z) | (y & ~z);
56  }
57 
58 
59  inline
60  unsigned int
61  H(const unsigned int x, const unsigned int y, const unsigned int z)
62  {
63  return x ^ y ^ z;
64  }
65 
66 
67  inline
68  unsigned int
69  I(const unsigned int x, const unsigned int y, const unsigned int z)
70  {
71  return y ^ (x | ~z);
72  }
73 
74 
75  inline
76  unsigned int
77  RotateLeft(const unsigned int x, const unsigned int n)
78  {
79  return (x << n) | (x >> (32-n));
80  }
81 
82 
83  inline
84  void
85  FF(unsigned int& a,
86  const unsigned int b,
87  const unsigned int c,
88  const unsigned int d,
89  const unsigned int x,
90  const unsigned int s,
91  const unsigned int ac)
92  {
93  a += F(b, c, d) + x + ac;
94  a = RotateLeft(a, s);
95  a += b;
96  }
97 
98 
99  inline
100  void
101  GG(unsigned int& a,
102  const unsigned int b,
103  const unsigned int c,
104  const unsigned int d,
105  const unsigned int x,
106  const unsigned int s,
107  const unsigned int ac)
108  {
109  a += G(b, c, d) + x + ac;
110  a = RotateLeft(a, s);
111  a += b;
112  }
113 
114 
115  inline
116  void
117  HH(unsigned int& a,
118  const unsigned int b,
119  const unsigned int c,
120  const unsigned int d,
121  const unsigned int x,
122  const unsigned int s,
123  const unsigned int ac)
124  {
125  a += H(b, c, d) + x + ac;
126  a = RotateLeft(a, s);
127  a += b;
128  }
129 
130 
131  inline
132  void
133  II(unsigned int& a,
134  const unsigned int b,
135  const unsigned int c,
136  const unsigned int d,
137  const unsigned int x,
138  const unsigned int s,
139  const unsigned int ac)
140  {
141  a += I(b, c, d) + x + ac;
142  a = RotateLeft(a, s);
143  a += b;
144  }
145 
146 
147  inline
148  void
149  UIntToUChar(unsigned char* const outBuffer, const unsigned int input)
150  {
151  outBuffer[0] = input & 0xff;
152  outBuffer[1] = (input >> 8) & 0xff;
153  outBuffer[2] = (input >> 16) & 0xff;
154  outBuffer[3] = (input >> 24) & 0xff;
155  }
156 
157 
158  const char gHexTable[] = "0123456789abcdef";
159 
160  }
161 
162 
163  void
164  Md5Sum::Clear()
165  {
166  fFinalized = false;
167 
168  fCountLow = 0;
169  fCountHigh = 0;
170 
171  // initialize with magic numbers
172  fStateA = 0x67452301;
173  fStateB = 0xefcdab89;
174  fStateC = 0x98badcfe;
175  fStateD = 0x10325476;
176  }
177 
178 
179  void
180  Md5Sum::AddDataRange(const unsigned char* const begin, const unsigned char* const end)
181  {
182  if (fFinalized)
183  throw WrongStageException("Cannot add data to Md5Sum object after extracting digest");
184 
185  if (begin > end)
186  throw InvalidIteratorException("begin > end");
187 
188  // bytecount mod buffer size from bitcount
189  unsigned int index = BufferIndex();
190 
191  // update number of bits
192  const unsigned int length = end - begin;
193  const unsigned int bits = (length << 3);
194  fCountLow += bits;
195  if (fCountLow < bits) // overflow
196  ++fCountHigh;
197  fCountHigh += (length >> 29); // top 3 bits are carried over
198 
199  for (const unsigned char* p = begin; p < end; ++p) {
200  fBuffer[index] = *p;
201  ++index;
202  if (index == kBufferSize) {
203  ProcessBuffer();
204  index = 0;
205  }
206  }
207  }
208 
209 
210  void
211  Md5Sum::ProcessBuffer()
212  {
213  const unsigned int scratchSize = 16; // buffer size / 4
214  unsigned int x[scratchSize];
215 
216  for (unsigned int i = 0; i < scratchSize; ++i) {
217  const unsigned int i4 = 4*i;
218  x[i] = fBuffer[i4] |
219  fBuffer[i4+1] << 8 |
220  fBuffer[i4+2] << 16 |
221  fBuffer[i4+3] << 24;
222  }
223 
224  unsigned int a = fStateA;
225  unsigned int b = fStateB;
226  unsigned int c = fStateC;
227  unsigned int d = fStateD;
228 
229  /* Round 1 */
230  FF(a, b, c, d, x[ 0], s11, 0xd76aa478); /* 1 */
231  FF(d, a, b, c, x[ 1], s12, 0xe8c7b756); /* 2 */
232  FF(c, d, a, b, x[ 2], s13, 0x242070db); /* 3 */
233  FF(b, c, d, a, x[ 3], s14, 0xc1bdceee); /* 4 */
234  FF(a, b, c, d, x[ 4], s11, 0xf57c0faf); /* 5 */
235  FF(d, a, b, c, x[ 5], s12, 0x4787c62a); /* 6 */
236  FF(c, d, a, b, x[ 6], s13, 0xa8304613); /* 7 */
237  FF(b, c, d, a, x[ 7], s14, 0xfd469501); /* 8 */
238  FF(a, b, c, d, x[ 8], s11, 0x698098d8); /* 9 */
239  FF(d, a, b, c, x[ 9], s12, 0x8b44f7af); /* 10 */
240  FF(c, d, a, b, x[10], s13, 0xffff5bb1); /* 11 */
241  FF(b, c, d, a, x[11], s14, 0x895cd7be); /* 12 */
242  FF(a, b, c, d, x[12], s11, 0x6b901122); /* 13 */
243  FF(d, a, b, c, x[13], s12, 0xfd987193); /* 14 */
244  FF(c, d, a, b, x[14], s13, 0xa679438e); /* 15 */
245  FF(b, c, d, a, x[15], s14, 0x49b40821); /* 16 */
246 
247  /* Round 2 */
248  GG(a, b, c, d, x[ 1], s21, 0xf61e2562); /* 17 */
249  GG(d, a, b, c, x[ 6], s22, 0xc040b340); /* 18 */
250  GG(c, d, a, b, x[11], s23, 0x265e5a51); /* 19 */
251  GG(b, c, d, a, x[ 0], s24, 0xe9b6c7aa); /* 20 */
252  GG(a, b, c, d, x[ 5], s21, 0xd62f105d); /* 21 */
253  GG(d, a, b, c, x[10], s22, 0x02441453); /* 22 */
254  GG(c, d, a, b, x[15], s23, 0xd8a1e681); /* 23 */
255  GG(b, c, d, a, x[ 4], s24, 0xe7d3fbc8); /* 24 */
256  GG(a, b, c, d, x[ 9], s21, 0x21e1cde6); /* 25 */
257  GG(d, a, b, c, x[14], s22, 0xc33707d6); /* 26 */
258  GG(c, d, a, b, x[ 3], s23, 0xf4d50d87); /* 27 */
259  GG(b, c, d, a, x[ 8], s24, 0x455a14ed); /* 28 */
260  GG(a, b, c, d, x[13], s21, 0xa9e3e905); /* 29 */
261  GG(d, a, b, c, x[ 2], s22, 0xfcefa3f8); /* 30 */
262  GG(c, d, a, b, x[ 7], s23, 0x676f02d9); /* 31 */
263  GG(b, c, d, a, x[12], s24, 0x8d2a4c8a); /* 32 */
264 
265  /* Round 3 */
266  HH(a, b, c, d, x[ 5], s31, 0xfffa3942); /* 33 */
267  HH(d, a, b, c, x[ 8], s32, 0x8771f681); /* 34 */
268  HH(c, d, a, b, x[11], s33, 0x6d9d6122); /* 35 */
269  HH(b, c, d, a, x[14], s34, 0xfde5380c); /* 36 */
270  HH(a, b, c, d, x[ 1], s31, 0xa4beea44); /* 37 */
271  HH(d, a, b, c, x[ 4], s32, 0x4bdecfa9); /* 38 */
272  HH(c, d, a, b, x[ 7], s33, 0xf6bb4b60); /* 39 */
273  HH(b, c, d, a, x[10], s34, 0xbebfbc70); /* 40 */
274  HH(a, b, c, d, x[13], s31, 0x289b7ec6); /* 41 */
275  HH(d, a, b, c, x[ 0], s32, 0xeaa127fa); /* 42 */
276  HH(c, d, a, b, x[ 3], s33, 0xd4ef3085); /* 43 */
277  HH(b, c, d, a, x[ 6], s34, 0x04881d05); /* 44 */
278  HH(a, b, c, d, x[ 9], s31, 0xd9d4d039); /* 45 */
279  HH(d, a, b, c, x[12], s32, 0xe6db99e5); /* 46 */
280  HH(c, d, a, b, x[15], s33, 0x1fa27cf8); /* 47 */
281  HH(b, c, d, a, x[ 2], s34, 0xc4ac5665); /* 48 */
282 
283  /* Round 4 */
284  II(a, b, c, d, x[ 0], s41, 0xf4292244); /* 49 */
285  II(d, a, b, c, x[ 7], s42, 0x432aff97); /* 50 */
286  II(c, d, a, b, x[14], s43, 0xab9423a7); /* 51 */
287  II(b, c, d, a, x[ 5], s44, 0xfc93a039); /* 52 */
288  II(a, b, c, d, x[12], s41, 0x655b59c3); /* 53 */
289  II(d, a, b, c, x[ 3], s42, 0x8f0ccc92); /* 54 */
290  II(c, d, a, b, x[10], s43, 0xffeff47d); /* 55 */
291  II(b, c, d, a, x[ 1], s44, 0x85845dd1); /* 56 */
292  II(a, b, c, d, x[ 8], s41, 0x6fa87e4f); /* 57 */
293  II(d, a, b, c, x[15], s42, 0xfe2ce6e0); /* 58 */
294  II(c, d, a, b, x[ 6], s43, 0xa3014314); /* 59 */
295  II(b, c, d, a, x[13], s44, 0x4e0811a1); /* 60 */
296  II(a, b, c, d, x[ 4], s41, 0xf7537e82); /* 61 */
297  II(d, a, b, c, x[11], s42, 0xbd3af235); /* 62 */
298  II(c, d, a, b, x[ 2], s43, 0x2ad7d2bb); /* 63 */
299  II(b, c, d, a, x[ 9], s44, 0xeb86d391); /* 64 */
300 
301  fStateA += a;
302  fStateB += b;
303  fStateC += c;
304  fStateD += d;
305  }
306 
307 
309  Md5Sum::GetRawDigest()
310  {
311  if (!fFinalized) {
312  unsigned char bitCountBuffer[8];
313 
314  UIntToUChar(bitCountBuffer, fCountLow);
315  UIntToUChar(bitCountBuffer + 4, fCountHigh);
316 
317  int length = int(kBufferSize - 8) - int(BufferIndex());
318  // message always has to be padded with one bit (0x80)
319  if (length < 1)
320  length += kBufferSize;
321  AddDataRange(gPadding, gPadding + length);
322  // the remaining 8 bits are for the bitcount
323  AddDataRange(bitCountBuffer, bitCountBuffer + 8);
324 
325  UIntToUChar(fDigest, fStateA);
326  UIntToUChar(fDigest + 4, fStateB);
327  UIntToUChar(fDigest + 8, fStateC);
328  UIntToUChar(fDigest + 12, fStateD);
329 
330  // wipe out state
331  Clear();
332  fFinalized = true;
333  }
334 
335  return make_pair(fDigest, fDigest + kDigestSize);
336  }
337 
338 
339  string
340  Md5Sum::GetHexDigest()
341  {
342  string digest;
343  IteratorPair iters = GetRawDigest();
344 
345  for (Iterator cur = iters.first; cur != iters.second; ++cur) {
346  digest.push_back(gHexTable[(*cur >> 4) % 16]);
347  digest.push_back(gHexTable[*cur % 16]);
348  }
349 
350  return digest;
351  }
352 
353 }
#define I
constexpr double s
Definition: AugerUnits.h:163
std::pair< Iterator, Iterator > IteratorPair
Definition: Md5Sum.h:30
Exception for invalid operation on Iterators.
const unsigned char * Iterator
Definition: Md5Sum.h:29

, generated on Tue Sep 26 2023.