digestpp 1.0
C++11 header-only message digest library
Loading...
Searching...
No Matches
shake_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_SHAKE_HPP
6#define DIGESTPP_PROVIDERS_SHAKE_HPP
7
10#include "sha3_provider.hpp"
11#include <array>
12
13namespace digestpp
14{
15
16namespace detail
17{
18
19namespace shake_functions
20{
21 static inline size_t left_encode(size_t num, unsigned char* buf)
22 {
23 // first, calculate length
24 unsigned char n = 1;
25 size_t tmp = num;
26 while (tmp >>= 8)
27 ++n;
28 buf[0] = n;
29 size_t result = n + 1;
30 size_t i = 0;
31 while (n)
32 buf[n--] = static_cast<unsigned char>(num >> (8*i++));
33 return result;
34 }
35
36 static inline size_t right_encode(size_t num, unsigned char* buf, bool k12)
37 {
38 // first, calculate length
39 unsigned char n = k12 ? num ? 1 : 0 : 1;
40 size_t tmp = num;
41 while (tmp >>= 8)
42 ++n;
43 buf[n] = n;
44 size_t result = n + 1;
45 size_t i = 0;
46 while (n--)
47 buf[n] = static_cast<unsigned char>(num >> (8*i++));
48 return result;
49 }
50
51} // namespace shake_functions
52
53
54template<size_t B, int R>
56{
57public:
58 static const bool is_xof = true;
59
61 {
62 static_assert(B == 128 || B == 256, "SHAKE only supports 128 and 256 bits");
63 }
64
66 {
67 clear();
68 }
69
70 inline void set_function_name(const std::string& function_name)
71 {
72 N = function_name;
73 }
74
75 inline void set_customization(const std::string& customization)
76 {
77 S = customization;
78 }
79
80 inline void init()
81 {
82 zero_memory(A);
83 pos = 0;
84 total = 0;
85 squeezing = false;
86 suffix = 0;
87
88 if (!N.empty() || !S.empty())
89 {
90 unsigned char buf[1024];
91 size_t r = rate / 8;
92 size_t len = shake_functions::left_encode(r, buf);
93 size_t total = len;
94 update(buf, len);
95 len = shake_functions::left_encode(N.length() * 8, buf);
96 total += len;
97 update(buf, len);
98 if (!N.empty())
99 update(reinterpret_cast<const unsigned char*>(N.data()), N.length());
100 len = shake_functions::left_encode(S.length() * 8, buf);
101 update(buf, len);
102 total += len;
103 if (!S.empty())
104 update(reinterpret_cast<const unsigned char*>(S.data()), S.length());
105 total += S.length() + N.length();
106
107 len = r - (total % r);
108 memset(buf, 0, len);
109 update(buf, len);
110 }
111 }
112
113 inline void update(const unsigned char* data, size_t len)
114 {
115 detail::absorb_bytes(data, len, rate / 8, rate / 8, m.data(), pos, total,
116 [this](const unsigned char* data, size_t len) { sha3_functions::transform<R>(data, len, A.data(), rate); });
117 }
118
119 inline void set_suffix(unsigned char s)
120 {
121 suffix = s;
122 }
123
124 inline void squeeze(unsigned char* hash, size_t hs)
125 {
126 size_t r = rate / 8;
127 size_t processed = 0;
128 if (!squeezing)
129 {
130 m[pos++] = suffix ? suffix : N.empty() && S.empty() ? 0x1F : 0x04;
131 if (r != pos)
132 memset(&m[pos], 0, r - pos);
133 m[r - 1] |= 0x80;
134 sha3_functions::transform<R>(m.data(), 1, A.data(), rate);
135 squeezing = true;
136 }
137 else if (pos < r)
138 {
139 size_t to_copy = std::min(hs, r - pos);
140 memcpy(hash, reinterpret_cast<unsigned char*>(A.data()) + pos, to_copy);
141 processed += to_copy;
142 pos += to_copy;
143 }
144 else if (pos == r)
145 {
147 }
148 while (processed < hs)
149 {
150 if (processed)
152 pos = std::min(hs - processed, r);
153 memcpy(hash + processed, A.data(), pos);
154 processed += pos;
155 }
156 }
157
158 inline void clear()
159 {
160 zero_memory(A);
161 zero_memory(m);
162 zero_memory(N);
163 zero_memory(S);
164 N.clear();
165 S.clear();
166 }
167
168private:
169 std::array<uint64_t, 25> A;
170 std::array<unsigned char, 168> m;
171 std::string N;
172 std::string S;
173 const size_t rate = B == 128 ? 1344 : 1088;
174 size_t pos;
175 size_t total;
176 bool squeezing;
177 unsigned char suffix;
178};
179
180} // namespace detail
181
182} // namespace digestpp
183
184#endif // DIGESTPP_PROVIDERS_SHAKE_HPP
Definition shake_provider.hpp:56
void update(const unsigned char *data, size_t len)
Definition shake_provider.hpp:113
void squeeze(unsigned char *hash, size_t hs)
Definition shake_provider.hpp:124
void clear()
Definition shake_provider.hpp:158
shake_provider()
Definition shake_provider.hpp:60
~shake_provider()
Definition shake_provider.hpp:65
void set_function_name(const std::string &function_name)
Definition shake_provider.hpp:70
void set_suffix(unsigned char s)
Definition shake_provider.hpp:119
void set_customization(const std::string &customization)
Definition shake_provider.hpp:75
void init()
Definition shake_provider.hpp:80
Main class template implementing the public API for hashing.
Definition hasher.hpp:38
static void transform(uint64_t *A)
Definition sha3_provider.hpp:23
static size_t left_encode(size_t num, unsigned char *buf)
Definition shake_provider.hpp:21
static size_t right_encode(size_t num, unsigned char *buf, bool k12)
Definition shake_provider.hpp:36
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