Skip to content

Commit fa72b53

Browse files
committed
Convert all usage to the class
1 parent d1ffa8e commit fa72b53

File tree

2 files changed

+67
-170
lines changed

2 files changed

+67
-170
lines changed

include/boost/crypt/hash/md5.hpp

Lines changed: 66 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -51,58 +51,9 @@ static constexpr boost::crypt::array<boost::crypt::uint32_t, 64> K {
5151
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
5252
};
5353

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
10455

105-
class md5
56+
class md5_hasher
10657
{
10758
private:
10859
boost::crypt::uint32_t a0_ {0x67452301};
@@ -124,6 +75,8 @@ class md5
12475
template <typename ForwardIter>
12576
constexpr auto md5_copy_data(ForwardIter data, boost::crypt::size_t offset, boost::crypt::size_t size) noexcept;
12677

78+
constexpr auto md5_body() noexcept -> void;
79+
12780
public:
12881
constexpr auto init() noexcept -> void;
12982

@@ -138,7 +91,7 @@ class md5
13891
constexpr auto get_digest(DigestType digest, boost::crypt::size_t digest_size) noexcept;
13992
};
14093

141-
constexpr auto md5::init() noexcept -> void
94+
constexpr auto md5_hasher::init() noexcept -> void
14295
{
14396
a0_ = 0x67452301U;
14497
b0_ = 0xefcdab89U;
@@ -152,7 +105,7 @@ constexpr auto md5::init() noexcept -> void
152105
blocks_.fill(0U);
153106
}
154107

155-
constexpr auto md5::md5_convert_buffer_to_blocks() noexcept
108+
constexpr auto md5_hasher::md5_convert_buffer_to_blocks() noexcept
156109
{
157110
boost::crypt::size_t buffer_index {};
158111
for (auto& block : blocks_)
@@ -169,17 +122,17 @@ constexpr auto md5::md5_convert_buffer_to_blocks() noexcept
169122
}
170123

171124
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
173126
{
174127
for (boost::crypt::size_t i {}; i < size; ++i)
175128
{
176129
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)));
178131
}
179132
}
180133

181134
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
183136
{
184137
const auto input_bits {size << 3U}; // Convert size to bits
185138
const auto old_low {low_};
@@ -203,16 +156,16 @@ constexpr auto md5::md5_update(ForwardIter data, boost::crypt::size_t size) noex
203156

204157
md5_copy_data(data, used, available);
205158
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);
208161
size -= available;
209162
}
210163

211164
while (size >= 64U)
212165
{
213166
md5_copy_data(data, 0U, 64U);
214167
md5_convert_buffer_to_blocks();
215-
md5_body(blocks_, a0_, b0_, c0_, d0_);
168+
md5_body();
216169
data += 64U;
217170
size -= 64U;
218171
}
@@ -224,7 +177,7 @@ constexpr auto md5::md5_update(ForwardIter data, boost::crypt::size_t size) noex
224177
}
225178

226179
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
228181
{
229182
auto used {(low_ >> 3U) & 0x3F}; // Number of bytes used in buffer
230183
buffer_[used++] = 0x80;
@@ -234,7 +187,7 @@ constexpr auto md5::get_digest(DigestType digest, boost::crypt::size_t digest_si
234187
{
235188
fill_array(buffer_.begin() + used, buffer_.end(), static_cast<boost::crypt::uint8_t>(0));
236189
md5_convert_buffer_to_blocks();
237-
md5_body(blocks_, a0_, b0_, c0_, d0_);
190+
md5_body();
238191
used = 0;
239192
buffer_.fill(0);
240193
}
@@ -256,140 +209,79 @@ constexpr auto md5::get_digest(DigestType digest, boost::crypt::size_t digest_si
256209
buffer_[63] = static_cast<boost::crypt::uint8_t>((total_bits >> 56) & 0xFF);
257210

258211
md5_convert_buffer_to_blocks();
259-
md5_body(blocks_, a0_, b0_, c0_, d0_);
212+
md5_body();
260213

261214
if (digest_size >= 4)
262215
{
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_);
267220
}
268221
}
269222

270223
template <typename ByteType>
271-
constexpr auto md5::process_byte(ByteType byte) noexcept
224+
constexpr auto md5_hasher::process_byte(ByteType byte) noexcept
272225
BOOST_CRYPT_REQUIRES_CONVERSION(ByteType, boost::crypt::uint8_t)
273226
{
274227
md5_update(&byte, 1UL);
275228
}
276229

277230
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
279232
{
280233
md5_update(buffer, byte_count);
281234
}
282235

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
285238
{
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_};
302243

303-
while (first != last)
244+
for (boost::crypt::uint32_t i {}; i < 64U; ++i)
304245
{
305-
boost::crypt::size_t current_block = 0;
246+
boost::crypt::uint32_t F {};
247+
boost::crypt::uint32_t g {};
306248

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)
309255
{
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;
322263
}
323264
else
324265
{
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;
382268
}
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]);
383277
}
384278

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;
389283
}
390284

391-
} // namespace detail
392-
393285
template <typename ResultType = boost::crypt::array<boost::crypt::uint32_t, 4>, typename T>
394286
ResultType md5(T begin, T end)
395287
{
@@ -402,7 +294,12 @@ ResultType md5(T begin, T end)
402294
return ResultType{0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e};
403295
}
404296

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;
406303
}
407304

408305
template <typename ResultType = boost::crypt::array<boost::crypt::uint32_t, 4>>
@@ -414,20 +311,20 @@ ResultType md5(const char* str)
414311
}
415312

416313
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);
418315
}
419316

420317
template <typename ResultType = boost::crypt::array<boost::crypt::uint32_t, 4>>
421318
ResultType md5(const std::string& str)
422319
{
423-
return md5(str.begin(), str.end());
320+
return md5<ResultType>(str.begin(), str.end());
424321
}
425322

426323
#ifdef BOOST_CRYPT_HAS_STRING_VIEW
427324
template <typename ResultType = boost::crypt::array<boost::crypt::uint32_t, 4>>
428325
ResultType md5(const std::string_view& str)
429326
{
430-
return md5(str.begin(), str.end());
327+
return md5<ResultType>(str.begin(), str.end());
431328
}
432329
#endif
433330

test/test_md5.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void bad_input()
8585

8686
void test_class()
8787
{
88-
boost::crypt::detail::md5 hasher;
88+
boost::crypt::md5_hasher hasher;
8989

9090
for (const auto& test_value : test_values)
9191
{

0 commit comments

Comments
 (0)