29 static_assert(Bits % 8 == 0);
30 constexpr static std::size_t nr_rounds = (
sizeof(T) == 4) ? 64 : 80;
31 constexpr static std::size_t pad_length_of_length = (
sizeof(T) == 4) ? 8 : 16;
43 constexpr state_type(T a, T b, T c, T d, T e, T f, T g, T h) noexcept : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h) {}
45 [[nodiscard]]
constexpr T get_word(
std::size_t i)
const noexcept
69 [[nodiscard]]
constexpr std::byte get_byte(
std::size_t i)
const noexcept
71 hi_axiom(i < 8 *
sizeof(T));
72 auto const word_nr = i /
sizeof(T);
73 auto const byte_nr = i %
sizeof(T);
74 auto const word = get_word(word_nr);
75 return static_cast<std::byte
>(word >> (
sizeof(T) - 1 - byte_nr) * 8);
78 template<std::
size_t N>
79 [[nodiscard]] bstring get_bytes()
const noexcept
90 constexpr state_type& operator+=(state_type
const& rhs)
noexcept
109 constexpr void set_byte(
std::size_t i, std::byte value)
noexcept
111 auto const word_nr = i /
sizeof(T);
112 auto const byte_nr = i %
sizeof(T);
113 auto& word = v[word_nr];
115 auto const valueT =
static_cast<T
>(
static_cast<uint8_t
>(value));
116 word |= valueT << (
sizeof(T) - 1 - byte_nr) * 8;
119 constexpr block_type(std::byte
const *ptr) noexcept : v()
122 set_byte(i, *(ptr++));
126 constexpr T
const& operator[](
std::size_t i)
const noexcept
137 using byteptr = std::byte *;
138 using cbyteptr = std::byte
const *;
142 overflow_type overflow;
143 typename overflow_type::iterator overflow_it;
147 [[nodiscard]]
constexpr static T K(
std::size_t i)
noexcept
150 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
151 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
152 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
153 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
154 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
155 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
156 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
157 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
160 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
161 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
162 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
163 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
164 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
165 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
166 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
167 0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
168 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
169 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
170 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
171 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
172 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
173 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
174 0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
175 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817};
177 if constexpr (std::is_same_v<T, uint32_t>) {
184 [[nodiscard]]
constexpr static T Maj(T x, T y, T z)
noexcept
186 return (x & y) ^ (x & z) ^ (y & z);
189 [[nodiscard]]
constexpr static T Ch(T x, T y, T z)
noexcept
191 return (x & y) ^ (~x & z);
194 template<
int A,
int B,
int C>
195 [[nodiscard]]
constexpr static T S(T x)
noexcept
197 return std::rotr(x, A) ^ std::rotr(x, B) ^ std::rotr(x, C);
200 template<
int A,
int B,
int C>
201 [[nodiscard]]
constexpr static T s(T x)
noexcept
203 return std::rotr(x, A) ^ std::rotr(x, B) ^ x >> C;
206 [[nodiscard]]
constexpr static T S0(T x)
noexcept
208 if constexpr (std::is_same_v<T, uint32_t>) {
209 return S<2, 13, 22>(x);
211 return S<28, 34, 39>(x);
215 [[nodiscard]]
constexpr static T S1(T x)
217 if constexpr (std::is_same_v<T, uint32_t>) {
218 return S<6, 11, 25>(x);
220 return S<14, 18, 41>(x);
224 [[nodiscard]]
constexpr static T s0(T x)
226 if constexpr (std::is_same_v<T, uint32_t>) {
227 return s<7, 18, 3>(x);
229 return s<1, 8, 7>(x);
233 [[nodiscard]]
constexpr static T s1(T x)
235 if constexpr (std::is_same_v<T, uint32_t>) {
236 return s<17, 19, 10>(x);
238 return s<19, 61, 6>(x);
242 constexpr static state_type
round(state_type
const& tmp, T K, T W)
noexcept
244 auto const T1 = tmp.h + S1(tmp.e) + Ch(tmp.e, tmp.f, tmp.g) + K + W;
246 auto const T2 = S0(tmp.a) + Maj(tmp.a, tmp.b, tmp.c);
248 return {T1 + T2, tmp.a, tmp.b, tmp.c, tmp.d + T1, tmp.e, tmp.f, tmp.g};
251 constexpr void add(block_type W)
noexcept
255 tmp =
round(tmp, K(i), W[i]);
259 auto const W_ = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
261 tmp =
round(tmp, K(i), W_);
268 constexpr void add_to_overflow(cbyteptr& ptr, std::byte
const *last)
noexcept
270 hi_axiom_not_null(ptr);
271 hi_axiom_not_null(last);
273 while (overflow_it != overflow.end() && ptr != last) {
274 *(overflow_it++) = *(ptr++);
278 constexpr void pad()
noexcept
280 hi_axiom(overflow_it != overflow.end());
283 *(overflow_it++) = std::byte{0x80};
287 auto const overflow_left = overflow.end() - overflow_it;
288 if (overflow_left < pad_length_of_length) {
289 while (overflow_it != overflow.end()) {
290 *(overflow_it++) = std::byte{0x00};
292 add(block_type{overflow.data()});
293 overflow_it = overflow.begin();
297 auto const overflow_length_start = overflow.end() - pad_length_of_length;
298 while (overflow_it != overflow_length_start) {
299 *(overflow_it++) = std::byte{0x00};
303 for (
int i = pad_length_of_length - 1; i >= 0; --i) {
304 *(overflow_it++) = i <
sizeof(nr_of_bits) ?
static_cast<std::byte
>(nr_of_bits >> i * 8) : std::byte{0x00};
307 auto b = block_type{overflow.data()};
312 constexpr SHA2(T a, T b, T c, T d, T e, T f, T g, T h) noexcept :
313 state(a, b, c, d, e, f, g, h), overflow(), overflow_it(overflow.begin()), size(0)
317 constexpr SHA2& add(std::byte
const *ptr, std::byte
const *last,
bool finish =
true)
noexcept
321 if (overflow_it != overflow.begin()) {
322 add_to_overflow(ptr, last);
324 if (overflow_it == overflow.end()) {
325 add(block_type{overflow.data()});
326 overflow_it = overflow.begin();
336 while (ptr + block_type::size <= last) {
337 add(block_type{ptr});
338 ptr += block_type::size;
341 add_to_overflow(ptr, last);
349 constexpr SHA2& add(bstring
const& str,
bool finish =
true)
noexcept
351 auto const first = str.data();
352 auto const last = first + str.size();
353 return add(first, last, finish);
356 constexpr SHA2& add(bstring_view str,
bool finish =
true)
noexcept
358 auto const first = str.data();
359 auto const last = first + str.size();
360 return add(first, last, finish);
363 constexpr SHA2& add(
std::string const& str,
bool finish =
true)
noexcept
365 auto const first =
reinterpret_cast<std::byte
const *
>(str.data());
366 auto const last = first + str.size();
367 return add(first, last, finish);
370 constexpr SHA2& add(std::string_view str,
bool finish =
true)
noexcept
372 auto const first =
reinterpret_cast<std::byte
const *
>(str.data());
373 auto const last = first + str.size();
374 return add(first, last, finish);
377 constexpr void add(std::span<std::byte const> str,
bool finish =
true)
noexcept
379 auto const first =
reinterpret_cast<std::byte
const *
>(str.data());
380 auto const last = first + str.size();
381 add(first, last, finish);
384 [[nodiscard]] bstring get_bytes()
const noexcept
386 return state.template get_bytes<Bits / 8>();