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 #include <fstream>
39 namespace picosha2 {
40 typedef unsigned long word_t;
41 typedef unsigned char byte_t;
42 
43 static const size_t k_digest_size = 32;
44 
45 namespace detail {
mask_8bit(byte_t x)46 inline byte_t mask_8bit(byte_t x) { return x & 0xff; }
47 
mask_32bit(word_t x)48 inline word_t mask_32bit(word_t x) { return x & 0xffffffff; }
49 
50 const 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 
63 const word_t initial_message_digest[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372,
64                                           0xa54ff53a, 0x510e527f, 0x9b05688c,
65                                           0x1f83d9ab, 0x5be0cd19};
66 
ch(word_t x,word_t y,word_t z)67 inline word_t ch(word_t x, word_t y, word_t z) { return (x & y) ^ ((~x) & z); }
68 
maj(word_t x,word_t y,word_t z)69 inline word_t maj(word_t x, word_t y, word_t z) {
70     return (x & y) ^ (x & z) ^ (y & z);
71 }
72 
rotr(word_t x,std::size_t n)73 inline 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 
bsig0(word_t x)78 inline word_t bsig0(word_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); }
79 
bsig1(word_t x)80 inline word_t bsig1(word_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); }
81 
shr(word_t x,std::size_t n)82 inline word_t shr(word_t x, std::size_t n) {
83     assert(n < 32);
84     return x >> n;
85 }
86 
ssig0(word_t x)87 inline word_t ssig0(word_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3); }
88 
ssig1(word_t x)89 inline word_t ssig1(word_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10); }
90 
91 template <typename RaIter1, typename RaIter2>
hash256_block(RaIter1 message_digest,RaIter2 first,RaIter2 last)92 void 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, 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 
144 template <typename InIter>
output_hex(InIter first,InIter last,std::ostream & os)145 void 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 
156 template <typename InIter>
bytes_to_hex_string(InIter first,InIter last,std::string & hex_str)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>
bytes_to_hex_string(const InContainer & bytes,std::string & hex_str)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>
bytes_to_hex_string(InIter first,InIter last)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>
bytes_to_hex_string(const InContainer & bytes)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 
182 class hash256_one_by_one {
183    public:
hash256_one_by_one()184     hash256_one_by_one() { init(); }
185 
init()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>
process(RaIter first,RaIter last)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 
finish()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>
get_hash_bytes(OutIter first,OutIter last)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:
add_to_data_length(word_t n)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     }
write_data_bit_length(byte_t * begin)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 
get_hash_hex_string(const hash256_one_by_one & hasher,std::string & hex_str)274 inline 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 
get_hash_hex_string(const hash256_one_by_one & hasher)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>
hash256_impl(RaIter first,RaIter last,OutIter first2,OutIter last2,int,std::random_access_iterator_tag)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>
hash256_impl(InputIter first,InputIter last,OutIter first2,OutIter last2,int buffer_size,std::input_iterator_tag)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>
hash256(InIter first,InIter last,OutContainer & dst)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>
hash256(const InContainer & src,OutIter first,OutIter last)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>
hash256(const InContainer & src,OutContainer & dst)339 void hash256(const InContainer& src, OutContainer& dst) {
340     hash256(src.begin(), src.end(), dst.begin(), dst.end());
341 }
342 
343 template <typename InIter>
hash256_hex_string(InIter first,InIter last,std::string & hex_str)344 void 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 
352 template <typename InIter>
hash256_hex_string(InIter first,InIter last)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 
hash256_hex_string(const std::string & src,std::string & hex_str)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>
hash256_hex_string(const InContainer & src,std::string & hex_str)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>
hash256_hex_string(const InContainer & src)369 std::string hash256_hex_string(const InContainer& src) {
370     return hash256_hex_string(src.begin(), src.end());
371 }
hash256(std::ifstream & f,OutIter first,OutIter last)372 template<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