@@ -51,58 +51,9 @@ static constexpr boost::crypt::array<boost::crypt::uint32_t, 64> K {
51
51
0xf7537e82 , 0xbd3af235 , 0x2ad7d2bb , 0xeb86d391
52
52
};
53
53
54
- // TODO(mborland): Replace the loop with the known statements
55
- auto md5_body (const boost::crypt::array<boost::crypt::uint32_t , 16 >& blocks,
56
- boost::crypt::uint32_t & a, boost::crypt::uint32_t & b,
57
- boost::crypt::uint32_t & c, boost::crypt::uint32_t & d) noexcept
58
- {
59
- boost::crypt::uint32_t A {a};
60
- boost::crypt::uint32_t B {b};
61
- boost::crypt::uint32_t C {c};
62
- boost::crypt::uint32_t D {d};
63
-
64
- for (boost::crypt::uint32_t i {}; i < 64U ; ++i)
65
- {
66
- boost::crypt::uint32_t F {};
67
- boost::crypt::uint32_t g {};
68
-
69
- if (i <= 15U )
70
- {
71
- F = (B & C) | ((~B) & D);
72
- g = i;
73
- }
74
- else if (i <= 31U )
75
- {
76
- F = (D & B) | ((~D) & C);
77
- g = (5U * i + 1U ) % 16U ;
78
- }
79
- else if (i <= 47U )
80
- {
81
- F = B ^ C ^ D;
82
- g = (3U * i + 5U ) % 16U ;
83
- }
84
- else
85
- {
86
- F = C ^ (B | (~D));
87
- g = (7U * i) % 16U ;
88
- }
89
-
90
- BOOST_CRYPT_ASSERT (i <= 63U );
91
-
92
- F = F + A + K[i] + blocks[g];
93
- A = D;
94
- D = C;
95
- C = B;
96
- B = B + rotl (F, S[i]);
97
- }
98
-
99
- a += A;
100
- b += B;
101
- c += C;
102
- d += D;
103
- }
54
+ } // namespace detail
104
55
105
- class md5
56
+ class md5_hasher
106
57
{
107
58
private:
108
59
boost::crypt::uint32_t a0_ {0x67452301 };
@@ -124,6 +75,8 @@ class md5
124
75
template <typename ForwardIter>
125
76
constexpr auto md5_copy_data (ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept ;
126
77
78
+ constexpr auto md5_body () noexcept -> void;
79
+
127
80
public:
128
81
constexpr auto init () noexcept -> void;
129
82
@@ -138,7 +91,7 @@ class md5
138
91
constexpr auto get_digest (DigestType digest, boost::crypt::size_t digest_size) noexcept ;
139
92
};
140
93
141
- constexpr auto md5 ::init () noexcept -> void
94
+ constexpr auto md5_hasher ::init () noexcept -> void
142
95
{
143
96
a0_ = 0x67452301U ;
144
97
b0_ = 0xefcdab89U ;
@@ -152,7 +105,7 @@ constexpr auto md5::init() noexcept -> void
152
105
blocks_.fill (0U );
153
106
}
154
107
155
- constexpr auto md5 ::md5_convert_buffer_to_blocks () noexcept
108
+ constexpr auto md5_hasher ::md5_convert_buffer_to_blocks () noexcept
156
109
{
157
110
boost::crypt::size_t buffer_index {};
158
111
for (auto & block : blocks_)
@@ -169,17 +122,17 @@ constexpr auto md5::md5_convert_buffer_to_blocks() noexcept
169
122
}
170
123
171
124
template <typename ForwardIter>
172
- constexpr auto md5 ::md5_copy_data (ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept
125
+ constexpr auto md5_hasher ::md5_copy_data (ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept
173
126
{
174
127
for (boost::crypt::size_t i {}; i < size; ++i)
175
128
{
176
129
BOOST_CRYPT_ASSERT (offset + i < buffer_.size ());
177
- buffer_[offset + i] = static_cast <boost::crypt::uint8_t >(*(data + i ));
130
+ buffer_[offset + i] = static_cast <boost::crypt::uint8_t >(*(data + static_cast <boost::crypt:: ptrdiff_t >(i) ));
178
131
}
179
132
}
180
133
181
134
template <typename ForwardIter>
182
- constexpr auto md5 ::md5_update (ForwardIter data, boost::crypt::size_t size) noexcept
135
+ constexpr auto md5_hasher ::md5_update (ForwardIter data, boost::crypt::size_t size) noexcept
183
136
{
184
137
const auto input_bits {size << 3U }; // Convert size to bits
185
138
const auto old_low {low_};
@@ -203,16 +156,16 @@ constexpr auto md5::md5_update(ForwardIter data, boost::crypt::size_t size) noex
203
156
204
157
md5_copy_data (data, used, available);
205
158
md5_convert_buffer_to_blocks ();
206
- md5_body (blocks_, a0_, b0_, c0_, d0_ );
207
- data += available;
159
+ md5_body ();
160
+ data += static_cast <boost::crypt:: ptrdiff_t >( available) ;
208
161
size -= available;
209
162
}
210
163
211
164
while (size >= 64U )
212
165
{
213
166
md5_copy_data (data, 0U , 64U );
214
167
md5_convert_buffer_to_blocks ();
215
- md5_body (blocks_, a0_, b0_, c0_, d0_ );
168
+ md5_body ();
216
169
data += 64U ;
217
170
size -= 64U ;
218
171
}
@@ -224,7 +177,7 @@ constexpr auto md5::md5_update(ForwardIter data, boost::crypt::size_t size) noex
224
177
}
225
178
226
179
template <typename DigestType>
227
- constexpr auto md5 ::get_digest (DigestType digest, boost::crypt::size_t digest_size) noexcept
180
+ constexpr auto md5_hasher ::get_digest (DigestType digest, boost::crypt::size_t digest_size) noexcept
228
181
{
229
182
auto used {(low_ >> 3U ) & 0x3F }; // Number of bytes used in buffer
230
183
buffer_[used++] = 0x80 ;
@@ -234,7 +187,7 @@ constexpr auto md5::get_digest(DigestType digest, boost::crypt::size_t digest_si
234
187
{
235
188
fill_array (buffer_.begin () + used, buffer_.end (), static_cast <boost::crypt::uint8_t >(0 ));
236
189
md5_convert_buffer_to_blocks ();
237
- md5_body (blocks_, a0_, b0_, c0_, d0_ );
190
+ md5_body ();
238
191
used = 0 ;
239
192
buffer_.fill (0 );
240
193
}
@@ -256,140 +209,79 @@ constexpr auto md5::get_digest(DigestType digest, boost::crypt::size_t digest_si
256
209
buffer_[63 ] = static_cast <boost::crypt::uint8_t >((total_bits >> 56 ) & 0xFF );
257
210
258
211
md5_convert_buffer_to_blocks ();
259
- md5_body (blocks_, a0_, b0_, c0_, d0_ );
212
+ md5_body ();
260
213
261
214
if (digest_size >= 4 )
262
215
{
263
- digest[0 ] = swap_endian (a0_);
264
- digest[1 ] = swap_endian (b0_);
265
- digest[2 ] = swap_endian (c0_);
266
- digest[3 ] = swap_endian (d0_);
216
+ digest[0 ] = detail:: swap_endian (a0_);
217
+ digest[1 ] = detail:: swap_endian (b0_);
218
+ digest[2 ] = detail:: swap_endian (c0_);
219
+ digest[3 ] = detail:: swap_endian (d0_);
267
220
}
268
221
}
269
222
270
223
template <typename ByteType>
271
- constexpr auto md5 ::process_byte (ByteType byte) noexcept
224
+ constexpr auto md5_hasher ::process_byte (ByteType byte) noexcept
272
225
BOOST_CRYPT_REQUIRES_CONVERSION(ByteType, boost::crypt::uint8_t )
273
226
{
274
227
md5_update (&byte, 1UL );
275
228
}
276
229
277
230
template <typename ForwardIter>
278
- constexpr auto md5 ::process_bytes (ForwardIter buffer, boost::crypt::size_t byte_count) noexcept
231
+ constexpr auto md5_hasher ::process_bytes (ForwardIter buffer, boost::crypt::size_t byte_count) noexcept
279
232
{
280
233
md5_update (buffer, byte_count);
281
234
}
282
235
283
- template < typename ResultType, typename ForwardIterator>
284
- auto md5_impl (ForwardIterator first, ForwardIterator last) -> ResultType
236
+ // TODO(mborland): Replace the loop with the known statements
237
+ constexpr auto md5_hasher::md5_body () noexcept -> void
285
238
{
286
- // Initial MD5 buffer values
287
- boost::crypt::uint32_t a0 {0x67452301 };
288
- boost::crypt::uint32_t b0 {0xefcdab89 };
289
- boost::crypt::uint32_t c0 {0x98badcfe };
290
- boost::crypt::uint32_t d0 {0x10325476 };
291
-
292
- boost::crypt::array<boost::crypt::uint32_t , 16 > blocks {};
293
-
294
- // Store the original 'first' to compute the total message length
295
- const auto total_message_length {static_cast <boost::crypt::uint64_t >(last - first) * 8UL };
296
-
297
- // Handles the empty case with known values
298
- if (first == last)
299
- {
300
- return ResultType{0xd41d8cd9 , 0x8f00b204 , 0xe9800998 , 0xecf8427e };
301
- }
239
+ boost::crypt::uint32_t A {a0_};
240
+ boost::crypt::uint32_t B {b0_};
241
+ boost::crypt::uint32_t C {c0_};
242
+ boost::crypt::uint32_t D {d0_};
302
243
303
- while (first != last )
244
+ for (boost::crypt:: uint32_t i {}; i < 64U ; ++i )
304
245
{
305
- boost::crypt::size_t current_block = 0 ;
246
+ boost::crypt::uint32_t F {};
247
+ boost::crypt::uint32_t g {};
306
248
307
- // Process as many full 64-byte blocks as possible
308
- if (last - first >= 64 )
249
+ if (i <= 15U )
250
+ {
251
+ F = (B & C) | ((~B) & D);
252
+ g = i;
253
+ }
254
+ else if (i <= 31U )
309
255
{
310
- for (auto & block : blocks)
311
- {
312
- block = static_cast <boost::crypt::uint32_t >(
313
- static_cast <boost::crypt::uint32_t >(*first) +
314
- (static_cast <boost::crypt::uint32_t >(*(first + 1U )) << 8U ) +
315
- (static_cast <boost::crypt::uint32_t >(*(first + 2U )) << 16U ) +
316
- (static_cast <boost::crypt::uint32_t >(*(first + 3U )) << 24U )
317
- );
318
-
319
- first += 4U ;
320
- }
321
- md5_body (blocks, a0, b0, c0, d0);
256
+ F = (D & B) | ((~D) & C);
257
+ g = (5U * i + 1U ) % 16U ;
258
+ }
259
+ else if (i <= 47U )
260
+ {
261
+ F = B ^ C ^ D;
262
+ g = (3U * i + 5U ) % 16U ;
322
263
}
323
264
else
324
265
{
325
- // Process remaining bytes
326
- // Initialize blocks to zero
327
- blocks.fill (0 );
328
-
329
- // Process complete 4-byte chunks
330
- while (last - first >= 4 )
331
- {
332
- blocks[current_block] = static_cast <boost::crypt::uint32_t >(
333
- static_cast <boost::crypt::uint32_t >(*first) +
334
- (static_cast <boost::crypt::uint32_t >(*(first + 1U )) << 8U ) +
335
- (static_cast <boost::crypt::uint32_t >(*(first + 2U )) << 16U ) +
336
- (static_cast <boost::crypt::uint32_t >(*(first + 3U )) << 24U )
337
- );
338
-
339
- first += 4U ;
340
- ++current_block;
341
- }
342
-
343
- // Process remaining bytes (less than 4)
344
- blocks[current_block] = 0 ;
345
- auto byte_offset = 0U ;
346
- while (first != last)
347
- {
348
- blocks[current_block] |= static_cast <boost::crypt::uint32_t >(*first) << (8U * byte_offset);
349
- ++first;
350
- ++byte_offset;
351
- }
352
-
353
- // Append the '1' bit (0x80) after the last byte
354
- blocks[current_block] |= static_cast <boost::crypt::uint32_t >(0x80 ) << (8U * byte_offset);
355
- ++current_block;
356
-
357
- // Check if there is enough space to append the length
358
- if (current_block > 14U )
359
- {
360
- // Not enough space, process this block and start a new one
361
- md5_body (blocks, a0, b0, c0, d0);
362
- blocks.fill (0 );
363
- current_block = 0 ;
364
- }
365
-
366
- // Pad with zeros until block[14]
367
- while (current_block < 14U )
368
- {
369
- blocks[current_block] = 0 ;
370
- ++current_block;
371
- }
372
-
373
- // Append the 64-bit length in bits in little-endian format
374
- blocks[14 ] = static_cast <boost::crypt::uint32_t >(total_message_length & 0xFFFFFFFF );
375
- blocks[15 ] = static_cast <boost::crypt::uint32_t >((total_message_length >> 32 ) & 0xFFFFFFFF );
376
-
377
- // Process the final block
378
- md5_body (blocks, a0, b0, c0, d0);
379
-
380
- // Break out of the loop as we've processed all data
381
- break ;
266
+ F = C ^ (B | (~D));
267
+ g = (7U * i) % 16U ;
382
268
}
269
+
270
+ BOOST_CRYPT_ASSERT (i <= 63U );
271
+
272
+ F = F + A + detail::K[i] + blocks_[g];
273
+ A = D;
274
+ D = C;
275
+ C = B;
276
+ B = B + detail::rotl (F, detail::S[i]);
383
277
}
384
278
385
- return ResultType { swap_endian (a0),
386
- swap_endian (b0),
387
- swap_endian (c0),
388
- swap_endian (d0)} ;
279
+ a0_ += A;
280
+ b0_ += B;
281
+ c0_ += C;
282
+ d0_ += D ;
389
283
}
390
284
391
- } // namespace detail
392
-
393
285
template <typename ResultType = boost::crypt::array<boost::crypt::uint32_t , 4 >, typename T>
394
286
ResultType md5 (T begin, T end)
395
287
{
@@ -402,7 +294,12 @@ ResultType md5(T begin, T end)
402
294
return ResultType{0xd41d8cd9 , 0x8f00b204 , 0xe9800998 , 0xecf8427e };
403
295
}
404
296
405
- return detail::md5_impl<ResultType>(begin, end);
297
+ boost::crypt::md5_hasher hasher;
298
+ hasher.process_bytes (begin, static_cast <boost::crypt::size_t >(end - begin));
299
+ ResultType result;
300
+ hasher.get_digest (result.begin (), result.size ());
301
+
302
+ return result;
406
303
}
407
304
408
305
template <typename ResultType = boost::crypt::array<boost::crypt::uint32_t , 4 >>
@@ -414,20 +311,20 @@ ResultType md5(const char* str)
414
311
}
415
312
416
313
const auto message_len {std::strlen (str)};
417
- return detail::md5_impl <ResultType>(str, str + message_len);
314
+ return md5 <ResultType>(str, str + message_len);
418
315
}
419
316
420
317
template <typename ResultType = boost::crypt::array<boost::crypt::uint32_t , 4 >>
421
318
ResultType md5 (const std::string& str)
422
319
{
423
- return md5 (str.begin (), str.end ());
320
+ return md5<ResultType> (str.begin (), str.end ());
424
321
}
425
322
426
323
#ifdef BOOST_CRYPT_HAS_STRING_VIEW
427
324
template <typename ResultType = boost::crypt::array<boost::crypt::uint32_t , 4 >>
428
325
ResultType md5 (const std::string_view& str)
429
326
{
430
- return md5 (str.begin (), str.end ());
327
+ return md5<ResultType> (str.begin (), str.end ());
431
328
}
432
329
#endif
433
330
0 commit comments