digestpp 1.0
C++11 header-only message digest library
Loading...
Searching...
No Matches
jh_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_JH_HPP
6#define DIGESTPP_PROVIDERS_JH_HPP
7
12#include <array>
13
14namespace digestpp
15{
16
17namespace detail
18{
19
20namespace jh_functions
21{
22 static inline void bitswap(uint64_t& x, uint64_t mask, int shift)
23 {
24 x = ((x & mask) << shift) | ((x & ~mask) >> shift);
25 }
26
27 static inline void bitswap(std::array<uint64_t, 16>& H, uint64_t mask, int shift)
28 {
29 bitswap(H[2], mask, shift);
30 bitswap(H[3], mask, shift);
31 bitswap(H[6], mask, shift);
32 bitswap(H[7], mask, shift);
33 bitswap(H[10], mask, shift);
34 bitswap(H[11], mask, shift);
35 bitswap(H[14], mask, shift);
36 bitswap(H[15], mask, shift);
37 }
38
39 static inline void Sbitsli(uint64_t& x0a, uint64_t& x0b, uint64_t& x1a, uint64_t& x1b, uint64_t& x2a, uint64_t& x2b,
40 uint64_t& x3a, uint64_t& x3b, uint64_t ca, uint64_t cb)
41 {
42 x3a = ~x3a;
43 x3b = ~x3b;
44 x0a ^= (ca & ~x2a);
45 x0b ^= (cb & ~x2b);
46 uint64_t ta = ca ^ (x0a & x1a);
47 uint64_t tb = cb ^ (x0b & x1b);
48 x0a ^= (x2a & x3a);
49 x0b ^= (x2b & x3b);
50 x3a ^= (~x1a & x2a);
51 x3b ^= (~x1b & x2b);
52 x1a ^= (x0a & x2a);
53 x1b ^= (x0b & x2b);
54 x2a ^= (x0a & ~x3a);
55 x2b ^= (x0b & ~x3b);
56 x0a ^= (x1a | x3a);
57 x0b ^= (x1b | x3b);
58 x3a ^= (x1a & x2a);
59 x3b ^= (x1b & x2b);
60 x1a ^= (ta & x0a);
61 x1b ^= (tb & x0b);
62 x2a ^= ta;
63 x2b ^= tb;
64 }
65
66 static inline void Lbitsli(std::array<uint64_t, 16>& H)
67 {
68 H[2] ^= H[4];
69 H[3] ^= H[5];
70 H[6] ^= H[8];
71 H[7] ^= H[9];
72 H[10] ^= H[12] ^ H[0];
73 H[11] ^= H[13] ^ H[1];
74 H[14] ^= H[0];
75 H[15] ^= H[1];
76 H[0] ^= H[6];
77 H[1] ^= H[7];
78 H[4] ^= H[10];
79 H[5] ^= H[11];
80 H[8] ^= H[14] ^ H[2];
81 H[9] ^= H[15] ^ H[3];
82 H[12] ^= H[2];
83 H[13] ^= H[3];
84 }
85
86 static inline void round(std::array<uint64_t, 16>& H, int r, uint64_t mask, int shift)
87 {
88 jh_functions::Sbitsli(H[0], H[1], H[4], H[5], H[8], H[9], H[12], H[13],
89 jh_constants<void>::C[r * 4 + 0], jh_constants<void>::C[r * 4 + 1]);
90 jh_functions::Sbitsli(H[2], H[3], H[6], H[7], H[10], H[11], H[14], H[15],
91 jh_constants<void>::C[r * 4 + 2], jh_constants<void>::C[r * 4 + 3]);
93 if (shift)
94 jh_functions::bitswap(H, mask, shift);
95 }
96}
97
98template<size_t HS = 0>
100{
101public:
102 static const bool is_xof = false;
103
104 template<size_t hss=HS, typename std::enable_if<hss == 0>::type* = nullptr>
105 jh_provider(size_t hashsize = 512)
106 : hs(hashsize)
107 {
108 validate_hash_size(hashsize, 512);
109 }
110
111 template<size_t hss=HS, typename std::enable_if<hss != 0>::type* = nullptr>
113 : hs(hss)
114 {
115 static_assert(hss <= 512 && hss > 0 && hss % 8 == 0);
116 }
117
119 {
120 clear();
121 }
122
123 inline void init()
124 {
125 pos = 0;
126 total = 0;
127
128 zero_memory(H);
129 H[0] = byteswap(static_cast<uint16_t>(hs));
130
131 unsigned char msg[64];
132 memset(msg, 0, sizeof(msg));
133 transform(msg, 1);
134 }
135
136 inline void update(const unsigned char* data, size_t len)
137 {
138 detail::absorb_bytes(data, len, 64, 64, m.data(), pos, total,
139 [this](const unsigned char* data, size_t len) { transform(data, len); });
140 }
141
142 inline void final(unsigned char* hash)
143 {
144 total += pos * 8;
145 m[pos++] = 0x80;
146 if (pos > 1)
147 {
148 if (pos != 64)
149 memset(&m[pos], 0, 64 - pos);
150 transform(&m[0], 1);
151 pos = 0;
152 }
153 memset(&m[0] + pos, 0, 56 - pos);
154 uint64_t mlen = byteswap(total);
155 memcpy(&m[0] + (64 - 8), &mlen, 64 / 8);
156 transform(&m[0], 1);
157
158 memcpy(hash, reinterpret_cast<unsigned char*>(H.data()) + 128 - hash_size() / 8, hash_size() / 8);
159 }
160
161 inline void clear()
162 {
163 zero_memory(H);
164 zero_memory(m);
165 }
166
167 inline size_t hash_size() const { return hs; }
168
169private:
170 inline void transform(const unsigned char* mp, size_t num_blks)
171 {
172 for (uint64_t blk = 0; blk < num_blks; blk++)
173 {
174 const uint64_t* M = (const uint64_t*)(((const unsigned char*)mp) + blk * 64);
175 H[0] ^= M[0];
176 H[1] ^= M[1];
177 H[2] ^= M[2];
178 H[3] ^= M[3];
179 H[4] ^= M[4];
180 H[5] ^= M[5];
181 H[6] ^= M[6];
182 H[7] ^= M[7];
183
184 // partially unroll
185 for (int r = 0; r < 42; r += 7)
186 {
187 jh_functions::round(H, r, 0x5555555555555555ULL, 1);
188 jh_functions::round(H, r + 1, 0x3333333333333333ULL, 2);
189 jh_functions::round(H, r + 2, 0x0f0f0f0f0f0f0f0fULL, 4);
190 jh_functions::round(H, r + 3, 0x00ff00ff00ff00ffULL, 8);
191 jh_functions::round(H, r + 4, 0x0000ffff0000ffffULL, 16);
192 jh_functions::round(H, r + 5, 0x00000000ffffffffULL, 32);
193 jh_functions::round(H, r + 6, 0, 0);
194
195 std::swap(H[2], H[3]);
196 std::swap(H[6], H[7]);
197 std::swap(H[10], H[11]);
198 std::swap(H[14], H[15]);
199 }
200
201 H[8] ^= M[0];
202 H[9] ^= M[1];
203 H[10] ^= M[2];
204 H[11] ^= M[3];
205 H[12] ^= M[4];
206 H[13] ^= M[5];
207 H[14] ^= M[6];
208 H[15] ^= M[7];
209 }
210 }
211
212 std::array<uint64_t, 16> H;
213 std::array<unsigned char, 64> m;
214 size_t hs;
215 size_t pos;
216 uint64_t total;
217};
218
219} // namespace detail
220
221} // namespace digestpp
222
223#endif
Definition jh_provider.hpp:100
size_t hash_size() const
Definition jh_provider.hpp:167
void init()
Definition jh_provider.hpp:123
void clear()
Definition jh_provider.hpp:161
jh_provider()
Definition jh_provider.hpp:112
jh_provider(size_t hashsize=512)
Definition jh_provider.hpp:105
void update(const unsigned char *data, size_t len)
Definition jh_provider.hpp:136
~jh_provider()
Definition jh_provider.hpp:118
static void bitswap(uint64_t &x, uint64_t mask, int shift)
Definition jh_provider.hpp:22
static void Lbitsli(std::array< uint64_t, 16 > &H)
Definition jh_provider.hpp:66
static void round(std::array< uint64_t, 16 > &H, int r, uint64_t mask, int shift)
Definition jh_provider.hpp:86
static void Sbitsli(uint64_t &x0a, uint64_t &x0b, uint64_t &x1a, uint64_t &x1b, uint64_t &x2a, uint64_t &x2b, uint64_t &x3a, uint64_t &x3b, uint64_t ca, uint64_t cb)
Definition jh_provider.hpp:39
uint16_t byteswap(uint16_t val)
Definition functions.hpp:16
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 jh_constants.hpp:16