4 Copyright (C) 2017 okdshin
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:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
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
28 #ifndef PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR
29 #define PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR \
30 1048576 //=1024*1024: default is 1MB memory
40 typedef unsigned long word_t
;
41 typedef unsigned char byte_t
;
43 static const size_t k_digest_size
= 32;
46 inline byte_t
mask_8bit(byte_t x
) { return x
& 0xff; }
48 inline word_t
mask_32bit(word_t x
) { return x
& 0xffffffff; }
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};
63 const word_t initial_message_digest
[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372,
64 0xa54ff53a, 0x510e527f, 0x9b05688c,
65 0x1f83d9ab, 0x5be0cd19};
67 inline word_t
ch(word_t x
, word_t y
, word_t z
) { return (x
& y
) ^ ((~x
) & z
); }
69 inline word_t
maj(word_t x
, word_t y
, word_t z
) {
70 return (x
& y
) ^ (x
& z
) ^ (y
& z
);
73 inline word_t
rotr(word_t x
, std::size_t n
) {
75 return mask_32bit((x
>> n
) | (x
<< (32 - n
)));
78 inline word_t
bsig0(word_t x
) { return rotr(x
, 2) ^ rotr(x
, 13) ^ rotr(x
, 22); }
80 inline word_t
bsig1(word_t x
) { return rotr(x
, 6) ^ rotr(x
, 11) ^ rotr(x
, 25); }
82 inline word_t
shr(word_t x
, std::size_t n
) {
87 inline word_t
ssig0(word_t x
) { return rotr(x
, 7) ^ rotr(x
, 18) ^ shr(x
, 3); }
89 inline word_t
ssig1(word_t x
) { return rotr(x
, 17) ^ rotr(x
, 19) ^ shr(x
, 10); }
91 template <typename RaIter1
, typename RaIter2
>
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
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))));
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]) +
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);
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
);
123 e
= mask_32bit(d
+ temp1
);
127 a
= mask_32bit(temp1
+ temp2
);
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
));
142 } // namespace detail
144 template <typename InIter
>
145 void output_hex(InIter first
, InIter last
, std::ostream
& os
) {
146 os
.setf(std::ios::hex
, std::ios::basefield
);
147 while (first
!= last
) {
150 os
<< static_cast<unsigned int>(*first
);
153 os
.setf(std::ios::dec
, std::ios::basefield
);
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());
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
);
168 template <typename InIter
>
169 std::string
bytes_to_hex_string(InIter first
, InIter last
) {
171 bytes_to_hex_string(first
, last
, hex_str
);
175 template <typename InContainer
>
176 std::string
bytes_to_hex_string(const InContainer
& bytes
) {
178 bytes_to_hex_string(bytes
, hex_str
);
182 class hash256_one_by_one
{
184 hash256_one_by_one() { init(); }
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_
);
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_
));
198 for (; i
+ 64 <= buffer_
.size(); i
+= 64) {
199 detail::hash256_block(h_
, buffer_
.begin() + i
,
200 buffer_
.begin() + i
+ 64);
202 buffer_
.erase(buffer_
.begin(), buffer_
.begin() + i
);
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;
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));
217 std::fill(temp
+ remains
+ 1, temp
+ 64 - 4, byte_t(0));
220 write_data_bit_length(&(temp
[56]));
221 detail::hash256_block(h_
, temp
, temp
+ 64);
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
))));
235 void add_to_data_length(word_t n
) {
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;
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
);
253 // convert byte length to bit length (multiply 8 or shift 3 times left)
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;
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
]);
269 std::vector
<byte_t
> buffer_
;
270 word_t data_length_digits_
[4]; // as 64bit integer (16bit x 4 integer)
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
);
281 inline std::string
get_hash_hex_string(const hash256_one_by_one
& hasher
) {
283 get_hash_hex_string(hasher
, hex_str
);
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
;
293 hasher
.process(first
, last
);
295 hasher
.get_hash_bytes(first2
, last2
);
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
;
304 while (first
!= last
) {
305 int size
= buffer_size
;
306 for (int i
= 0; i
!= buffer_size
; ++i
, ++first
) {
313 hasher
.process(buffer
.begin(), buffer
.begin() + size
);
316 hasher
.get_hash_bytes(first2
, last2
);
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());
328 template <typename InIter
, typename OutContainer
>
329 void hash256(InIter first
, InIter last
, OutContainer
& dst
) {
330 hash256(first
, last
, dst
.begin(), dst
.end());
333 template <typename InContainer
, typename OutIter
>
334 void hash256(const InContainer
& src
, OutIter first
, OutIter last
) {
335 hash256(src
.begin(), src
.end(), first
, last
);
338 template <typename InContainer
, typename OutContainer
>
339 void hash256(const InContainer
& src
, OutContainer
& dst
) {
340 hash256(src
.begin(), src
.end(), dst
.begin(), dst
.end());
343 template <typename InIter
>
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());
352 template <typename InIter
>
353 std::string
hash256_hex_string(InIter first
, InIter last
) {
355 hash256_hex_string(first
, last
, 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
);
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
);
368 template <typename InContainer
>
369 std::string
hash256_hex_string(const InContainer
& src
) {
370 return hash256_hex_string(src
.begin(), src
.end());
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
);
376 }// namespace picosha2