digestpp 1.0
C++11 header-only message digest library
Loading...
Searching...
No Matches
lsh_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_LSH_HPP
6#define DIGESTPP_PROVIDERS_LSH_HPP
7
12#include <array>
13
14namespace digestpp
15{
16
17namespace detail
18{
19
20namespace lsh_functions
21{
22
23 template<typename T>
24 inline T step_constant(size_t scidx, size_t idx);
25
26 template<>
27 inline uint32_t step_constant(size_t scidx, size_t idx)
28 {
29 return lsh_constants<void>::SC256[scidx][idx];
30 }
31
32 template<>
33 inline uint64_t step_constant(size_t scidx, size_t idx)
34 {
35 return lsh_constants<void>::SC512[scidx][idx];
36 }
37
38 template<typename T>
39 inline int gamma(size_t idx, T dummy = T());
40
41 template<>
42 inline int gamma(size_t idx, uint32_t)
43 {
44 return lsh_constants<void>::G256[idx];
45 }
46
47 template<>
48 inline int gamma(size_t idx, uint64_t)
49 {
50 return lsh_constants<void>::G512[idx];
51 }
52
53 template<typename T>
54 inline int alphabeta(size_t idx, T dummy = T());
55
56 template<>
57 inline int alphabeta(size_t idx, uint32_t)
58 {
60 }
61
62 template<>
63 inline int alphabeta(size_t idx, uint64_t)
64 {
66 }
67}
68
69template<typename T, size_t HS = 0>
71{
72public:
73 static const bool is_xof = false;
74
75 template<size_t hss=HS, typename std::enable_if<hss == 0>::type* = nullptr>
76 lsh_provider(size_t hashsize)
77 : hs(hashsize)
78 {
79 static_assert(sizeof(T) == 4 || sizeof(T) == 8, "LSH only supports 4 and 8 bits word size");
80 validate_hash_size(hashsize, N);
81 }
82
83 template<size_t hss=HS, typename std::enable_if<hss != 0>::type* = nullptr>
85 : hs(hss)
86 {
87 static_assert(sizeof(T) == 4 || sizeof(T) == 8, "LSH only supports 4 and 8 bits word size");
88 static_assert(hss <= N && hss > 0 && hss % 8 == 0);
89 }
90
92 {
93 clear();
94 }
95
96 inline void init()
97 {
98 pos = 0;
99 total = 0;
100
101 cv[0] = N / 8;
102 cv[1] = hs;
103 memset(&cv[2], 0, sizeof(T) * 14);
104 unsigned char msg[N / 2];
105 memset(msg, 0, sizeof(msg));
106 transform(msg, 1);
107
108 memset(&t[0], 0, sizeof(T) * 16);
109 memset(&msgexp, 0, sizeof(msgexp));
110 }
111
112 inline void update(const unsigned char* data, size_t len)
113 {
114 detail::absorb_bytes(data, len, block_bytes(), block_bytes(), m.data(), pos, total,
115 [this](const unsigned char* data, size_t len) { transform(data, len); });
116 }
117
118 inline void final(unsigned char* hash)
119 {
120 m[pos++] = 0x80;
121 total += pos * 8;
122 if (pos != block_bytes())
123 memset(&m[pos], 0, block_bytes() - pos);
124 transform(m.data(), 1);
125
126 T h[N / 2];
127 for (size_t i = 0; i < 8; ++i)
128 h[i] = cv[i] ^ cv[i + 8];
129 memcpy(hash, h, hash_size() / 8);
130 }
131
132 inline void clear()
133 {
134 zero_memory(cv);
135 zero_memory(t);
136 zero_memory(m);
137 zero_memory(msgexp);
138 }
139
140 inline size_t hash_size() const { return hs; }
141
142private:
143 inline size_t block_bytes() const { return N / 2; }
144
145 inline void msgexpand(const unsigned char* mp)
146 {
147 memcpy(msgexp.data(), mp, block_bytes());
148 for (size_t i = 2; i < NS + 1; i++)
149 {
150 msgexp[i][0] = msgexp[i - 1][0] + msgexp[i - 2][3];
151 msgexp[i][1] = msgexp[i - 1][1] + msgexp[i - 2][2];
152 msgexp[i][2] = msgexp[i - 1][2] + msgexp[i - 2][0];
153 msgexp[i][3] = msgexp[i - 1][3] + msgexp[i - 2][1];
154 msgexp[i][4] = msgexp[i - 1][4] + msgexp[i - 2][7];
155 msgexp[i][5] = msgexp[i - 1][5] + msgexp[i - 2][4];
156 msgexp[i][6] = msgexp[i - 1][6] + msgexp[i - 2][5];
157 msgexp[i][7] = msgexp[i - 1][7] + msgexp[i - 2][6];
158 msgexp[i][8] = msgexp[i - 1][8] + msgexp[i - 2][11];
159 msgexp[i][9] = msgexp[i - 1][9] + msgexp[i - 2][10];
160 msgexp[i][10] = msgexp[i - 1][10] + msgexp[i - 2][8];
161 msgexp[i][11] = msgexp[i - 1][11] + msgexp[i - 2][9];
162 msgexp[i][12] = msgexp[i - 1][12] + msgexp[i - 2][15];
163 msgexp[i][13] = msgexp[i - 1][13] + msgexp[i - 2][12];
164 msgexp[i][14] = msgexp[i - 1][14] + msgexp[i - 2][13];
165 msgexp[i][15] = msgexp[i - 1][15] + msgexp[i - 2][14];
166 }
167 }
168
169 inline void addmix(size_t l, size_t i, T sc, int alpha, int beta, int gamma)
170 {
171 T x = cv[l] ^ msgexp[i][l];
172 T y = cv[l + 8] ^ msgexp[i][l + 8];
173 x = rotate_left(x + y, alpha) ^ sc;
174 y = rotate_left(x + y, beta);
175 t[l] = x + y;
176 t[l + 8] = rotate_left(y, gamma);
177 }
178
179 inline void step(size_t i, int alpha, int beta)
180 {
181 addmix(0, i, lsh_functions::step_constant<T>(i, 0), alpha, beta, lsh_functions::gamma<T>(0));
182 addmix(1, i, lsh_functions::step_constant<T>(i, 1), alpha, beta, lsh_functions::gamma<T>(1));
183 addmix(2, i, lsh_functions::step_constant<T>(i, 2), alpha, beta, lsh_functions::gamma<T>(2));
184 addmix(3, i, lsh_functions::step_constant<T>(i, 3), alpha, beta, lsh_functions::gamma<T>(3));
185 addmix(4, i, lsh_functions::step_constant<T>(i, 4), alpha, beta, lsh_functions::gamma<T>(4));
186 addmix(5, i, lsh_functions::step_constant<T>(i, 5), alpha, beta, lsh_functions::gamma<T>(5));
187 addmix(6, i, lsh_functions::step_constant<T>(i, 6), alpha, beta, lsh_functions::gamma<T>(6));
188 addmix(7, i, lsh_functions::step_constant<T>(i, 7), alpha, beta, lsh_functions::gamma<T>(7));
189 cv[0] = t[6];
190 cv[1] = t[4];
191 cv[2] = t[5];
192 cv[3] = t[7];
193 cv[4] = t[12];
194 cv[5] = t[15];
195 cv[6] = t[14];
196 cv[7] = t[13];
197 cv[8] = t[2];
198 cv[9] = t[0];
199 cv[10] = t[1];
200 cv[11] = t[3];
201 cv[12] = t[8];
202 cv[13] = t[11];
203 cv[14] = t[10];
204 cv[15] = t[9];
205 }
206
207 inline void transform(const unsigned char* mp, size_t num_blks)
208 {
209 for (size_t blk = 0; blk < num_blks; blk++)
210 {
211 msgexpand(mp + block_bytes() * blk);
212 for (size_t i = 0; i < NS; i += 2)
213 {
216 }
217 for (size_t i = 0; i < 16; ++i)
218 cv[i] ^= msgexp[NS][i];
219 }
220 }
221
222 constexpr static size_t N = sizeof(T) == 4 ? 256 : 512;
223 constexpr static size_t NS = sizeof(T) == 4 ? 26 : 28;
224
225 std::array<T, 16> cv;
226 std::array<T, 16> t;
227 std::array<std::array<T, 16>, NS + 1> msgexp;
228 std::array<unsigned char, N / 2> m;
229 size_t hs;
230 size_t pos;
231 uint64_t total;
232};
233
234} // namespace detail
235
236} // namespace digestpp
237
238#endif
Definition lsh_provider.hpp:71
lsh_provider(size_t hashsize)
Definition lsh_provider.hpp:76
size_t hash_size() const
Definition lsh_provider.hpp:140
~lsh_provider()
Definition lsh_provider.hpp:91
lsh_provider()
Definition lsh_provider.hpp:84
void init()
Definition lsh_provider.hpp:96
void update(const unsigned char *data, size_t len)
Definition lsh_provider.hpp:112
void clear()
Definition lsh_provider.hpp:132
int gamma(size_t idx, T dummy=T())
int alphabeta(size_t idx, T dummy=T())
T step_constant(size_t scidx, size_t idx)
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 lsh_constants.hpp:16