10 static constexpr std::size_t digest_size = 16;
14 update(bytes.begin(), bytes.end());
17 template<
typename InputIt,
typename Sentinel, enable_if_t<
18 is_input_iterator<InputIt>::value &&
19 !is_random_access_iterator<InputIt>::value &&
20 is_sentinel_for<Sentinel, InputIt>::value &&
21 is_byte_like<iter_value_t<InputIt>>::value
23 auto update(InputIt first, Sentinel last) ->
void {
25 for (
auto it = first; it != last;) {
27 for (; it != last && n <
sizeof(temp); ++it, ++n) {
28 temp[n] =
static_cast<byte>(*it);
34 template<
typename RandomAccessIt,
typename Sentinel, enable_if_t<
35 is_random_access_iterator<RandomAccessIt>::value &&
36 is_sentinel_for<Sentinel, RandomAccessIt>::value &&
37 is_byte_like<iter_value_t<RandomAccessIt>>::value
39 auto update(RandomAccessIt first, Sentinel last) ->
void {
40 std::size_t bytes_count = last - first;
41 total_size_ += bytes_count;
44 if (buffer_size_ > 0) {
45 std::size_t to_copy = std::min(bytes_count, 64 - buffer_size_);
46 std::copy_n(first, to_copy, buffer_.data() + buffer_size_);
47 buffer_size_ += to_copy;
49 if (buffer_size_ == 64) {
50 process_(w_table_(buffer_.data()));
55 for (; i + 63 < bytes_count; i += 64) {
56 (process_)((w_table_)(std::next(first, i)));
59 if (i < bytes_count) {
60 std::copy_n(std::next(first, i), bytes_count - i, buffer_.data());
61 buffer_size_ = bytes_count - i;
66 auto do_digest()
noexcept -> std::array<std::uint32_t, 4> {
68 auto buffer_size = buffer_size_;
69 auto total_size = total_size_;
72 std::size_t padding_size = (buffer_size < 56) ? (56 - buffer_size) : (120 - buffer_size);
73 update({padding, padding_size});
74 std::uint64_t bits = total_size * 8;
75 for (std::size_t i = 0; i < 8; ++i) padding[i] = (bits >> (8 * i)) & 0xff;
77 return {a_, b_, c_, d_};
81 static auto unit_to_bytes(std::uint32_t unit)
noexcept -> std::array<byte, 4> {
82 byte* byte_ptr =
reinterpret_cast<byte*
>(&unit);
83 if HASHLIB_CXX17_CONSTEXPR (is_little_endian()) {
84 return {byte_ptr[0], byte_ptr[1], byte_ptr[2], byte_ptr[3]};
87 return {byte_ptr[3], byte_ptr[2], byte_ptr[1], byte_ptr[0]};
92 auto process_(
const std::array<std::uint32_t, 16>& w)
noexcept ->
void {
93 static constexpr std::uint32_t K[64]{
94 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
95 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
96 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
97 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
98 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
99 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
100 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
101 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
102 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
103 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
104 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
105 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
106 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
107 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
108 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
109 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
111 static constexpr std::uint32_t S[16]{7, 12, 17, 22, 5, 9, 14, 20, 4, 11, 16, 23, 6, 10, 15, 21};
113 std::uint32_t a = a_, b = b_, c = c_, d = d_;
114 for (std::size_t i = 0; i < 64; ++i) {
115 std::uint32_t F, g, cnt;
117 F = (b & c) | ((~b) & d);
122 F = (d & b) | ((~d) & c);
123 g = (5 * i + 1) % 16;
128 g = (3 * i + 5) % 16;
136 F = F + a + K[i] + w[g];
140 b = b + ((F << cnt) | (F >> (32 - cnt)));
148 template<
typename RandomAccessIt>
149 static auto w_table_(RandomAccessIt it)
noexcept -> std::array<std::uint32_t, 16> {
150 static_assert(is_random_access_iterator<RandomAccessIt>::value,
"unexpected");
151 std::array<std::uint32_t, 16> w;
152 for (std::size_t i = 0; i < 16; ++i) {
153 w[i] = (std::uint32_t(it[i * 4])) |
154 (std::uint32_t(it[i * 4 + 1]) << 8) |
155 (std::uint32_t(it[i * 4 + 2]) << 16) |
156 (std::uint32_t(it[i * 4 + 3]) << 24);
162 std::array<byte, 64> buffer_{};
163 std::size_t buffer_size_ = 0;
164 std::uint64_t total_size_ = 0;
165 std::uint32_t a_ = 0x67452301, b_ = 0xefcdab89, c_ = 0x98badcfe, d_ = 0x10325476;