Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
MD5.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 *
4 * Copyright (C) 1990, RSA Data Security, Inc. All rights reserved
5 */
6#include "Stroika/Foundation/StroikaPreComp.h"
7
10
11#include "MD5.h"
12
13using std::byte;
14
15using namespace Stroika::Foundation;
16using namespace Stroika::Foundation::Cryptography;
17using namespace Stroika::Foundation::Cryptography::Digest;
18
19namespace {
20 /*
21 **********************************************************************
22 ** md5.h -- Header file for implementation of MD5 **
23 ** RSA Data Security, Inc. MD5 Message Digest Algorithm **
24 ** Created: 2/17/90 RLR **
25 ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
26 ** Revised (for MD5): RLR 4/27/91 **
27 ** -- G modified to have y&~z instead of y&z **
28 ** -- FF, GG, HH modified to add in last register done **
29 ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
30 ** -- distinct additive constant for each step **
31 ** -- round 4 added, working mod 7 **
32 **********************************************************************
33 */
34
35 /*
36 **********************************************************************
37 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
38 ** **
39 ** License to copy and use this software is granted provided that **
40 ** it is identified as the "RSA Data Security, Inc. MD5 Message **
41 ** Digest Algorithm" in all material mentioning or referencing this **
42 ** software or this function. **
43 ** **
44 ** License is also granted to make and use derivative works **
45 ** provided that such works are identified as "derived from the RSA **
46 ** Data Security, Inc. MD5 Message Digest Algorithm" in all **
47 ** material mentioning or referencing the derived work. **
48 ** **
49 ** RSA Data Security, Inc. makes no representations concerning **
50 ** either the merchantability of this software or the suitability **
51 ** of this software for any particular purpose. It is provided "as **
52 ** is" without express or implied warranty of any kind. **
53 ** **
54 ** These notices must be retained in any copies of any part of this **
55 ** documentation and/or software. **
56 **********************************************************************
57 */
58 /*
59 **********************************************************************
60 ** End of md5.h **
61 ******************************* (cut) ********************************
62 */
63
64 /*
65 **********************************************************************
66 ** md5.c **
67 ** RSA Data Security, Inc. MD5 Message Digest Algorithm **
68 ** Created: 2/17/90 RLR **
69 ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version **
70 **********************************************************************
71 */
72
73 /*
74 **********************************************************************
75 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
76 ** **
77 ** License to copy and use this software is granted provided that **
78 ** it is identified as the "RSA Data Security, Inc. MD5 Message **
79 ** Digest Algorithm" in all material mentioning or referencing this **
80 ** software or this function. **
81 ** **
82 ** License is also granted to make and use derivative works **
83 ** provided that such works are identified as "derived from the RSA **
84 ** Data Security, Inc. MD5 Message Digest Algorithm" in all **
85 ** material mentioning or referencing the derived work. **
86 ** **
87 ** RSA Data Security, Inc. makes no representations concerning **
88 ** either the merchantability of this software or the suitability **
89 ** of this software for any particular purpose. It is provided "as **
90 ** is" without express or implied warranty of any kind. **
91 ** **
92 ** These notices must be retained in any copies of any part of this **
93 ** documentation and/or software. **
94 **********************************************************************
95 */
96
97 /* -- include the following line if the md5.h header file is separate -- */
98 /* #include "md5.h" */
99
100 /* forward declaration */
101 // static void Transform (UINT4* buf, UINT4* in);
102
103 constexpr static unsigned char kPADDING_[64] = {
104 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
107
108/* F, G and H are basic MD5 functions: selection, majority, parity */
109#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
110#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
111#define H(x, y, z) ((x) ^ (y) ^ (z))
112#define I(x, y, z) ((y) ^ ((x) | (~z)))
113
114/* ROTATE_LEFT rotates x left n bits */
115#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
116
117/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
118/* Rotation is separate from addition to prevent recomputation */
119#define FF(a, b, c, d, x, s, ac) \
120 { \
121 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
122 (a) = ROTATE_LEFT ((a), (s)); \
123 (a) += (b); \
124 }
125#define GG(a, b, c, d, x, s, ac) \
126 { \
127 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
128 (a) = ROTATE_LEFT ((a), (s)); \
129 (a) += (b); \
130 }
131#define HH(a, b, c, d, x, s, ac) \
132 { \
133 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
134 (a) = ROTATE_LEFT ((a), (s)); \
135 (a) += (b); \
136 }
137#define II(a, b, c, d, x, s, ac) \
138 { \
139 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
140 (a) = ROTATE_LEFT ((a), (s)); \
141 (a) += (b); \
142 }
143
144}
145inline void Algorithm::DigesterAlgorithm<Algorithm::MD5>::MD5Init_ (MD5_CTX* mdContext)
146{
147 mdContext->i[0] = mdContext->i[1] = (UINT4)0;
148
149 /* Load magic initialization constants. */
150 mdContext->buf[0] = (UINT4)0x67452301;
151 mdContext->buf[1] = (UINT4)0xefcdab89;
152 mdContext->buf[2] = (UINT4)0x98badcfe;
153 mdContext->buf[3] = (UINT4)0x10325476;
154}
155
156void Algorithm::DigesterAlgorithm<Algorithm::MD5>::MD5Update_ (MD5_CTX* mdContext, const unsigned char* inBuf, unsigned int inLen)
157{
158 UINT4 in[16];
159 int mdi;
160 unsigned int i, ii;
161
162 /* compute number of bytes mod 64 */
163 mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
164
165 /* update number of bits */
166 if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
167 mdContext->i[1]++;
168 mdContext->i[0] += ((UINT4)inLen << 3);
169 mdContext->i[1] += ((UINT4)inLen >> 29);
170
171 while (inLen--) {
172 /* add new character to buffer, increment mdi */
173 mdContext->in[mdi++] = *inBuf++;
174
175 /* transform if necessary */
176 if (mdi == 0x40) {
177 for (i = 0, ii = 0; i < 16; i++, ii += 4)
178 in[i] = (((UINT4)mdContext->in[ii + 3]) << 24) | (((UINT4)mdContext->in[ii + 2]) << 16) |
179 (((UINT4)mdContext->in[ii + 1]) << 8) | ((UINT4)mdContext->in[ii]);
180 Transform (mdContext->buf, in);
181 mdi = 0;
182 }
183 }
184}
185
187{
188 UINT4 in[16];
189 int mdi;
190 unsigned int i, ii;
191 unsigned int padLen;
192
193 /* save number of bits */
194 in[14] = mdContext->i[0];
195 in[15] = mdContext->i[1];
196
197 /* compute number of bytes mod 64 */
198 mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
199
200 /* pad out to 56 mod 64 */
201 padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
202 if (padLen == 64) {
203 padLen = 0;
204 }
205 Assert (padLen < Memory::NEltsOf (kPADDING_));
206 MD5Update_ (mdContext, kPADDING_, padLen);
207
208 /* append length in bits and transform */
209 for (i = 0, ii = 0; i < 14; i++, ii += 4)
210 in[i] = (((UINT4)mdContext->in[ii + 3]) << 24) | (((UINT4)mdContext->in[ii + 2]) << 16) | (((UINT4)mdContext->in[ii + 1]) << 8) |
211 ((UINT4)mdContext->in[ii]);
212 Transform (mdContext->buf, in);
213
214 /* store buffer in digest */
215 for (i = 0, ii = 0; i < 4; i++, ii += 4) {
216 mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
217 mdContext->digest[ii + 1] = (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
218 mdContext->digest[ii + 2] = (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
219 mdContext->digest[ii + 3] = (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
220 }
221}
222
223/* Basic MD5 step. Transform buf based on in. */
225{
226 UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
227
228/* Round 1 */
229#define S11 7
230#define S12 12
231#define S13 17
232#define S14 22
233 FF (a, b, c, d, in[0], S11, 3614090360u); /* 1 */
234 FF (d, a, b, c, in[1], S12, 3905402710u); /* 2 */
235 FF (c, d, a, b, in[2], S13, 606105819u); /* 3 */
236 FF (b, c, d, a, in[3], S14, 3250441966u); /* 4 */
237 FF (a, b, c, d, in[4], S11, 4118548399u); /* 5 */
238 FF (d, a, b, c, in[5], S12, 1200080426u); /* 6 */
239 FF (c, d, a, b, in[6], S13, 2821735955u); /* 7 */
240 FF (b, c, d, a, in[7], S14, 4249261313u); /* 8 */
241 FF (a, b, c, d, in[8], S11, 1770035416u); /* 9 */
242 FF (d, a, b, c, in[9], S12, 2336552879u); /* 10 */
243 FF (c, d, a, b, in[10], S13, 4294925233u); /* 11 */
244 FF (b, c, d, a, in[11], S14, 2304563134u); /* 12 */
245 FF (a, b, c, d, in[12], S11, 1804603682u); /* 13 */
246 FF (d, a, b, c, in[13], S12, 4254626195u); /* 14 */
247 FF (c, d, a, b, in[14], S13, 2792965006u); /* 15 */
248 FF (b, c, d, a, in[15], S14, 1236535329u); /* 16 */
249
250/* Round 2 */
251#define S21 5
252#define S22 9
253#define S23 14
254#define S24 20
255 GG (a, b, c, d, in[1], S21, 4129170786u); /* 17 */
256 GG (d, a, b, c, in[6], S22, 3225465664u); /* 18 */
257 GG (c, d, a, b, in[11], S23, 643717713u); /* 19 */
258 GG (b, c, d, a, in[0], S24, 3921069994u); /* 20 */
259 GG (a, b, c, d, in[5], S21, 3593408605u); /* 21 */
260 GG (d, a, b, c, in[10], S22, 38016083u); /* 22 */
261 GG (c, d, a, b, in[15], S23, 3634488961u); /* 23 */
262 GG (b, c, d, a, in[4], S24, 3889429448u); /* 24 */
263 GG (a, b, c, d, in[9], S21, 568446438u); /* 25 */
264 GG (d, a, b, c, in[14], S22, 3275163606u); /* 26 */
265 GG (c, d, a, b, in[3], S23, 4107603335u); /* 27 */
266 GG (b, c, d, a, in[8], S24, 1163531501u); /* 28 */
267 GG (a, b, c, d, in[13], S21, 2850285829u); /* 29 */
268 GG (d, a, b, c, in[2], S22, 4243563512u); /* 30 */
269 GG (c, d, a, b, in[7], S23, 1735328473u); /* 31 */
270 GG (b, c, d, a, in[12], S24, 2368359562u); /* 32 */
271
272/* Round 3 */
273#define S31 4
274#define S32 11
275#define S33 16
276#define S34 23
277 HH (a, b, c, d, in[5], S31, 4294588738u); /* 33 */
278 HH (d, a, b, c, in[8], S32, 2272392833u); /* 34 */
279 HH (c, d, a, b, in[11], S33, 1839030562u); /* 35 */
280 HH (b, c, d, a, in[14], S34, 4259657740u); /* 36 */
281 HH (a, b, c, d, in[1], S31, 2763975236u); /* 37 */
282 HH (d, a, b, c, in[4], S32, 1272893353u); /* 38 */
283 HH (c, d, a, b, in[7], S33, 4139469664u); /* 39 */
284 HH (b, c, d, a, in[10], S34, 3200236656u); /* 40 */
285 HH (a, b, c, d, in[13], S31, 681279174u); /* 41 */
286 HH (d, a, b, c, in[0], S32, 3936430074u); /* 42 */
287 HH (c, d, a, b, in[3], S33, 3572445317u); /* 43 */
288 HH (b, c, d, a, in[6], S34, 76029189u); /* 44 */
289 HH (a, b, c, d, in[9], S31, 3654602809u); /* 45 */
290 HH (d, a, b, c, in[12], S32, 3873151461u); /* 46 */
291 HH (c, d, a, b, in[15], S33, 530742520u); /* 47 */
292 HH (b, c, d, a, in[2], S34, 3299628645u); /* 48 */
293
294/* Round 4 */
295#define S41 6
296#define S42 10
297#define S43 15
298#define S44 21
299 II (a, b, c, d, in[0], S41, 4096336452u); /* 49 */
300 II (d, a, b, c, in[7], S42, 1126891415u); /* 50 */
301 II (c, d, a, b, in[14], S43, 2878612391u); /* 51 */
302 II (b, c, d, a, in[5], S44, 4237533241u); /* 52 */
303 II (a, b, c, d, in[12], S41, 1700485571u); /* 53 */
304 II (d, a, b, c, in[3], S42, 2399980690u); /* 54 */
305 II (c, d, a, b, in[10], S43, 4293915773u); /* 55 */
306 II (b, c, d, a, in[1], S44, 2240044497u); /* 56 */
307 II (a, b, c, d, in[8], S41, 1873313359u); /* 57 */
308 II (d, a, b, c, in[15], S42, 4264355552u); /* 58 */
309 II (c, d, a, b, in[6], S43, 2734768916u); /* 59 */
310 II (b, c, d, a, in[13], S44, 1309151649u); /* 60 */
311 II (a, b, c, d, in[4], S41, 4149444226u); /* 61 */
312 II (d, a, b, c, in[11], S42, 3174756917u); /* 62 */
313 II (c, d, a, b, in[2], S43, 718787259u); /* 63 */
314 II (b, c, d, a, in[9], S44, 3951481745u); /* 64 */
315
316 buf[0] += a;
317 buf[1] += b;
318 buf[2] += c;
319 buf[3] += d;
320}
321
322/*
323 **********************************************************************
324 ** End of md5.c **
325 ******************************* (cut) ********************************
326 */
327
328/*
329 ********************************************************************************
330 **************** Algorithm::DigesterAlgorithm<Algorithm::MD5> ******************
331 ********************************************************************************
332 */
334{
335 MD5Init_ (&fCtx_);
336}
337
338void Algorithm::DigesterAlgorithm<Algorithm::MD5>::Write (const byte* start, const byte* end)
339{
340#if qStroika_Foundation_Debug_AssertionsChecked
341 Require (not fCompleted_);
342#endif
343 Require (start == end or start != nullptr);
344 Require (start == end or end != nullptr);
345 MD5Update_ (&fCtx_, reinterpret_cast<const unsigned char*> (start), static_cast<unsigned int> (end - start));
346}
347
349{
350#if qStroika_Foundation_Debug_AssertionsChecked
351 Require (not fCompleted_);
352 fCompleted_ = true;
353#endif
354 MD5Final_ (&fCtx_);
355 ReturnType result{};
356 (void)::memcpy (Traversal::Iterator2Pointer (result.begin ()), fCtx_.digest, 16);
357 return result;
358}
constexpr auto Transform(const optional< T > &o, F &&f)
Definition Optional.h:241
DigesterAlgorithm is specialized for each algorithm; generally don't use this directly,...
Definition Algorithm.h:55