HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
SHA2.hpp
1// Copyright Take Vos 2020.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../byte_string.hpp"
8#include "../required.hpp"
9#include "../assert.hpp"
10#include <bit>
11#include <array>
12#include <cstdint>
13#include <span>
14
15namespace tt {
16namespace detail::SHA2 {
17
18template<typename T>
19struct state {
20 T a;
21 T b;
22 T c;
23 T d;
24 T e;
25 T f;
26 T g;
27 T h;
28
29 constexpr state(T a, T b, T c, T d, T e, T f, T g, T h) noexcept :
30 a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h) {}
31
32 [[nodiscard]] constexpr T get_word(size_t i) const noexcept {
33 switch (i) {
34 case 0: return a;
35 case 1: return b;
36 case 2: return c;
37 case 3: return d;
38 case 4: return e;
39 case 5: return f;
40 case 6: return g;
41 case 7: return h;
42 default: tt_no_default();
43 }
44 }
45
46 [[nodiscard]] constexpr std::byte get_byte(size_t i) const noexcept {
47 tt_axiom(i < 8 * sizeof(T));
48 ttlet word_nr = i / sizeof(T);
49 ttlet byte_nr = i % sizeof(T);
50 ttlet word = get_word(word_nr);
51 return static_cast<std::byte>(word >> (sizeof(T) - 1 - byte_nr) * 8);
52 }
53
54 template<size_t N>
55 [[nodiscard]] bstring get_bytes() const noexcept {
56 auto r = bstring{};
57 r.reserve(N);
58
59 for (size_t i = 0; i != N; ++i) {
60 r += get_byte(i);
61 }
62 return r;
63 }
64
65 constexpr state &operator+=(state const &rhs) noexcept {
66 a += rhs.a; b += rhs.b; c += rhs.c; d += rhs.d;
67 e += rhs.e; f += rhs.f; g += rhs.g; h += rhs.h;
68 return *this;
69 }
70};
71
72template<typename T>
73struct block {
75
76 static constexpr size_t size = sizeof(v);
77
78 constexpr void set_byte(size_t i, std::byte value) noexcept {
79 ttlet word_nr = i / sizeof(T);
80 ttlet byte_nr = i % sizeof(T);
81 auto &word = v[word_nr];
82
83 ttlet valueT = static_cast<T>(static_cast<uint8_t>(value));
84 word |= valueT << (sizeof(T) - 1 - byte_nr) * 8;
85 }
86
87 constexpr block(std::byte const *ptr) noexcept :
88 v()
89 {
90 for (size_t i = 0; i != size; ++i) {
91 set_byte(i, *(ptr++));
92 }
93 }
94
95 constexpr T const &operator[](size_t i) const noexcept {
96 return v[i % 16];
97 }
98
99 constexpr T &operator[](size_t i) noexcept {
100 return v[i % 16];
101 }
102
103};
104
105}
106
107template<typename T, size_t Bits>
108class SHA2 {
109 static_assert(Bits % 8 == 0);
110 static constexpr size_t nr_rounds = (sizeof(T) == 4) ? 64 : 80;
111 static constexpr size_t pad_length_of_length = (sizeof(T) == 4) ? 8 : 16;
112
115 using byteptr = std::byte *;
116 using cbyteptr = std::byte const *;
117 state_type state;
118
120 overflow_type overflow;
121 typename overflow_type::iterator overflow_it;
122
123 size_t size;
124
125 [[nodiscard]] static constexpr T K(size_t i) noexcept {
126 constexpr std::array<uint32_t,64> K32 = {
127 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
128 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
129 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
130 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
131 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
132 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
133 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
134 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
135 };
136
137 constexpr std::array<uint64_t,80> K64 = {
138 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
139 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
140 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
141 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
142 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
143 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
144 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
145 0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
146 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
147 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
148 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
149 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
150 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
151 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
152 0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
153 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
154 };
155
156 if constexpr (std::is_same_v<T,uint32_t>) {
157 return K32[i];
158 } else {
159 return K64[i];
160 }
161 }
162
163 [[nodiscard]] static constexpr T Maj(T x, T y, T z) noexcept {
164 return (x & y) ^ (x & z) ^ (y & z);
165 }
166
167 [[nodiscard]] static constexpr T Ch(T x, T y, T z) noexcept {
168 return (x & y) ^ (~x & z);
169 }
170
171 template<int A, int B, int C>
172 [[nodiscard]] static constexpr T S(T x) noexcept {
173 return std::rotr(x, A) ^ std::rotr(x, B) ^ std::rotr(x, C);
174 }
175
176 template<int A, int B, int C>
177 [[nodiscard]] static constexpr T s(T x) noexcept {
178 return std::rotr(x, A) ^ std::rotr(x, B) ^ x >> C;
179 }
180
181 [[nodiscard]] static constexpr T S0(T x) noexcept {
182 if constexpr (std::is_same_v<T,uint32_t>) {
183 return S<2,13,22>(x);
184 } else {
185 return S<28,34,39>(x);
186 }
187 }
188
189 [[nodiscard]] static constexpr T S1(T x) {
190 if constexpr (std::is_same_v<T,uint32_t>) {
191 return S<6,11,25>(x);
192 } else {
193 return S<14,18,41>(x);
194 }
195 }
196
197 [[nodiscard]] static constexpr T s0(T x) {
198 if constexpr (std::is_same_v<T,uint32_t>) {
199 return s<7,18,3>(x);
200 } else {
201 return s<1,8,7>(x);
202 }
203 }
204
205 [[nodiscard]] static constexpr T s1(T x) {
206 if constexpr (std::is_same_v<T,uint32_t>) {
207 return s<17,19,10>(x);
208 } else {
209 return s<19,61,6>(x);
210 }
211 }
212
213 static constexpr state_type round(state_type const &tmp, T K, T W) noexcept
214 {
215 ttlet T1 =
216 tmp.h +
217 S1(tmp.e) +
218 Ch(tmp.e, tmp.f, tmp.g) +
219 K +
220 W;
221
222 ttlet T2 =
223 S0(tmp.a) +
224 Maj(tmp.a, tmp.b, tmp.c);
225
226 return {
227 T1 + T2,
228 tmp.a,
229 tmp.b,
230 tmp.c,
231 tmp.d + T1,
232 tmp.e,
233 tmp.f,
234 tmp.g
235 };
236 }
237
238 constexpr void add(block_type W) noexcept
239 {
240 auto tmp = state;
241 for (size_t i = 0; i != 16; ++i) {
242 tmp = round(tmp, K(i), W[i]);
243 }
244
245 for (size_t i = 16; i != nr_rounds; ++i) {
246 ttlet W_ = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
247
248 tmp = round(tmp, K(i), W_);
249
250 W[i] = W_;
251 }
252 state += tmp;
253 }
254
255 constexpr void add_to_overflow(cbyteptr &ptr, std::byte const *last) noexcept {
256 while (overflow_it != overflow.end() && ptr != last) {
257 *(overflow_it++) = *(ptr++);
258 }
259 }
260
261 constexpr void pad() noexcept {
262 tt_axiom(overflow_it != overflow.end());
263
264 // Add the terminating '1' bit.
265 *(overflow_it++) = std::byte{0x80};
266
267 // Complete the current block if there is not enough room
268 // for the length in this block.
269 ttlet overflow_left = overflow.end() - overflow_it;
270 if (overflow_left < pad_length_of_length) {
271 while (overflow_it != overflow.end()) {
272 *(overflow_it++) = std::byte{0x00};
273 }
274 add(block_type{overflow.data()});
275 overflow_it = overflow.begin();
276 }
277
278 // Pad until the start of length.
279 ttlet overflow_length_start = overflow.end() - pad_length_of_length;
280 while (overflow_it != overflow_length_start) {
281 *(overflow_it++) = std::byte{0x00};
282 }
283
284 size_t nr_of_bits = size * 8;
285 for (int i = pad_length_of_length - 1; i >= 0; --i) {
286 *(overflow_it++) = i < sizeof(nr_of_bits) ? static_cast<std::byte>(nr_of_bits >> i * 8) : std::byte{0x00};
287 }
288
289 auto b = block_type{overflow.data()};
290 add(b);
291 }
292
293public:
294 constexpr SHA2(T a, T b, T c, T d, T e, T f, T g, T h) noexcept :
295 state(a, b, c, d, e, f, g, h),
296 overflow(),
297 overflow_it(overflow.begin()),
298 size(0) {}
299
300 constexpr SHA2 &add(std::byte const *ptr, std::byte const *last, bool finish=true) noexcept {
301 size += last - ptr;
302
303 if (overflow_it != overflow.begin()) {
304 add_to_overflow(ptr, last);
305
306 if (overflow_it == overflow.end()) {
307 add(block_type{overflow.data()});
308 overflow_it = overflow.begin();
309
310 } else {
311 if (finish) {
312 pad();
313 }
314 return *this;
315 }
316 }
317
318 while (ptr + block_type::size <= last) {
319 add(block_type{ptr});
320 ptr += block_type::size;
321 }
322
323 add_to_overflow(ptr, last);
324
325 if (finish) {
326 pad();
327 }
328 return *this;
329 }
330
331 constexpr SHA2 &add(bstring const &str, bool finish=true) noexcept {
332 ttlet first = str.data();
333 ttlet last = first + str.size();
334 return add(first, last, finish);
335 }
336
337 constexpr SHA2 &add(bstring_view str, bool finish=true) noexcept {
338 ttlet first = str.data();
339 ttlet last = first + str.size();
340 return add(first, last, finish);
341 }
342
343 constexpr SHA2 &add(std::string const &str, bool finish=true) noexcept {
344 ttlet first = reinterpret_cast<std::byte const *>(str.data());
345 ttlet last = first + str.size();
346 return add(first, last, finish);
347 }
348
349 constexpr SHA2 &add(std::string_view str, bool finish=true) noexcept {
350 ttlet first = reinterpret_cast<std::byte const *>(str.data());
351 ttlet last = first + str.size();
352 return add(first, last, finish);
353 }
354
355 constexpr void add(std::span<std::byte const> str, bool finish=true) noexcept {
356 ttlet first = reinterpret_cast<std::byte const *>(str.data());
357 ttlet last = first + str.size();
358 add(first, last, finish);
359 }
360
361 [[nodiscard]] bstring get_bytes() const noexcept {
362 return state.template get_bytes<Bits / 8>();
363 }
364};
365
366class SHA224 final : public SHA2<uint32_t,224> {
367public:
368 SHA224() noexcept :
370 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
371 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
372 ) {}
373
374};
375
376class SHA256 final : public SHA2<uint32_t,256> {
377public:
378 SHA256() noexcept :
380 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
381 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
382 ) {}
383};
384
385class SHA384 final : public SHA2<uint64_t,384> {
386public:
387 SHA384() noexcept :
389 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939,
390 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4
391 ) {}
392};
393
394class SHA512 final : public SHA2<uint64_t,512> {
395public:
396 SHA512() noexcept :
398 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
399 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
400 ) {}
401};
402
403class SHA512_224 final : public SHA2<uint64_t,224> {
404public:
405 SHA512_224() noexcept :
407 0x8C3D37C819544DA2, 0x73E1996689DCD4D6, 0x1DFAB7AE32FF9C82, 0x679DD514582F9FCF,
408 0x0F6D2B697BD44DA8, 0x77E36F7304C48942, 0x3F9D85A86A1D36C8, 0x1112E6AD91D692A1
409 ) {}
410};
411
412class SHA512_256 final : public SHA2<uint64_t,256> {
413public:
414 SHA512_256() noexcept :
416 0x22312194FC2BF72C, 0x9F555FA3C84C64C2, 0x2393B86B6F53B151, 0x963877195940EABD,
417 0x96283EE2A88EFFE3, 0xBE5E1E2553863992, 0x2B0199FC2C85B8AA, 0x0EB72DDC81C52CA2
418 ) {}
419};
420
421}
422
Definition SHA2.hpp:19
Definition SHA2.hpp:73
Definition SHA2.hpp:108
Definition SHA2.hpp:366
Definition SHA2.hpp:376
Definition SHA2.hpp:385
Definition SHA2.hpp:394
Definition SHA2.hpp:403
Definition SHA2.hpp:412
T begin(T... args)
T data(T... args)
T end(T... args)
T reserve(T... args)
T size(T... args)