bes  Updated for version 3.20.6
picosha2.h
1 /*
2 The MIT License (MIT)
3 
4 Copyright (C) 2017 okdshin
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE 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 
39 namespace picosha2 {
40 typedef unsigned long word_t;
41 typedef unsigned char byte_t;
42 
43 namespace detail {
44 inline byte_t mask_8bit(byte_t x) { return x & 0xff; }
45 
46 inline word_t mask_32bit(word_t x) { return x & 0xffffffff; }
47 
48 const word_t add_constant[64] = {
49  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
50  0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
51  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
52  0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
53  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
54  0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
55  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
56  0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
57  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
58  0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
59  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
60 
61 const word_t initial_message_digest[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372,
62  0xa54ff53a, 0x510e527f, 0x9b05688c,
63  0x1f83d9ab, 0x5be0cd19};
64 
65 inline word_t ch(word_t x, word_t y, word_t z) { return (x & y) ^ ((~x) & z); }
66 
67 inline word_t maj(word_t x, word_t y, word_t z) {
68  return (x & y) ^ (x & z) ^ (y & z);
69 }
70 
71 inline word_t rotr(word_t x, std::size_t n) {
72  assert(n < 32);
73  return mask_32bit((x >> n) | (x << (32 - n)));
74 }
75 
76 inline word_t bsig0(word_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); }
77 
78 inline word_t bsig1(word_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); }
79 
80 inline word_t shr(word_t x, std::size_t n) {
81  assert(n < 32);
82  return x >> n;
83 }
84 
85 inline word_t ssig0(word_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3); }
86 
87 inline word_t ssig1(word_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10); }
88 
89 template <typename RaIter1, typename RaIter2>
90 void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last) {
91  assert(first + 64 == last);
92  static_cast<void>(last); // for avoiding unused-variable warning
93  word_t w[64];
94  std::fill(w, w + 64, 0);
95  for (std::size_t i = 0; i < 16; ++i) {
96  w[i] = (static_cast<word_t>(mask_8bit(*(first + i * 4))) << 24) |
97  (static_cast<word_t>(mask_8bit(*(first + i * 4 + 1))) << 16) |
98  (static_cast<word_t>(mask_8bit(*(first + i * 4 + 2))) << 8) |
99  (static_cast<word_t>(mask_8bit(*(first + i * 4 + 3))));
100  }
101  for (std::size_t i = 16; i < 64; ++i) {
102  w[i] = mask_32bit(ssig1(w[i - 2]) + w[i - 7] + ssig0(w[i - 15]) +
103  w[i - 16]);
104  }
105 
106  word_t a = *message_digest;
107  word_t b = *(message_digest + 1);
108  word_t c = *(message_digest + 2);
109  word_t d = *(message_digest + 3);
110  word_t e = *(message_digest + 4);
111  word_t f = *(message_digest + 5);
112  word_t g = *(message_digest + 6);
113  word_t h = *(message_digest + 7);
114 
115  for (std::size_t i = 0; i < 64; ++i) {
116  word_t temp1 = h + bsig1(e) + ch(e, f, g) + add_constant[i] + w[i];
117  word_t temp2 = bsig0(a) + maj(a, b, c);
118  h = g;
119  g = f;
120  f = e;
121  e = mask_32bit(d + temp1);
122  d = c;
123  c = b;
124  b = a;
125  a = mask_32bit(temp1 + temp2);
126  }
127  *message_digest += a;
128  *(message_digest + 1) += b;
129  *(message_digest + 2) += c;
130  *(message_digest + 3) += d;
131  *(message_digest + 4) += e;
132  *(message_digest + 5) += f;
133  *(message_digest + 6) += g;
134  *(message_digest + 7) += h;
135  for (std::size_t i = 0; i < 8; ++i) {
136  *(message_digest + i) = mask_32bit(*(message_digest + i));
137  }
138 }
139 
140 } // namespace detail
141 
142 template <typename InIter>
143 void output_hex(InIter first, InIter last, std::ostream& os) {
144  os.setf(std::ios::hex, std::ios::basefield);
145  char orig_fill_char = os.fill();
146  while (first != last) {
147  os.width(2);
148  os.fill('0');
149  os << static_cast<unsigned int>(*first);
150  ++first;
151  }
152  os.setf(std::ios::dec, std::ios::basefield);
153  os.fill(orig_fill_char);
154 }
155 
156 template <typename InIter>
157 void bytes_to_hex_string(InIter first, InIter last, std::string& hex_str) {
158  std::ostringstream oss;
159  output_hex(first, last, oss);
160  hex_str.assign(oss.str());
161 }
162 
163 template <typename InContainer>
164 void bytes_to_hex_string(const InContainer& bytes, std::string& hex_str) {
165  bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str);
166 }
167 
168 template <typename InIter>
169 std::string bytes_to_hex_string(InIter first, InIter last) {
170  std::string hex_str;
171  bytes_to_hex_string(first, last, hex_str);
172  return hex_str;
173 }
174 
175 template <typename InContainer>
176 std::string bytes_to_hex_string(const InContainer& bytes) {
177  std::string hex_str;
178  bytes_to_hex_string(bytes, hex_str);
179  return hex_str;
180 }
181 
183  public:
184  hash256_one_by_one() { init(); }
185 
186  void init() {
187  buffer_.clear();
188  std::fill(data_length_digits_, data_length_digits_ + 4, 0);
189  std::copy(detail::initial_message_digest,
190  detail::initial_message_digest + 8, h_);
191  }
192 
193  template <typename RaIter>
194  void process(RaIter first, RaIter last) {
195  add_to_data_length(std::distance(first, last));
196  std::copy(first, last, std::back_inserter(buffer_));
197  std::size_t i = 0;
198  for (; i + 64 <= buffer_.size(); i += 64) {
199  detail::hash256_block(h_, buffer_.begin() + i,
200  buffer_.begin() + i + 64);
201  }
202  buffer_.erase(buffer_.begin(), buffer_.begin() + i);
203  }
204 
205  void finish() {
206  byte_t temp[64];
207  std::fill(temp, temp + 64, 0);
208  std::size_t remains = buffer_.size();
209  std::copy(buffer_.begin(), buffer_.end(), temp);
210  temp[remains] = 0x80;
211 
212  if (remains > 55) {
213  std::fill(temp + remains + 1, temp + 64, 0);
214  detail::hash256_block(h_, temp, temp + 64);
215  std::fill(temp, temp + 64 - 4, 0);
216  } else {
217  std::fill(temp + remains + 1, temp + 64 - 4, 0);
218  }
219 
220  write_data_bit_length(&(temp[56]));
221  detail::hash256_block(h_, temp, temp + 64);
222  }
223 
224  template <typename OutIter>
225  void get_hash_bytes(OutIter first, OutIter last) const {
226  for (const word_t* iter = h_; iter != h_ + 8; ++iter) {
227  for (std::size_t i = 0; i < 4 && first != last; ++i) {
228  *(first++) = detail::mask_8bit(
229  static_cast<byte_t>((*iter >> (24 - 8 * i))));
230  }
231  }
232  }
233 
234  private:
235  void add_to_data_length(word_t n) {
236  word_t carry = 0;
237  data_length_digits_[0] += n;
238  for (std::size_t i = 0; i < 4; ++i) {
239  data_length_digits_[i] += carry;
240  if (data_length_digits_[i] >= 65536u) {
241  carry = data_length_digits_[i] >> 16;
242  data_length_digits_[i] &= 65535u;
243  } else {
244  break;
245  }
246  }
247  }
248  void write_data_bit_length(byte_t* begin) {
249  word_t data_bit_length_digits[4];
250  std::copy(data_length_digits_, data_length_digits_ + 4,
251  data_bit_length_digits);
252 
253  // convert byte length to bit length (multiply 8 or shift 3 times left)
254  word_t carry = 0;
255  for (std::size_t i = 0; i < 4; ++i) {
256  word_t before_val = data_bit_length_digits[i];
257  data_bit_length_digits[i] <<= 3;
258  data_bit_length_digits[i] |= carry;
259  data_bit_length_digits[i] &= 65535u;
260  carry = (before_val >> (16 - 3)) & 65535u;
261  }
262 
263  // write data_bit_length
264  for (int i = 3; i >= 0; --i) {
265  (*begin++) = static_cast<byte_t>(data_bit_length_digits[i] >> 8);
266  (*begin++) = static_cast<byte_t>(data_bit_length_digits[i]);
267  }
268  }
269  std::vector<byte_t> buffer_;
270  word_t data_length_digits_[4]; // as 64bit integer (16bit x 4 integer)
271  word_t h_[8];
272 };
273 
274 inline void get_hash_hex_string(const hash256_one_by_one& hasher,
275  std::string& hex_str) {
276  byte_t hash[32];
277  hasher.get_hash_bytes(hash, hash + 32);
278  return bytes_to_hex_string(hash, hash + 32, hex_str);
279 }
280 
281 inline std::string get_hash_hex_string(const hash256_one_by_one& hasher) {
282  std::string hex_str;
283  get_hash_hex_string(hasher, hex_str);
284  return hex_str;
285 }
286 
287 namespace impl {
288 template <typename RaIter, typename OutIter>
289 void hash256_impl(RaIter first, RaIter last, OutIter first2, OutIter last2, int,
290  std::random_access_iterator_tag) {
291  hash256_one_by_one hasher;
292  // hasher.init();
293  hasher.process(first, last);
294  hasher.finish();
295  hasher.get_hash_bytes(first2, last2);
296 }
297 
298 template <typename InputIter, typename OutIter>
299 void hash256_impl(InputIter first, InputIter last, OutIter first2,
300  OutIter last2, int buffer_size, std::input_iterator_tag) {
301  std::vector<byte_t> buffer(buffer_size);
302  hash256_one_by_one hasher;
303  // hasher.init();
304  while (first != last) {
305  int size = buffer_size;
306  for (int i = 0; i != buffer_size; ++i, ++first) {
307  if (first == last) {
308  size = i;
309  break;
310  }
311  buffer[i] = *first;
312  }
313  hasher.process(buffer.begin(), buffer.begin() + size);
314  }
315  hasher.finish();
316  hasher.get_hash_bytes(first2, last2);
317 }
318 }
319 
320 template <typename InIter, typename OutIter>
321 void hash256(InIter first, InIter last, OutIter first2, OutIter last2,
322  int buffer_size = PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR) {
323  picosha2::impl::hash256_impl(
324  first, last, first2, last2, buffer_size,
325  typename std::iterator_traits<InIter>::iterator_category());
326 }
327 
328 template <typename InIter, typename OutContainer>
329 void hash256(InIter first, InIter last, OutContainer& dst) {
330  hash256(first, last, dst.begin(), dst.end());
331 }
332 
333 template <typename InContainer, typename OutIter>
334 void hash256(const InContainer& src, OutIter first, OutIter last) {
335  hash256(src.begin(), src.end(), first, last);
336 }
337 
338 template <typename InContainer, typename OutContainer>
339 void hash256(const InContainer& src, OutContainer& dst) {
340  hash256(src.begin(), src.end(), dst.begin(), dst.end());
341 }
342 
343 template <typename InIter>
344 void hash256_hex_string(InIter first, InIter last, std::string& hex_str) {
345  byte_t hashed[32];
346  hash256(first, last, hashed, hashed + 32);
347  std::ostringstream oss;
348  output_hex(hashed, hashed + 32, oss);
349  hex_str.assign(oss.str());
350 }
351 
352 template <typename InIter>
353 std::string hash256_hex_string(InIter first, InIter last) {
354  std::string hex_str;
355  hash256_hex_string(first, last, hex_str);
356  return hex_str;
357 }
358 
359 inline void hash256_hex_string(const std::string& src, std::string& hex_str) {
360  hash256_hex_string(src.begin(), src.end(), hex_str);
361 }
362 
363 template <typename InContainer>
364 void hash256_hex_string(const InContainer& src, std::string& hex_str) {
365  hash256_hex_string(src.begin(), src.end(), hex_str);
366 }
367 
368 template <typename InContainer>
369 std::string hash256_hex_string(const InContainer& src) {
370  return hash256_hex_string(src.begin(), src.end());
371 }
372 
373 } // namespace picosha2
374 
375 #endif // PICOSHA2_H
picosha2::hash256_one_by_one
Definition: picosha2.h:182