digestpp 1.0
C++11 header-only message digest library
Loading...
Searching...
No Matches
sha2_provider.hpp
Go to the documentation of this file.
1/*
2This code is written by kerukuro and released into public domain.
3*/
4
5#ifndef DIGESTPP_PROVIDERS_SHA2_HPP
6#define DIGESTPP_PROVIDERS_SHA2_HPP
7
12#include <array>
13
14namespace digestpp
15{
16
17namespace detail
18{
19
20namespace sha2_functions
21{
22 template<typename T>
23 static inline T Ch(T x, T y, T z)
24 {
25 return (x & y) ^ (~x & z);
26 }
27
28 template<typename T>
29 static inline T Maj(T x, T y, T z)
30 {
31 return (x & y) ^ (x & z) ^ (y & z);
32 }
33
34 template<typename T>
35 inline T getK(int t);
36
37 template<>
38 inline uint32_t getK(int t)
39 {
41 }
42
43 template<>
44 inline uint64_t getK(int t)
45 {
47 }
48
49 static inline uint64_t sum0(uint64_t x)
50 {
51 return rotate_right(x, 28) ^ rotate_right(x, 34) ^ rotate_right(x, 39);
52 }
53
54 static inline uint64_t sum1(uint64_t x)
55 {
56 return rotate_right(x, 14) ^ rotate_right(x, 18) ^ rotate_right(x, 41);
57 }
58
59 static inline uint64_t sigma0(uint64_t x)
60 {
61 return rotate_right(x, 1) ^ rotate_right(x, 8) ^ (x >> 7);
62 }
63
64 static inline uint64_t sigma1(uint64_t x)
65 {
66 return rotate_right(x, 19) ^ rotate_right(x, 61) ^ (x >> 6);
67 }
68
69 static inline uint32_t sum0(uint32_t x)
70 {
71 return rotate_right(x, 2) ^ rotate_right(x, 13) ^ rotate_right(x, 22);
72 }
73
74 static inline uint32_t sum1(uint32_t x)
75 {
76 return rotate_right(x, 6) ^ rotate_right(x, 11) ^ rotate_right(x, 25);
77 }
78
79 static inline uint32_t sigma0(uint32_t x)
80 {
81 return rotate_right(x, 7) ^ rotate_right(x, 18) ^ (x >> 3);
82 }
83
84 static inline uint32_t sigma1(uint32_t x)
85 {
86 return rotate_right(x, 17) ^ rotate_right(x, 19) ^ (x >> 10);
87 }
88}
89
90// SHA-224, SHA-256, SHA-384, SHA-512/t algorithm
91// SHA-512/t supports any output size up to 512 bits; in this case O must be 0 and output size provided to the constructor
92template<typename T, size_t O = 0>
94{
95public:
96 static const bool is_xof = false;
97
98 template<typename t=T, size_t o=O, typename std::enable_if<o != 0>::type* = nullptr>
100 : hs(O)
101 {
102 static_assert((sizeof(t) == 4 && (o == 224 || o == 256))
103 || (sizeof(t) == 8 && o > 0 && o <= 512 && o % 8 == 0));
104 }
105
106 template<typename t=T, size_t o=O, typename std::enable_if<sizeof(t) == 8 && !o>::type* = nullptr>
107 sha2_provider(size_t hashsize = N)
108 : hs(hashsize)
109 {
110 detail::validate_hash_size(hashsize, N);
111 }
112
114 {
115 clear();
116 }
117
118 inline void init()
119 {
120 pos = 0;
121 total = 0;
122
123 // precalculated initial values for most common output sizes
124 switch(hs)
125 {
126 case 224:
127 H[0] = 0x8C3D37C819544DA2ull;
128 H[1] = 0x73E1996689DCD4D6ull;
129 H[2] = 0x1DFAB7AE32FF9C82ull;
130 H[3] = 0x679DD514582F9FCFull;
131 H[4] = 0x0F6D2B697BD44DA8ull;
132 H[5] = 0x77E36F7304C48942ull;
133 H[6] = 0x3F9D85A86A1D36C8ull;
134 H[7] = 0x1112E6AD91D692A1ull;
135 return;
136 case 256:
137 H[0] = 0x22312194FC2BF72Cull;
138 H[1] = 0x9F555FA3C84C64C2ull;
139 H[2] = 0x2393B86B6F53B151ull;
140 H[3] = 0x963877195940EABDull;
141 H[4] = 0x96283EE2A88EFFE3ull;
142 H[5] = 0xBE5E1E2553863992ull;
143 H[6] = 0x2B0199FC2C85B8AAull;
144 H[7] = 0x0EB72DDC81C52CA2ull;
145 return;
146 case 384:
147 H[0] = 0xcbbb9d5dc1059ed8ull;
148 H[1] = 0x629a292a367cd507ull;
149 H[2] = 0x9159015a3070dd17ull;
150 H[3] = 0x152fecd8f70e5939ull;
151 H[4] = 0x67332667ffc00b31ull;
152 H[5] = 0x8eb44a8768581511ull;
153 H[6] = 0xdb0c2e0d64f98fa7ull;
154 H[7] = 0x47b5481dbefa4fa4ull;
155 return;
156 default:
157 H[0] = 0x6a09e667f3bcc908ull;
158 H[1] = 0xbb67ae8584caa73bull;
159 H[2] = 0x3c6ef372fe94f82bull;
160 H[3] = 0xa54ff53a5f1d36f1ull;
161 H[4] = 0x510e527fade682d1ull;
162 H[5] = 0x9b05688c2b3e6c1full;
163 H[6] = 0x1f83d9abfb41bd6bull;
164 H[7] = 0x5be0cd19137e2179ull;
165 }
166 if (hs == 512)
167 return;
168
169 // calculate initial values for SHA-512/t with a different output size
170 for (int i = 0; i < 8; i++)
171 H[i] ^= 0xa5a5a5a5a5a5a5a5ull;
172 std::string tmp = "SHA-512/" + std::to_string(hs);
173
174 update(reinterpret_cast<unsigned char*>(&tmp[0]), tmp.length());
175 unsigned char buf[512 / 8];
176 final(buf);
177 for (int i = 0; i < 8; i++)
178 H[i] = byteswap(H[i]);
179 pos = 0;
180 total = 0;
181 }
182
183 inline void update(const unsigned char* data, size_t len)
184 {
185 detail::absorb_bytes(data, len, N / 4, N / 4, m.data(), pos, total,
186 [this](const unsigned char* data, size_t len) { transform(data, len); });
187 }
188
189 inline void final(unsigned char* hash)
190 {
191 total += pos * 8;
192 m[pos++] = 0x80;
193 if (pos > N / 4 - sizeof(T) * 2) {
194 if (pos != N / 4)
195 memset(&m[pos], 0, N / 4 - pos);
196 transform(m.data(), 1);
197 pos = 0;
198 }
199 memset(&m[pos], 0, N / 4 - pos);
200 uint64_t mlen = byteswap(total);
201 memcpy(&m[N / 4 - 8], &mlen, 64 / 8);
202 transform(m.data(), 1);
203 for (int i = 0; i < 8; i++)
204 H[i] = byteswap(H[i]);
205 memcpy(hash, &H[0], hs/8);
206 }
207
208 inline void clear()
209 {
210 zero_memory(H);
211 zero_memory(m);
212 }
213
214 inline size_t hash_size() const { return hs; }
215
216private:
217 inline void transform(const unsigned char* data, size_t num_blks)
218 {
219 for (size_t blk = 0; blk < num_blks; blk++)
220 {
221 T M[16];
222 for (int i = 0; i < 16; i++)
223 M[i] = byteswap(reinterpret_cast<const T*>(data)[blk * 16 + i]);
224
225 const int rounds = N == 512 ? 80 : 64;
226 T W[rounds];
227 for (int t = 0; t <= 15; t++)
228 W[t] = M[t];
229 for (int t = 16; t < rounds; t++)
230 W[t] = sha2_functions::sigma1(W[t - 2]) + W[t - 7] + sha2_functions::sigma0(W[t - 15]) + W[t - 16];
231
232 T a = H[0];
233 T b = H[1];
234 T c = H[2];
235 T d = H[3];
236 T e = H[4];
237 T f = H[5];
238 T g = H[6];
239 T h = H[7];
240
241 for (int t = 0; t < rounds; t++)
242 {
243 T T1 = h + sha2_functions::sum1(e) + sha2_functions::Ch(e, f, g) + sha2_functions::getK<T>(t) + W[t];
244 T T2 = sha2_functions::sum0(a) + sha2_functions::Maj(a, b, c);
245 h = g;
246 g = f;
247 f = e;
248 e = d + T1;
249 d = c;
250 c = b;
251 b = a;
252 a = T1 + T2;
253
254 }
255 H[0] += a;
256 H[1] += b;
257 H[2] += c;
258 H[3] += d;
259 H[4] += e;
260 H[5] += f;
261 H[6] += g;
262 H[7] += h;
263 }
264
265 }
266
267 constexpr static size_t N = sizeof(T) == 8 ? 512 : 256;
268 std::array<T, 8> H;
269 std::array<unsigned char, N / 4> m;
270 size_t pos;
271 uint64_t total;
272 size_t hs;
273};
274
275template<>
277{
278 pos = 0;
279 total = 0;
280 H[0] = 0xc1059ed8;
281 H[1] = 0x367cd507;
282 H[2] = 0x3070dd17;
283 H[3] = 0xf70e5939;
284 H[4] = 0xffc00b31;
285 H[5] = 0x68581511;
286 H[6] = 0x64f98fa7;
287 H[7] = 0xbefa4fa4;
288}
289
290template<>
292{
293 pos = 0;
294 total = 0;
295 H[0] = 0x6a09e667;
296 H[1] = 0xbb67ae85;
297 H[2] = 0x3c6ef372;
298 H[3] = 0xa54ff53a;
299 H[4] = 0x510e527f;
300 H[5] = 0x9b05688c;
301 H[6] = 0x1f83d9ab;
302 H[7] = 0x5be0cd19;
303}
304
305} // namespace detail
306
307} // namespace digestpp
308
309#endif
Definition sha2_provider.hpp:94
void clear()
Definition sha2_provider.hpp:208
void update(const unsigned char *data, size_t len)
Definition sha2_provider.hpp:183
sha2_provider(size_t hashsize=N)
Definition sha2_provider.hpp:107
void init()
Definition sha2_provider.hpp:118
size_t hash_size() const
Definition sha2_provider.hpp:214
sha2_provider()
Definition sha2_provider.hpp:99
~sha2_provider()
Definition sha2_provider.hpp:113
static T Ch(T x, T y, T z)
Definition sha2_provider.hpp:23
static T Maj(T x, T y, T z)
Definition sha2_provider.hpp:29
static uint64_t sum0(uint64_t x)
Definition sha2_provider.hpp:49
static uint64_t sigma1(uint64_t x)
Definition sha2_provider.hpp:64
static uint64_t sum1(uint64_t x)
Definition sha2_provider.hpp:54
static uint64_t sigma0(uint64_t x)
Definition sha2_provider.hpp:59
uint16_t byteswap(uint16_t val)
Definition functions.hpp:16
uint32_t rotate_right(uint32_t x, unsigned n)
Definition functions.hpp:61
void validate_hash_size(size_t hs, std::initializer_list< size_t > set)
Definition validate_hash_size.hpp:14
void zero_memory(void *v, size_t n)
Definition functions.hpp:85
void absorb_bytes(const unsigned char *data, size_t len, size_t bs, size_t bschk, unsigned char *m, size_t &pos, T &total, TF transform)
Definition absorb_data.hpp:16
digestpp namespace
Definition ascon.hpp:14
Definition traits.hpp:17
Definition sha2_constants.hpp:46
Definition sha2_constants.hpp:16