timemory 3.3.0
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
md5.cpp
Go to the documentation of this file.
1// MIT License
2//
3// Copyright (c) 2020, The Regents of the University of California,
4// through Lawrence Berkeley National Laboratory (subject to receipt of any
5// required approvals from the U.S. Dept. of Energy). All rights reserved.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in all
15// copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23// SOFTWARE.
24
25#ifndef TIMEMORY_UTILITY_MD5_CPP_
26#define TIMEMORY_UTILITY_MD5_CPP_ 1
27
30
31#if !defined(TIMEMORY_UTILITY_HEADER_MODE)
33#endif
34
35// system implementation headers
36#include <cstdio>
37
38namespace tim
39{
40namespace md5
41{
42namespace
43{
44using size_type = typename md5sum::size_type;
45
46// Constants for md5sumTransform routine.
47constexpr uint32_t S11 = 7;
48constexpr uint32_t S12 = 12;
49constexpr uint32_t S13 = 17;
50constexpr uint32_t S14 = 22;
51constexpr uint32_t S21 = 5;
52constexpr uint32_t S22 = 9;
53constexpr uint32_t S23 = 14;
54constexpr uint32_t S24 = 20;
55constexpr uint32_t S31 = 4;
56constexpr uint32_t S32 = 11;
57constexpr uint32_t S33 = 16;
58constexpr uint32_t S34 = 23;
59constexpr uint32_t S41 = 6;
60constexpr uint32_t S42 = 10;
61constexpr uint32_t S43 = 15;
62constexpr uint32_t S44 = 21;
63
64// low level logic operations
65inline uint32_t
66F(uint32_t x, uint32_t y, uint32_t z);
67
68inline uint32_t
69G(uint32_t x, uint32_t y, uint32_t z);
70
71inline uint32_t
72H(uint32_t x, uint32_t y, uint32_t z);
73
74inline uint32_t
75I(uint32_t x, uint32_t y, uint32_t z);
76
77inline uint32_t
78rotate_left(uint32_t x, int n);
79
80inline void
81FF(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac);
82
83inline void
84GG(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac);
85
86inline void
87HH(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac);
88
89inline void
90II(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac);
91
92// F, G, H and I are basic md5sum functions.
93inline uint32_t
94F(uint32_t x, uint32_t y, uint32_t z)
95{
96 return (x & y) | (~x & z);
97}
98
99inline uint32_t
100G(uint32_t x, uint32_t y, uint32_t z)
101{
102 return (x & z) | (y & ~z);
103}
104
105inline uint32_t
106H(uint32_t x, uint32_t y, uint32_t z)
107{
108 return x ^ y ^ z;
109}
110
111inline uint32_t
112I(uint32_t x, uint32_t y, uint32_t z)
113{
114 return y ^ (x | ~z);
115}
116
117// rotate_left rotates x left n bits.
118inline uint32_t
119rotate_left(uint32_t x, int n)
120{
121 return (x << n) | (x >> (32 - n));
122}
123
124// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
125// Rotation is separate from addition to prevent recomputation.
126inline void
127FF(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac)
128{
129 a = rotate_left(a + F(b, c, d) + x + ac, s) + b;
130}
131
132inline void
133GG(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac)
134{
135 a = rotate_left(a + G(b, c, d) + x + ac, s) + b;
136}
137
138inline void
139HH(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac)
140{
141 a = rotate_left(a + H(b, c, d) + x + ac, s) + b;
142}
143
144inline void
145II(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac)
146{
147 a = rotate_left(a + I(b, c, d) + x + ac, s) + b;
148}
149
150//--------------------------------------------------------------------------------------//
151
152// decodes input (unsigned char) into output (uint32_t). Assumes len is a multiple of 4.
153inline void
154decode(uint32_t* output, const uint8_t* input, size_type len)
155{
156 for(unsigned int i = 0, j = 0; j < len; i++, j += 4)
157 output[i] = ((uint32_t) input[j]) | (((uint32_t) input[j + 1]) << 8) |
158 (((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24);
159}
160
161//--------------------------------------------------------------------------------------//
162
163// encodes input (uint32_t) into output (unsigned char). Assumes len is
164// a multiple of 4.
165inline void
166encode(uint8_t* output, const uint32_t* input, size_type len)
167{
168 for(size_type i = 0, j = 0; j < len; i++, j += 4)
169 {
170 output[j] = input[i] & 0xff;
171 output[j + 1] = (input[i] >> 8) & 0xff;
172 output[j + 2] = (input[i] >> 16) & 0xff;
173 output[j + 3] = (input[i] >> 24) & 0xff;
174 }
175}
176
177//--------------------------------------------------------------------------------------//
178
179} // namespace
180
181//--------------------------------------------------------------------------------------//
182
183// nifty shortcut ctor, compute md5sum for string and finalize it right away
186{
187 update(text.c_str(), text.length());
188 finalize();
189}
190
191//--------------------------------------------------------------------------------------//
192
193// apply md5sum algo on a block
195void
196md5sum::transform(const uint8_t block[blocksize])
197{
198 uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
199 decode(x, block, blocksize);
200
201 /* Round 1 */
202 FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
203 FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
204 FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
205 FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
206 FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
207 FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
208 FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
209 FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
210 FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
211 FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
212 FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
213 FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
214 FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
215 FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
216 FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
217 FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
218
219 /* Round 2 */
220 GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
221 GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
222 GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
223 GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
224 GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
225 GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
226 GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
227 GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
228 GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
229 GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
230 GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
231 GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
232 GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
233 GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
234 GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
235 GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
236
237 /* Round 3 */
238 HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
239 HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
240 HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
241 HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
242 HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
243 HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
244 HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
245 HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
246 HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
247 HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
248 HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
249 HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
250 HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
251 HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
252 HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
253 HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
254
255 /* Round 4 */
256 II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
257 II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
258 II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
259 II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
260 II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
261 II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
262 II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
263 II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
264 II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
265 II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
266 II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
267 II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
268 II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
269 II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
270 II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
271 II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
272
273 state[0] += a;
274 state[1] += b;
275 state[2] += c;
276 state[3] += d;
277
278 // Zeroize sensitive information.
279 memset(x, 0, sizeof x);
280}
281
282//--------------------------------------------------------------------------------------//
283
284// md5sum block update operation. Continues an md5sum message-digest
285// operation, processing another message block
287md5sum&
288md5sum::update(const unsigned char* input, size_type length)
289{
290 // compute number of bytes mod 64
291 size_type index = count[0] / 8 % blocksize;
292
293 // Update number of bits
294 if((count[0] += (length << 3)) < (length << 3))
295 count[1]++;
296 count[1] += (length >> 29);
297
298 // number of bytes we need to fill in buffer
299 size_type firstpart = 64 - index;
300 size_type i = 0;
301
302 // transform as many times as possible.
303 if(length >= firstpart)
304 {
305 // fill buffer first, transform
306 memcpy(&buffer[index], input, firstpart);
307 transform(buffer.data());
308
309 // transform chunks of blocksize (64 bytes)
310 for(i = firstpart; i + blocksize <= length; i += blocksize)
311 transform(&input[i]);
312
313 index = 0;
314 }
315
316 // buffer remaining input
317 memcpy(&buffer[index], &input[i], length - i);
318
319 return *this;
320}
321
322//--------------------------------------------------------------------------------------//
323
324// for convenience provide a verson with signed char
326md5sum&
327md5sum::update(const char* input, size_type length)
328{
329 return update((const unsigned char*) input, length);
330}
331
332//--------------------------------------------------------------------------------------//
333
334// md5sum finalization. Ends an md5sum message-digest operation, writing the
335// the message digest and zeroizing the context.
337md5sum&
339{
340 static unsigned char padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
341 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
342 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
343 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
344 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
345
346 if(!finalized)
347 {
348 // Save number of bits
349 unsigned char bits[8];
350 encode(bits, count.data(), 8);
351
352 // pad out to 56 mod 64.
353 size_type index = count[0] / 8 % 64;
354 size_type padLen = (index < 56) ? (56 - index) : (120 - index);
355 update(padding, padLen);
356
357 // Append length (before padding)
358 update(bits, 8);
359
360 // Store state in digest
361 encode(digest.data(), state.data(), 16);
362
363 // Zeroize sensitive information.
364 memset(buffer.data(), 0, sizeof buffer);
365 memset(count.data(), 0, sizeof count);
366
367 finalized = true;
368 }
369
370 return *this;
371}
372
373//--------------------------------------------------------------------------------------//
374
375// return hex representation of digest as string
379{
380 if(!finalized)
381 return "";
382
383 char buf[33];
384 for(int i = 0; i < 16; i++)
385 sprintf(buf + i * 2, "%02x", digest[i]);
386 buf[32] = '\0';
387
388 return std::string(buf);
389}
390
391//--------------------------------------------------------------------------------------//
392
394std::ostream&
395operator<<(std::ostream& out, md5sum md5)
396{
397 return out << md5.hexdigest();
398}
399
400//--------------------------------------------------------------------------------------//
401
405{
406 return md5sum{ inp }.hexdigest();
407}
408
409//--------------------------------------------------------------------------------------//
410} // namespace md5
411} // namespace tim
412
413#endif
uint32_t size_type
Definition: md5.hpp:53
md5sum & update(const unsigned char *buf, size_type length)
Definition: md5.cpp:288
md5sum()=default
std::string hexdigest() const
Definition: md5.cpp:378
static constexpr int blocksize
Definition: md5.hpp:54
md5sum & finalize()
Definition: md5.cpp:338
TIMEMORY_UTILITY_INLINE std::string compute_md5(const std::string &inp)
Definition: md5.cpp:404
TIMEMORY_UTILITY_INLINE std::ostream & operator<<(std::ostream &out, md5sum md5)
Definition: md5.cpp:395
Definition: kokkosp.cpp:39
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
#define TIMEMORY_UTILITY_INLINE
Definition: macros.hpp:308