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 {
40typedef unsigned long word_t;
41typedef unsigned char byte_t;
42
43static const size_t k_digest_size = 32;
44
45namespace detail {
46inline byte_t mask_8bit(byte_t x) { return x & 0xff; }
47
48inline word_t mask_32bit(word_t x) { return x & 0xffffffff; }
49
50const word_t add_constant[64] = {
51 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
52 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
53 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
54 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
55 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
56 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
57 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
58 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
59 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
60 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
61 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
62
63const word_t initial_message_digest[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372,
64 0xa54ff53a, 0x510e527f, 0x9b05688c,
65 0x1f83d9ab, 0x5be0cd19};
66
67inline word_t ch(word_t x, word_t y, word_t z) { return (x & y) ^ ((~x) & z); }
68
69inline word_t maj(word_t x, word_t y, word_t z) {
70 return (x & y) ^ (x & z) ^ (y & z);
71}
72
73inline word_t rotr(word_t x, std::size_t n) {
74 assert(n < 32);
75 return mask_32bit((x >> n) | (x << (32 - n)));
76}
77
78inline word_t bsig0(word_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); }
79
80inline word_t bsig1(word_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); }
81
82inline word_t shr(word_t x, std::size_t n) {
83 assert(n < 32);
84 return x >> n;
85}
86
87inline word_t ssig0(word_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3); }
88
89inline word_t ssig1(word_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10); }
90
91template <typename RaIter1, typename RaIter2>
92void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last) {
93 assert(first + 64 == last);
94 static_cast<void>(last); // for avoiding unused-variable warning
95 word_t w[64];
96 std::fill(w, w + 64, word_t(0));
97 for (std::size_t i = 0; i < 16; ++i) {
98 w[i] = (static_cast<word_t>(mask_8bit(*(first + i * 4))) << 24) |
99 (static_cast<word_t>(mask_8bit(*(first + i * 4 + 1))) << 16) |
100 (static_cast<word_t>(mask_8bit(*(first + i * 4 + 2))) << 8) |
101 (static_cast<word_t>(mask_8bit(*(first + i * 4 + 3))));
102 }
103 for (std::size_t i = 16; i < 64; ++i) {
104 w[i] = mask_32bit(ssig1(w[i - 2]) + w[i - 7] + ssig0(w[i - 15]) +
105 w[i - 16]);
106 }
107
108 word_t a = *message_digest;
109 word_t b = *(message_digest + 1);
110 word_t c = *(message_digest + 2);
111 word_t d = *(message_digest + 3);
112 word_t e = *(message_digest + 4);
113 word_t f = *(message_digest + 5);
114 word_t g = *(message_digest + 6);
115 word_t h = *(message_digest + 7);
116
117 for (std::size_t i = 0; i < 64; ++i) {
118 word_t temp1 = h + bsig1(e) + ch(e, f, g) + add_constant[i] + w[i];
119 word_t temp2 = bsig0(a) + maj(a, b, c);
120 h = g;
121 g = f;
122 f = e;
123 e = mask_32bit(d + temp1);
124 d = c;
125 c = b;
126 b = a;
127 a = mask_32bit(temp1 + temp2);
128 }
129 *message_digest += a;
130 *(message_digest + 1) += b;
131 *(message_digest + 2) += c;
132 *(message_digest + 3) += d;
133 *(message_digest + 4) += e;
134 *(message_digest + 5) += f;
135 *(message_digest + 6) += g;
136 *(message_digest + 7) += h;
137 for (std::size_t i = 0; i < 8; ++i) {
138 *(message_digest + i) = mask_32bit(*(message_digest + i));
139 }
140}
141
142} // namespace detail
143
144template <typename InIter>
145void output_hex(InIter first, InIter last, std::ostream& os) {
146 os.setf(std::ios::hex, std::ios::basefield);
147 while (first != last) {
148 os.width(2);
149 os.fill('0');
150 os << static_cast<unsigned int>(*first);
151 ++first;
152 }
153 os.setf(std::ios::dec, std::ios::basefield);
154}
155
156template <typename InIter>
157void 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
163template <typename InContainer>
164void bytes_to_hex_string(const InContainer& bytes, std::string& hex_str) {
165 bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str);
166}
167
168template <typename InIter>
169std::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
175template <typename InContainer>
176std::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
182class hash256_one_by_one {
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, word_t(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(static_cast<word_t>(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, byte_t(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, byte_t(0));
214 detail::hash256_block(h_, temp, temp + 64);
215 std::fill(temp, temp + 64 - 4, byte_t(0));
216 } else {
217 std::fill(temp + remains + 1, temp + 64 - 4, byte_t(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
274inline void get_hash_hex_string(const hash256_one_by_one& hasher,
275 std::string& hex_str) {
276 byte_t hash[k_digest_size];
277 hasher.get_hash_bytes(hash, hash + k_digest_size);
278 return bytes_to_hex_string(hash, hash + k_digest_size, hex_str);
279}
280
281inline 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
287namespace impl {
288template <typename RaIter, typename OutIter>
289void 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
298template <typename InputIter, typename OutIter>
299void 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
320template <typename InIter, typename OutIter>
321void 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
328template <typename InIter, typename OutContainer>
329void hash256(InIter first, InIter last, OutContainer& dst) {
330 hash256(first, last, dst.begin(), dst.end());
331}
332
333template <typename InContainer, typename OutIter>
334void hash256(const InContainer& src, OutIter first, OutIter last) {
335 hash256(src.begin(), src.end(), first, last);
336}
337
338template <typename InContainer, typename OutContainer>
339void hash256(const InContainer& src, OutContainer& dst) {
340 hash256(src.begin(), src.end(), dst.begin(), dst.end());
341}
342
343template <typename InIter>
344void hash256_hex_string(InIter first, InIter last, std::string& hex_str) {
345 byte_t hashed[k_digest_size];
346 hash256(first, last, hashed, hashed + k_digest_size);
347 std::ostringstream oss;
348 output_hex(hashed, hashed + k_digest_size, oss);
349 hex_str.assign(oss.str());
350}
351
352template <typename InIter>
353std::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
359inline void hash256_hex_string(const std::string& src, std::string& hex_str) {
360 hash256_hex_string(src.begin(), src.end(), hex_str);
361}
362
363template <typename InContainer>
364void hash256_hex_string(const InContainer& src, std::string& hex_str) {
365 hash256_hex_string(src.begin(), src.end(), hex_str);
366}
367
368template <typename InContainer>
369std::string hash256_hex_string(const InContainer& src) {
370 return hash256_hex_string(src.begin(), src.end());
371}
372template<typename OutIter>void hash256(std::ifstream& f, OutIter first, OutIter last){
373 hash256(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>(), first,last);
374
375}
376}// namespace picosha2
377#endif // PICOSHA2_H
378