ESBMC
Efficient SMT-based Context-Bounded Model Checker
Loading...
Searching...
No Matches
picosha2.h
Go to the documentation of this file.
1/*
2The MIT License (MIT)
3
4Copyright (C) 2017 okdshin
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22THE SOFTWARE.
23*/
24#ifndef PICOSHA2_H
25#define PICOSHA2_H
26// picosha2:20140213
27
28#ifndef PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR
29# define PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR \
30 1048576 //=1024*1024: default is 1MB memory
31#endif
32
33#include <algorithm>
34#include <cassert>
35#include <iterator>
36#include <sstream>
37#include <vector>
38#include <fstream>
39namespace picosha2
40{
41typedef unsigned long word_t;
42typedef unsigned char byte_t;
43
44static const size_t k_digest_size = 32;
45
46namespace detail
47{
49{
50 return x & 0xff;
51}
52
54{
55 return x & 0xffffffff;
56}
57
58const word_t add_constant[64] = {
59 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
60 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
61 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
62 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
63 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
64 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
65 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
66 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
67 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
68 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
69 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
70
72 0x6a09e667,
73 0xbb67ae85,
74 0x3c6ef372,
75 0xa54ff53a,
76 0x510e527f,
77 0x9b05688c,
78 0x1f83d9ab,
79 0x5be0cd19};
80
81inline word_t ch(word_t x, word_t y, word_t z)
82{
83 return (x & y) ^ ((~x) & z);
84}
85
86inline word_t maj(word_t x, word_t y, word_t z)
87{
88 return (x & y) ^ (x & z) ^ (y & z);
89}
90
91inline word_t rotr(word_t x, std::size_t n)
92{
93 assert(n < 32);
94 return mask_32bit((x >> n) | (x << (32 - n)));
95}
96
98{
99 return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);
100}
101
103{
104 return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);
105}
106
107inline word_t shr(word_t x, std::size_t n)
108{
109 assert(n < 32);
110 return x >> n;
111}
112
114{
115 return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3);
116}
117
119{
120 return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10);
121}
122
123template <typename RaIter1, typename RaIter2>
124void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last)
125{
126 assert(first + 64 == last);
127 static_cast<void>(last); // for avoiding unused-variable warning
128 word_t w[64];
129 std::fill(w, w + 64, word_t(0));
130 for (std::size_t i = 0; i < 16; ++i)
131 {
132 w[i] = (static_cast<word_t>(mask_8bit(*(first + i * 4))) << 24) |
133 (static_cast<word_t>(mask_8bit(*(first + i * 4 + 1))) << 16) |
134 (static_cast<word_t>(mask_8bit(*(first + i * 4 + 2))) << 8) |
135 (static_cast<word_t>(mask_8bit(*(first + i * 4 + 3))));
136 }
137 for (std::size_t i = 16; i < 64; ++i)
138 {
139 w[i] =
140 mask_32bit(ssig1(w[i - 2]) + w[i - 7] + ssig0(w[i - 15]) + w[i - 16]);
141 }
142
143 word_t a = *message_digest;
144 word_t b = *(message_digest + 1);
145 word_t c = *(message_digest + 2);
146 word_t d = *(message_digest + 3);
147 word_t e = *(message_digest + 4);
148 word_t f = *(message_digest + 5);
149 word_t g = *(message_digest + 6);
150 word_t h = *(message_digest + 7);
151
152 for (std::size_t i = 0; i < 64; ++i)
153 {
154 word_t temp1 = h + bsig1(e) + ch(e, f, g) + add_constant[i] + w[i];
155 word_t temp2 = bsig0(a) + maj(a, b, c);
156 h = g;
157 g = f;
158 f = e;
159 e = mask_32bit(d + temp1);
160 d = c;
161 c = b;
162 b = a;
163 a = mask_32bit(temp1 + temp2);
164 }
165 *message_digest += a;
166 *(message_digest + 1) += b;
167 *(message_digest + 2) += c;
168 *(message_digest + 3) += d;
169 *(message_digest + 4) += e;
170 *(message_digest + 5) += f;
171 *(message_digest + 6) += g;
172 *(message_digest + 7) += h;
173 for (std::size_t i = 0; i < 8; ++i)
174 {
175 *(message_digest + i) = mask_32bit(*(message_digest + i));
176 }
177}
178
179} // namespace detail
180
181template <typename InIter>
182void output_hex(InIter first, InIter last, std::ostream &os)
183{
184 os.setf(std::ios::hex, std::ios::basefield);
185 while (first != last)
186 {
187 os.width(2);
188 os.fill('0');
189 os << static_cast<unsigned int>(*first);
190 ++first;
191 }
192 os.setf(std::ios::dec, std::ios::basefield);
193}
194
195template <typename InIter>
196void bytes_to_hex_string(InIter first, InIter last, std::string &hex_str)
197{
198 std::ostringstream oss;
199 output_hex(first, last, oss);
200 hex_str.assign(oss.str());
201}
202
203template <typename InContainer>
204void bytes_to_hex_string(const InContainer &bytes, std::string &hex_str)
205{
206 bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str);
207}
208
209template <typename InIter>
210std::string bytes_to_hex_string(InIter first, InIter last)
211{
212 std::string hex_str;
213 bytes_to_hex_string(first, last, hex_str);
214 return hex_str;
215}
216
217template <typename InContainer>
218std::string bytes_to_hex_string(const InContainer &bytes)
219{
220 std::string hex_str;
221 bytes_to_hex_string(bytes, hex_str);
222 return hex_str;
223}
224
226{
227public:
229 {
230 init();
231 }
232
233 void init()
234 {
235 buffer_.clear();
236 std::fill(data_length_digits_, data_length_digits_ + 4, word_t(0));
237 std::copy(
239 }
240
241 template <typename RaIter>
242 void process(RaIter first, RaIter last)
243 {
244 add_to_data_length(static_cast<word_t>(std::distance(first, last)));
245 std::copy(first, last, std::back_inserter(buffer_));
246 std::size_t i = 0;
247 for (; i + 64 <= buffer_.size(); i += 64)
248 {
249 detail::hash256_block(h_, buffer_.begin() + i, buffer_.begin() + i + 64);
250 }
251 buffer_.erase(buffer_.begin(), buffer_.begin() + i);
252 }
253
254 void finish()
255 {
256 byte_t temp[64];
257 std::fill(temp, temp + 64, byte_t(0));
258 std::size_t remains = buffer_.size();
259 std::copy(buffer_.begin(), buffer_.end(), temp);
260 assert(remains < 64);
261
262 // This branch is not executed actually (`remains` is always lower than 64),
263 // but needed to avoid g++ false-positive warning.
264 // See https://github.com/okdshin/PicoSHA2/issues/25
265 // vvvvvvvvvvvvvvvv
266 if (remains >= 64)
267 {
268 remains = 63;
269 }
270 // ^^^^^^^^^^^^^^^^
271
272 temp[remains] = 0x80;
273
274 if (remains > 55)
275 {
276 std::fill(temp + remains + 1, temp + 64, byte_t(0));
277 detail::hash256_block(h_, temp, temp + 64);
278 std::fill(temp, temp + 64 - 4, byte_t(0));
279 }
280 else
281 {
282 std::fill(temp + remains + 1, temp + 64 - 4, byte_t(0));
283 }
284
285 write_data_bit_length(&(temp[56]));
286 detail::hash256_block(h_, temp, temp + 64);
287 }
288
289 template <typename OutIter>
290 void get_hash_bytes(OutIter first, OutIter last) const
291 {
292 for (const word_t *iter = h_; iter != h_ + 8; ++iter)
293 {
294 for (std::size_t i = 0; i < 4 && first != last; ++i)
295 {
296 *(first++) =
297 detail::mask_8bit(static_cast<byte_t>((*iter >> (24 - 8 * i))));
298 }
299 }
300 }
301
302private:
303 void add_to_data_length(word_t n)
304 {
305 word_t carry = 0;
306 data_length_digits_[0] += n;
307 for (std::size_t i = 0; i < 4; ++i)
308 {
309 data_length_digits_[i] += carry;
310 if (data_length_digits_[i] >= 65536u)
311 {
312 carry = data_length_digits_[i] >> 16;
313 data_length_digits_[i] &= 65535u;
314 }
315 else
316 {
317 break;
318 }
319 }
320 }
321 void write_data_bit_length(byte_t *begin)
322 {
323 word_t data_bit_length_digits[4];
324 std::copy(
325 data_length_digits_, data_length_digits_ + 4, data_bit_length_digits);
326
327 // convert byte length to bit length (multiply 8 or shift 3 times left)
328 word_t carry = 0;
329 for (std::size_t i = 0; i < 4; ++i)
330 {
331 word_t before_val = data_bit_length_digits[i];
332 data_bit_length_digits[i] <<= 3;
333 data_bit_length_digits[i] |= carry;
334 data_bit_length_digits[i] &= 65535u;
335 carry = (before_val >> (16 - 3)) & 65535u;
336 }
337
338 // write data_bit_length
339 for (int i = 3; i >= 0; --i)
340 {
341 (*begin++) = static_cast<byte_t>(data_bit_length_digits[i] >> 8);
342 (*begin++) = static_cast<byte_t>(data_bit_length_digits[i]);
343 }
344 }
345 std::vector<byte_t> buffer_;
346 word_t data_length_digits_[4]; // as 64bit integer (16bit x 4 integer)
347 word_t h_[8];
348};
349
350inline void
351get_hash_hex_string(const hash256_one_by_one &hasher, std::string &hex_str)
352{
353 byte_t hash[k_digest_size];
354 hasher.get_hash_bytes(hash, hash + k_digest_size);
355 return bytes_to_hex_string(hash, hash + k_digest_size, hex_str);
356}
357
358inline std::string get_hash_hex_string(const hash256_one_by_one &hasher)
359{
360 std::string hex_str;
361 get_hash_hex_string(hasher, hex_str);
362 return hex_str;
363}
364
365namespace impl
366{
367template <typename RaIter, typename OutIter>
369 RaIter first,
370 RaIter last,
371 OutIter first2,
372 OutIter last2,
373 int,
375{
376 hash256_one_by_one hasher;
377 // hasher.init();
378 hasher.process(first, last);
379 hasher.finish();
380 hasher.get_hash_bytes(first2, last2);
381}
382
383template <typename InputIter, typename OutIter>
385 InputIter first,
386 InputIter last,
387 OutIter first2,
388 OutIter last2,
389 int buffer_size,
391{
392 std::vector<byte_t> buffer(buffer_size);
393 hash256_one_by_one hasher;
394 // hasher.init();
395 while (first != last)
396 {
397 int size = buffer_size;
398 for (int i = 0; i != buffer_size; ++i, ++first)
399 {
400 if (first == last)
401 {
402 size = i;
403 break;
404 }
405 buffer[i] = *first;
406 }
407 hasher.process(buffer.begin(), buffer.begin() + size);
408 }
409 hasher.finish();
410 hasher.get_hash_bytes(first2, last2);
411}
412} // namespace impl
413
414template <typename InIter, typename OutIter>
416 InIter first,
417 InIter last,
418 OutIter first2,
419 OutIter last2,
421{
423 first,
424 last,
425 first2,
426 last2,
427 buffer_size,
428 typename std::iterator_traits<InIter>::iterator_category());
429}
430
431template <typename InIter, typename OutContainer>
432void hash256(InIter first, InIter last, OutContainer &dst)
433{
434 hash256(first, last, dst.begin(), dst.end());
435}
436
437template <typename InContainer, typename OutIter>
438void hash256(const InContainer &src, OutIter first, OutIter last)
439{
440 hash256(src.begin(), src.end(), first, last);
441}
442
443template <typename InContainer, typename OutContainer>
444void hash256(const InContainer &src, OutContainer &dst)
445{
446 hash256(src.begin(), src.end(), dst.begin(), dst.end());
447}
448
449template <typename InIter>
450void hash256_hex_string(InIter first, InIter last, std::string &hex_str)
451{
452 byte_t hashed[k_digest_size];
453 hash256(first, last, hashed, hashed + k_digest_size);
454 std::ostringstream oss;
455 output_hex(hashed, hashed + k_digest_size, oss);
456 hex_str.assign(oss.str());
457}
458
459template <typename InIter>
460std::string hash256_hex_string(InIter first, InIter last)
461{
462 std::string hex_str;
463 hash256_hex_string(first, last, hex_str);
464 return hex_str;
465}
466
467inline void hash256_hex_string(const std::string &src, std::string &hex_str)
468{
469 hash256_hex_string(src.begin(), src.end(), hex_str);
470}
471
472template <typename InContainer>
473void hash256_hex_string(const InContainer &src, std::string &hex_str)
474{
475 hash256_hex_string(src.begin(), src.end(), hex_str);
476}
477
478template <typename InContainer>
479std::string hash256_hex_string(const InContainer &src)
480{
481 return hash256_hex_string(src.begin(), src.end());
482}
483template <typename OutIter>
484void hash256(std::ifstream &f, OutIter first, OutIter last)
485{
486 hash256(
487 std::istreambuf_iterator<char>(f),
488 std::istreambuf_iterator<char>(),
489 first,
490 last);
491}
492} // namespace picosha2
493#endif // PICOSHA2_H
Definition picosha2.h:226
void finish()
Definition picosha2.h:254
void process(RaIter first, RaIter last)
Definition picosha2.h:242
void get_hash_bytes(OutIter first, OutIter last) const
Definition picosha2.h:290
void init()
Definition picosha2.h:233
hash256_one_by_one()
Definition picosha2.h:228
Definition os.py:1
Definition picosha2.h:47
void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last)
Definition picosha2.h:124
byte_t mask_8bit(byte_t x)
Definition picosha2.h:48
word_t ssig0(word_t x)
Definition picosha2.h:113
word_t maj(word_t x, word_t y, word_t z)
Definition picosha2.h:86
word_t bsig0(word_t x)
Definition picosha2.h:97
word_t ssig1(word_t x)
Definition picosha2.h:118
word_t ch(word_t x, word_t y, word_t z)
Definition picosha2.h:81
word_t rotr(word_t x, std::size_t n)
Definition picosha2.h:91
word_t bsig1(word_t x)
Definition picosha2.h:102
word_t shr(word_t x, std::size_t n)
Definition picosha2.h:107
word_t mask_32bit(word_t x)
Definition picosha2.h:53
const word_t add_constant[64]
Definition picosha2.h:58
const word_t initial_message_digest[8]
Definition picosha2.h:71
Definition picosha2.h:366
void hash256_impl(RaIter first, RaIter last, OutIter first2, OutIter last2, int, std::random_access_iterator_tag)
Definition picosha2.h:368
Definition picosha2.h:40
void hash256(InIter first, InIter last, OutIter first2, OutIter last2, int buffer_size=PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR)
Definition picosha2.h:415
void bytes_to_hex_string(InIter first, InIter last, std::string &hex_str)
Definition picosha2.h:196
void get_hash_hex_string(const hash256_one_by_one &hasher, std::string &hex_str)
Definition picosha2.h:351
unsigned char byte_t
Definition picosha2.h:42
unsigned long word_t
Definition picosha2.h:41
void hash256_hex_string(InIter first, InIter last, std::string &hex_str)
Definition picosha2.h:450
static const size_t k_digest_size
Definition picosha2.h:44
void output_hex(InIter first, InIter last, std::ostream &os)
Definition picosha2.h:182
#define PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR
Definition picosha2.h:29
Marking input iterators.
Definition iterator_tags.h:17
Definition iterator_tags.h:37