1 | /* |
2 | * This RFC 1321 compatible MD5 implementation originated at: |
3 | * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 |
4 | * |
5 | * Author: |
6 | * Alexander Peslyak, better known as Solar Designer <solar at openwall.com> |
7 | * |
8 | * This software was written by Alexander Peslyak in 2001. No copyright is |
9 | * claimed, and the software is hereby placed in the public domain. |
10 | * In case this attempt to disclaim copyright and place the software in the |
11 | * public domain is deemed null and void, then the software is |
12 | * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the |
13 | * general public under the following terms: |
14 | * |
15 | * Redistribution and use in source and binary forms, with or without |
16 | * modification, are permitted. |
17 | * |
18 | * There's ABSOLUTELY NO WARRANTY, express or implied. |
19 | * |
20 | */ |
21 | |
22 | // Distributed under the Boost Software License, Version 1.0. (See |
23 | // accompanying file LICENSE_1_0.txt or copy at |
24 | // https://www.boost.org/LICENSE_1_0.txt) |
25 | |
26 | #ifndef BOOST_UUID_MD5_HPP |
27 | #define BOOST_UUID_MD5_HPP |
28 | |
29 | #include <boost/cast.hpp> |
30 | #include <boost/config.hpp> |
31 | #include <boost/cstdint.hpp> |
32 | #include <boost/uuid/uuid.hpp> // for version |
33 | #include <boost/predef/other/endian.h> |
34 | #include <string.h> |
35 | |
36 | namespace boost { |
37 | namespace uuids { |
38 | namespace detail { |
39 | |
40 | class md5 |
41 | { |
42 | public: |
43 | typedef unsigned int(digest_type)[4]; |
44 | |
45 | md5() |
46 | { |
47 | MD5_Init(ctx: &ctx_); |
48 | } |
49 | |
50 | void process_byte(unsigned char byte) |
51 | { |
52 | MD5_Update(ctx: &ctx_, data: &byte, size: 1); |
53 | } |
54 | |
55 | void process_bytes(void const* buffer, std::size_t byte_count) |
56 | { |
57 | MD5_Update(ctx: &ctx_, data: buffer, size: boost::numeric_cast<unsigned long>(arg: byte_count)); |
58 | } |
59 | |
60 | void get_digest(digest_type& digest) |
61 | { |
62 | MD5_Final(result: reinterpret_cast<unsigned char *>(&digest[0]), ctx: &ctx_); |
63 | } |
64 | |
65 | unsigned char get_version() const |
66 | { |
67 | // RFC 4122 Section 4.1.3 |
68 | return uuid::version_name_based_md5; |
69 | } |
70 | |
71 | private: |
72 | |
73 | /* Any 32-bit or wider unsigned integer data type will do */ |
74 | typedef uint32_t MD5_u32plus; |
75 | |
76 | typedef struct { |
77 | MD5_u32plus lo, hi; |
78 | MD5_u32plus a, b, c, d; |
79 | unsigned char buffer[64]; |
80 | MD5_u32plus block[16]; |
81 | } MD5_CTX; |
82 | |
83 | /* |
84 | * The basic MD5 functions. |
85 | * |
86 | * F and G are optimized compared to their RFC 1321 definitions for |
87 | * architectures that lack an AND-NOT instruction, just like in Colin Plumb's |
88 | * implementation. |
89 | */ |
90 | BOOST_FORCEINLINE MD5_u32plus BOOST_UUID_DETAIL_MD5_F(MD5_u32plus x, MD5_u32plus y, MD5_u32plus z) { return ((z) ^ ((x) & ((y) ^ (z)))); } |
91 | BOOST_FORCEINLINE MD5_u32plus BOOST_UUID_DETAIL_MD5_G(MD5_u32plus x, MD5_u32plus y, MD5_u32plus z) { return ((y) ^ ((z) & ((x) ^ (y)))); } |
92 | BOOST_FORCEINLINE MD5_u32plus BOOST_UUID_DETAIL_MD5_H(MD5_u32plus x, MD5_u32plus y, MD5_u32plus z) { return (((x) ^ (y)) ^ (z)); } |
93 | BOOST_FORCEINLINE MD5_u32plus BOOST_UUID_DETAIL_MD5_H2(MD5_u32plus x, MD5_u32plus y, MD5_u32plus z) { return ((x) ^ ((y) ^ (z))); } |
94 | BOOST_FORCEINLINE MD5_u32plus BOOST_UUID_DETAIL_MD5_I(MD5_u32plus x, MD5_u32plus y, MD5_u32plus z) { return ((y) ^ ((x) | ~(z))); } |
95 | |
96 | /* |
97 | * The MD5 transformation for all four rounds. |
98 | */ |
99 | #define BOOST_UUID_DETAIL_MD5_STEP(f, a, b, c, d, x, t, s) \ |
100 | (a) += f((b), (c), (d)) + (x) + (t); \ |
101 | (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ |
102 | (a) += (b); |
103 | |
104 | /* |
105 | * SET reads 4 input bytes in little-endian byte order and stores them in a |
106 | * properly aligned word in host byte order. |
107 | * |
108 | * The check for little-endian architectures that tolerate unaligned memory |
109 | * accesses is just an optimization. Nothing will break if it fails to detect |
110 | * a suitable architecture. |
111 | * |
112 | * Unfortunately, this optimization may be a C strict aliasing rules violation |
113 | * if the caller's data buffer has effective type that cannot be aliased by |
114 | * MD5_u32plus. In practice, this problem may occur if these MD5 routines are |
115 | * inlined into a calling function, or with future and dangerously advanced |
116 | * link-time optimizations. For the time being, keeping these MD5 routines in |
117 | * their own translation unit avoids the problem. |
118 | */ |
119 | #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) |
120 | #define BOOST_UUID_DETAIL_MD5_SET(n) \ |
121 | (*(MD5_u32plus *)&ptr[(n) * 4]) |
122 | #define BOOST_UUID_DETAIL_MD5_GET(n) \ |
123 | BOOST_UUID_DETAIL_MD5_SET(n) |
124 | #else |
125 | #define BOOST_UUID_DETAIL_MD5_SET(n) \ |
126 | (ctx->block[(n)] = \ |
127 | (MD5_u32plus)ptr[(n) * 4] | \ |
128 | ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ |
129 | ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ |
130 | ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) |
131 | #define BOOST_UUID_DETAIL_MD5_GET(n) \ |
132 | (ctx->block[(n)]) |
133 | #endif |
134 | |
135 | /* |
136 | * This processes one or more 64-byte data blocks, but does NOT update the bit |
137 | * counters. There are no alignment requirements. |
138 | */ |
139 | const void *body(MD5_CTX *ctx, const void *data, unsigned long size) |
140 | { |
141 | const unsigned char *ptr; |
142 | MD5_u32plus a, b, c, d; |
143 | MD5_u32plus saved_a, saved_b, saved_c, saved_d; |
144 | |
145 | ptr = (const unsigned char *)data; |
146 | |
147 | a = ctx->a; |
148 | b = ctx->b; |
149 | c = ctx->c; |
150 | d = ctx->d; |
151 | |
152 | do { |
153 | saved_a = a; |
154 | saved_b = b; |
155 | saved_c = c; |
156 | saved_d = d; |
157 | |
158 | /* Round 1 */ |
159 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, a, b, c, d, BOOST_UUID_DETAIL_MD5_SET(0), 0xd76aa478, 7) |
160 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, d, a, b, c, BOOST_UUID_DETAIL_MD5_SET(1), 0xe8c7b756, 12) |
161 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, c, d, a, b, BOOST_UUID_DETAIL_MD5_SET(2), 0x242070db, 17) |
162 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, b, c, d, a, BOOST_UUID_DETAIL_MD5_SET(3), 0xc1bdceee, 22) |
163 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, a, b, c, d, BOOST_UUID_DETAIL_MD5_SET(4), 0xf57c0faf, 7) |
164 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, d, a, b, c, BOOST_UUID_DETAIL_MD5_SET(5), 0x4787c62a, 12) |
165 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, c, d, a, b, BOOST_UUID_DETAIL_MD5_SET(6), 0xa8304613, 17) |
166 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, b, c, d, a, BOOST_UUID_DETAIL_MD5_SET(7), 0xfd469501, 22) |
167 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, a, b, c, d, BOOST_UUID_DETAIL_MD5_SET(8), 0x698098d8, 7) |
168 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, d, a, b, c, BOOST_UUID_DETAIL_MD5_SET(9), 0x8b44f7af, 12) |
169 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, c, d, a, b, BOOST_UUID_DETAIL_MD5_SET(10), 0xffff5bb1, 17) |
170 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, b, c, d, a, BOOST_UUID_DETAIL_MD5_SET(11), 0x895cd7be, 22) |
171 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, a, b, c, d, BOOST_UUID_DETAIL_MD5_SET(12), 0x6b901122, 7) |
172 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, d, a, b, c, BOOST_UUID_DETAIL_MD5_SET(13), 0xfd987193, 12) |
173 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, c, d, a, b, BOOST_UUID_DETAIL_MD5_SET(14), 0xa679438e, 17) |
174 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_F, b, c, d, a, BOOST_UUID_DETAIL_MD5_SET(15), 0x49b40821, 22) |
175 | |
176 | /* Round 2 */ |
177 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(1), 0xf61e2562, 5) |
178 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(6), 0xc040b340, 9) |
179 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(11), 0x265e5a51, 14) |
180 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(0), 0xe9b6c7aa, 20) |
181 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(5), 0xd62f105d, 5) |
182 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(10), 0x02441453, 9) |
183 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(15), 0xd8a1e681, 14) |
184 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(4), 0xe7d3fbc8, 20) |
185 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(9), 0x21e1cde6, 5) |
186 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(14), 0xc33707d6, 9) |
187 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(3), 0xf4d50d87, 14) |
188 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(8), 0x455a14ed, 20) |
189 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(13), 0xa9e3e905, 5) |
190 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(2), 0xfcefa3f8, 9) |
191 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(7), 0x676f02d9, 14) |
192 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_G, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(12), 0x8d2a4c8a, 20) |
193 | |
194 | /* Round 3 */ |
195 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(5), 0xfffa3942, 4) |
196 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(8), 0x8771f681, 11) |
197 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(11), 0x6d9d6122, 16) |
198 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(14), 0xfde5380c, 23) |
199 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(1), 0xa4beea44, 4) |
200 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(4), 0x4bdecfa9, 11) |
201 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(7), 0xf6bb4b60, 16) |
202 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(10), 0xbebfbc70, 23) |
203 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(13), 0x289b7ec6, 4) |
204 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(0), 0xeaa127fa, 11) |
205 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(3), 0xd4ef3085, 16) |
206 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(6), 0x04881d05, 23) |
207 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(9), 0xd9d4d039, 4) |
208 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(12), 0xe6db99e5, 11) |
209 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(15), 0x1fa27cf8, 16) |
210 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_H2, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(2), 0xc4ac5665, 23) |
211 | |
212 | /* Round 4 */ |
213 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(0), 0xf4292244, 6) |
214 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(7), 0x432aff97, 10) |
215 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(14), 0xab9423a7, 15) |
216 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(5), 0xfc93a039, 21) |
217 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(12), 0x655b59c3, 6) |
218 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(3), 0x8f0ccc92, 10) |
219 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(10), 0xffeff47d, 15) |
220 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(1), 0x85845dd1, 21) |
221 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(8), 0x6fa87e4f, 6) |
222 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(15), 0xfe2ce6e0, 10) |
223 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(6), 0xa3014314, 15) |
224 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(13), 0x4e0811a1, 21) |
225 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, a, b, c, d, BOOST_UUID_DETAIL_MD5_GET(4), 0xf7537e82, 6) |
226 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, d, a, b, c, BOOST_UUID_DETAIL_MD5_GET(11), 0xbd3af235, 10) |
227 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, c, d, a, b, BOOST_UUID_DETAIL_MD5_GET(2), 0x2ad7d2bb, 15) |
228 | BOOST_UUID_DETAIL_MD5_STEP(BOOST_UUID_DETAIL_MD5_I, b, c, d, a, BOOST_UUID_DETAIL_MD5_GET(9), 0xeb86d391, 21) |
229 | |
230 | a += saved_a; |
231 | b += saved_b; |
232 | c += saved_c; |
233 | d += saved_d; |
234 | |
235 | ptr += 64; |
236 | } while (size -= 64); |
237 | |
238 | ctx->a = a; |
239 | ctx->b = b; |
240 | ctx->c = c; |
241 | ctx->d = d; |
242 | |
243 | return ptr; |
244 | } |
245 | |
246 | void MD5_Init(MD5_CTX *ctx) |
247 | { |
248 | ctx->a = 0x67452301; |
249 | ctx->b = 0xefcdab89; |
250 | ctx->c = 0x98badcfe; |
251 | ctx->d = 0x10325476; |
252 | |
253 | ctx->lo = 0; |
254 | ctx->hi = 0; |
255 | } |
256 | |
257 | void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) |
258 | { |
259 | MD5_u32plus saved_lo; |
260 | unsigned long used, available; |
261 | |
262 | saved_lo = ctx->lo; |
263 | if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) |
264 | ctx->hi++; |
265 | ctx->hi += size >> 29; |
266 | |
267 | used = saved_lo & 0x3f; |
268 | |
269 | if (used) { |
270 | available = 64 - used; |
271 | |
272 | if (size < available) { |
273 | memcpy(dest: &ctx->buffer[used], src: data, n: size); |
274 | return; |
275 | } |
276 | |
277 | memcpy(dest: &ctx->buffer[used], src: data, n: available); |
278 | data = (const unsigned char *)data + available; |
279 | size -= available; |
280 | body(ctx, data: ctx->buffer, size: 64); |
281 | } |
282 | |
283 | if (size >= 64) { |
284 | data = body(ctx, data, size: size & ~(unsigned long)0x3f); |
285 | size &= 0x3f; |
286 | } |
287 | |
288 | memcpy(dest: ctx->buffer, src: data, n: size); |
289 | } |
290 | |
291 | // This must remain consistent no matter the endianness |
292 | #define BOOST_UUID_DETAIL_MD5_OUT(dst, src) \ |
293 | (dst)[0] = (unsigned char)(src); \ |
294 | (dst)[1] = (unsigned char)((src) >> 8); \ |
295 | (dst)[2] = (unsigned char)((src) >> 16); \ |
296 | (dst)[3] = (unsigned char)((src) >> 24); |
297 | |
298 | // |
299 | // A big-endian issue with MD5 results was resolved |
300 | // in boost 1.71. If you generated md5 name-based uuids |
301 | // with boost 1.66 through 1.70 and stored them, then |
302 | // set the following compatibility flag to ensure that |
303 | // your hash generation remains consistent. |
304 | // |
305 | #if defined(BOOST_UUID_COMPAT_PRE_1_71_MD5) |
306 | #define BOOST_UUID_DETAIL_MD5_BYTE_OUT(dst, src) \ |
307 | BOOST_UUID_DETAIL_MD5_OUT(dst, src) |
308 | #else |
309 | // |
310 | // We're copying into a byte buffer which is actually |
311 | // backed by an unsigned int array, which later on |
312 | // is then swabbed one more time by the basic name |
313 | // generator. Therefore the logic here is reversed. |
314 | // This was done to minimize the impact to existing |
315 | // name-based hash generation. The correct fix would |
316 | // be to make this and name generation endian-correct |
317 | // but that would even break previously generated sha1 |
318 | // hashes too. |
319 | // |
320 | #if BOOST_ENDIAN_LITTLE_BYTE |
321 | #define BOOST_UUID_DETAIL_MD5_BYTE_OUT(dst, src) \ |
322 | (dst)[0] = (unsigned char)((src) >> 24); \ |
323 | (dst)[1] = (unsigned char)((src) >> 16); \ |
324 | (dst)[2] = (unsigned char)((src) >> 8); \ |
325 | (dst)[3] = (unsigned char)(src); |
326 | #else |
327 | #define BOOST_UUID_DETAIL_MD5_BYTE_OUT(dst, src) \ |
328 | (dst)[0] = (unsigned char)(src); \ |
329 | (dst)[1] = (unsigned char)((src) >> 8); \ |
330 | (dst)[2] = (unsigned char)((src) >> 16); \ |
331 | (dst)[3] = (unsigned char)((src) >> 24); |
332 | #endif |
333 | #endif // BOOST_UUID_COMPAT_PRE_1_71_MD5 |
334 | |
335 | void MD5_Final(unsigned char *result, MD5_CTX *ctx) |
336 | { |
337 | unsigned long used, available; |
338 | |
339 | used = ctx->lo & 0x3f; |
340 | |
341 | ctx->buffer[used++] = 0x80; |
342 | |
343 | available = 64 - used; |
344 | |
345 | if (available < 8) { |
346 | memset(s: &ctx->buffer[used], c: 0, n: available); |
347 | body(ctx, data: ctx->buffer, size: 64); |
348 | used = 0; |
349 | available = 64; |
350 | } |
351 | |
352 | memset(s: &ctx->buffer[used], c: 0, n: available - 8); |
353 | |
354 | ctx->lo <<= 3; |
355 | BOOST_UUID_DETAIL_MD5_OUT(&ctx->buffer[56], ctx->lo) |
356 | BOOST_UUID_DETAIL_MD5_OUT(&ctx->buffer[60], ctx->hi) |
357 | |
358 | body(ctx, data: ctx->buffer, size: 64); |
359 | |
360 | BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[0], ctx->a) |
361 | BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[4], ctx->b) |
362 | BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[8], ctx->c) |
363 | BOOST_UUID_DETAIL_MD5_BYTE_OUT(&result[12], ctx->d) |
364 | |
365 | memset(s: ctx, c: 0, n: sizeof(*ctx)); |
366 | } |
367 | |
368 | #undef BOOST_UUID_DETAIL_MD5_OUT |
369 | #undef BOOST_UUID_DETAIL_MD5_SET |
370 | #undef BOOST_UUID_DETAIL_MD5_GET |
371 | #undef BOOST_UUID_DETAIL_MD5_STEP |
372 | |
373 | MD5_CTX ctx_; |
374 | }; |
375 | |
376 | |
377 | } // detail |
378 | } // uuids |
379 | } // boost |
380 | |
381 | #endif // BOOST_UUID_MD5_HPP |
382 | |