digestpp 1.0
C++11 header-only message digest library
Loading...
Searching...
No Matches
sha3_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_SHA3_HPP
6#define DIGESTPP_PROVIDERS_SHA3_HPP
7
12#include <array>
13
14namespace digestpp
15{
16
17namespace detail
18{
19
20namespace sha3_functions
21{
22 template<int R>
23 static inline void transform(uint64_t* A)
24 {
25 for (int round = 24 - R; round < 24; round++)
26 {
27 uint64_t C[5], D[5];
28 C[0] = A[0 * 5 + 0] ^ A[1 * 5 + 0] ^ A[2 * 5 + 0] ^ A[3 * 5 + 0] ^ A[4 * 5 + 0];
29 C[1] = A[0 * 5 + 1] ^ A[1 * 5 + 1] ^ A[2 * 5 + 1] ^ A[3 * 5 + 1] ^ A[4 * 5 + 1];
30 C[2] = A[0 * 5 + 2] ^ A[1 * 5 + 2] ^ A[2 * 5 + 2] ^ A[3 * 5 + 2] ^ A[4 * 5 + 2];
31 C[3] = A[0 * 5 + 3] ^ A[1 * 5 + 3] ^ A[2 * 5 + 3] ^ A[3 * 5 + 3] ^ A[4 * 5 + 3];
32 C[4] = A[0 * 5 + 4] ^ A[1 * 5 + 4] ^ A[2 * 5 + 4] ^ A[3 * 5 + 4] ^ A[4 * 5 + 4];
33
34 D[0] = C[4] ^ rotate_left(C[1], 1);
35 D[1] = C[0] ^ rotate_left(C[2], 1);
36 D[2] = C[1] ^ rotate_left(C[3], 1);
37 D[3] = C[2] ^ rotate_left(C[4], 1);
38 D[4] = C[3] ^ rotate_left(C[0], 1);
39
40 uint64_t B00 = A[0 * 5 + 0] ^ D[0];
41 uint64_t B10 = rotate_left(A[0 * 5 + 1] ^ D[1], 1);
42 uint64_t B20 = rotate_left(A[0 * 5 + 2] ^ D[2], 62);
43 uint64_t B5 = rotate_left(A[0 * 5 + 3] ^ D[3], 28);
44 uint64_t B15 = rotate_left(A[0 * 5 + 4] ^ D[4], 27);
45
46 uint64_t B16 = rotate_left(A[1 * 5 + 0] ^ D[0], 36);
47 uint64_t B1 = rotate_left(A[1 * 5 + 1] ^ D[1], 44);
48 uint64_t B11 = rotate_left(A[1 * 5 + 2] ^ D[2], 6);
49 uint64_t B21 = rotate_left(A[1 * 5 + 3] ^ D[3], 55);
50 uint64_t B6 = rotate_left(A[1 * 5 + 4] ^ D[4], 20);
51
52 uint64_t B7 = rotate_left(A[2 * 5 + 0] ^ D[0], 3);
53 uint64_t B17 = rotate_left(A[2 * 5 + 1] ^ D[1], 10);
54 uint64_t B2 = rotate_left(A[2 * 5 + 2] ^ D[2], 43);
55 uint64_t B12 = rotate_left(A[2 * 5 + 3] ^ D[3], 25);
56 uint64_t B22 = rotate_left(A[2 * 5 + 4] ^ D[4], 39);
57
58 uint64_t B23 = rotate_left(A[3 * 5 + 0] ^ D[0], 41);
59 uint64_t B8 = rotate_left(A[3 * 5 + 1] ^ D[1], 45);
60 uint64_t B18 = rotate_left(A[3 * 5 + 2] ^ D[2], 15);
61 uint64_t B3 = rotate_left(A[3 * 5 + 3] ^ D[3], 21);
62 uint64_t B13 = rotate_left(A[3 * 5 + 4] ^ D[4], 8);
63
64 uint64_t B14 = rotate_left(A[4 * 5 + 0] ^ D[0], 18);
65 uint64_t B24 = rotate_left(A[4 * 5 + 1] ^ D[1], 2);
66 uint64_t B9 = rotate_left(A[4 * 5 + 2] ^ D[2], 61);
67 uint64_t B19 = rotate_left(A[4 * 5 + 3] ^ D[3], 56);
68 uint64_t B4 = rotate_left(A[4 * 5 + 4] ^ D[4], 14);
69
70 A[0 * 5 + 0] = B00 ^ ((~B1) & B2);
71 A[0 * 5 + 1] = B1 ^ ((~B2) & B3);
72 A[0 * 5 + 2] = B2 ^ ((~B3) & B4);
73 A[0 * 5 + 3] = B3 ^ ((~B4) & B00);
74 A[0 * 5 + 4] = B4 ^ ((~B00) & B1);
75
76 A[1 * 5 + 0] = B5 ^ ((~B6) & B7);
77 A[1 * 5 + 1] = B6 ^ ((~B7) & B8);
78 A[1 * 5 + 2] = B7 ^ ((~B8) & B9);
79 A[1 * 5 + 3] = B8 ^ ((~B9) & B5);
80 A[1 * 5 + 4] = B9 ^ ((~B5) & B6);
81
82 A[2 * 5 + 0] = B10 ^ ((~B11) & B12);
83 A[2 * 5 + 1] = B11 ^ ((~B12) & B13);
84 A[2 * 5 + 2] = B12 ^ ((~B13) & B14);
85 A[2 * 5 + 3] = B13 ^ ((~B14) & B10);
86 A[2 * 5 + 4] = B14 ^ ((~B10) & B11);
87
88 A[3 * 5 + 0] = B15 ^ ((~B16) & B17);
89 A[3 * 5 + 1] = B16 ^ ((~B17) & B18);
90 A[3 * 5 + 2] = B17 ^ ((~B18) & B19);
91 A[3 * 5 + 3] = B18 ^ ((~B19) & B15);
92 A[3 * 5 + 4] = B19 ^ ((~B15) & B16);
93
94 A[4 * 5 + 0] = B20 ^ ((~B21) & B22);
95 A[4 * 5 + 1] = B21 ^ ((~B22) & B23);
96 A[4 * 5 + 2] = B22 ^ ((~B23) & B24);
97 A[4 * 5 + 3] = B23 ^ ((~B24) & B20);
98 A[4 * 5 + 4] = B24 ^ ((~B20) & B21);
99
100 A[0] ^= sha3_constants<void>::RC[round];
101 }
102 }
103
104 template<int R>
105 static inline void transform(const unsigned char* data, uint64_t num_blks, uint64_t* A, size_t rate)
106 {
107 size_t r = rate / 8;
108 size_t r64 = rate / 64;
109 for (uint64_t blk = 0; blk < num_blks; blk++)
110 {
111 for (size_t i = 0; i < r64; i++)
112 A[i] ^= reinterpret_cast<const uint64_t*>(data+blk*r)[i];
113
114 transform<R>(A);
115 }
116 }
117
118} // namespace sha3_functions
119
120
121template<size_t HS = 0>
123{
124public:
125 static const bool is_xof = false;
126
127 template<size_t hss=HS, typename std::enable_if<hss == 0>::type* = nullptr>
128 sha3_provider(size_t hashsize)
129 : hs(hashsize)
130 {
131 validate_hash_size(hashsize, {224, 256, 384, 512});
132 rate = 1600U - hs * 2;
133 }
134
135 template<size_t hss=HS, typename std::enable_if<hss != 0>::type* = nullptr>
137 : hs(hss)
138 {
139 static_assert(hss == 224 || hss == 256 || hss == 384 || hss == 512);
140 rate = 1600U - hss * 2;
141 }
142
144 {
145 clear();
146 }
147
148 inline void init()
149 {
150 zero_memory(A);
151 pos = 0;
152 total = 0;
153 }
154
155 inline void update(const unsigned char* data, size_t len)
156 {
157 detail::absorb_bytes(data, len, rate / 8, rate / 8, m.data(), pos, total,
158 [this](const unsigned char* data, size_t len) { sha3_functions::transform<24>(data, len, A.data(), rate); });
159 }
160
161 inline void final(unsigned char* hash)
162 {
163 size_t r = rate / 8;
164 m[pos++] = 0x06;
165 if (r != pos)
166 memset(&m[pos], 0, r - pos);
167 m[r - 1] |= 0x80;
168 sha3_functions::transform<24>(m.data(), 1, A.data(), rate);
169 memcpy(hash, A.data(), hash_size() / 8);
170 }
171
172 inline size_t hash_size() const
173 {
174 return hs;
175 }
176
177 inline void clear()
178 {
179 zero_memory(A);
180 zero_memory(m);
181 }
182
183private:
184 std::array<uint64_t, 25> A;
185 std::array<unsigned char, 144> m;
186 size_t pos;
187 size_t hs;
188 size_t rate;
189 uint64_t total;
190};
191
192} // namespace detail
193
194} // namespace digestpp
195
196#endif // DIGESTPP_PROVIDERS_SHA3_HPP
Definition sha3_provider.hpp:123
void init()
Definition sha3_provider.hpp:148
void clear()
Definition sha3_provider.hpp:177
sha3_provider(size_t hashsize)
Definition sha3_provider.hpp:128
void update(const unsigned char *data, size_t len)
Definition sha3_provider.hpp:155
size_t hash_size() const
Definition sha3_provider.hpp:172
sha3_provider()
Definition sha3_provider.hpp:136
~sha3_provider()
Definition sha3_provider.hpp:143
static void transform(uint64_t *A)
Definition sha3_provider.hpp:23
void validate_hash_size(size_t hs, std::initializer_list< size_t > set)
Definition validate_hash_size.hpp:14
uint32_t rotate_left(uint32_t x, unsigned n)
Definition functions.hpp:67
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 sha3_constants.hpp:16