Adobe Source Libraries 2.0.0
A collection of C++ libraries.
Loading...
Searching...
No Matches
sha.hpp
Go to the documentation of this file.
1/*
2 Copyright 2013 Adobe
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5*/
6/**************************************************************************************************/
7
8#ifndef ADOBE_SHA_HPP
9#define ADOBE_SHA_HPP
10
11/**************************************************************************************************/
12
13#include <array>
14#include <cassert>
15#include <cstdint>
16#include <cstring>
17#include <iterator>
18#include <string>
19
20#include <adobe/cassert.hpp>
21
22/**************************************************************************************************/
23
24namespace adobe {
25
26/**************************************************************************************************/
27
28namespace implementation {
29
30/**************************************************************************************************/
31
32#if !defined(ADOBE_NO_DOCUMENTATION)
33
34/**************************************************************************************************/
35
36template <typename T>
37constexpr std::size_t bitsizeof() {
38 return sizeof(T) * 8;
39}
40
41/**************************************************************************************************/
42
43template <std::size_t N, typename T>
44inline T shr(T x) {
45 static_assert(N < bitsizeof<T>(), "shr size mismatch.");
46
47 return x >> N;
48}
49
50template <std::size_t N, typename T>
51inline T rotr(T x) {
52 static_assert(N < bitsizeof<T>(), "rotr size mismatch.");
53
54 constexpr std::size_t l_shift = bitsizeof<T>() - N;
55
56 return (x >> N) | (x << l_shift);
57}
58
59template <std::size_t N, typename T>
60inline T rotl(T x) {
61 static_assert(N < bitsizeof<T>(), "rotl size mismatch.");
62
63 constexpr std::size_t r_shift = bitsizeof<T>() - N;
64
65 return (x << N) | (x >> r_shift);
66}
67
68/**************************************************************************************************/
69
70template <typename T>
71inline T ch(T x, T y, T z) {
72 return (x & y) ^ (~x & z);
73}
74
75template <typename T>
76inline T parity(T x, T y, T z) {
77 return x ^ y ^ z;
78}
79
80template <typename T>
81inline T maj(T x, T y, T z) {
82 return (x & y) ^ (x & z) ^ (y & z);
83}
84
85/*
86A source of bytes. The input is a range defined by two iterators. The length
87of the range does not need to be known up front. This will work with
88input iterators.
89*/
90template <typename I>
91class byte_source_iterators {
92public:
93 byte_source_iterators(I const& first, I const& last) : first_(first), last_(last) {
94 static_assert(sizeof(typename std::iterator_traits<I>::value_type) == sizeof(std::uint8_t),
95 "Iterator must supply bytes.");
96 }
97
98 // Note that this returns the number of *bits* available. Even though this
99 // class can only returns complete bytes we need consistency with
100 // byte_source_iterator_n.
101 // The number available is not necessarily the total number, it is just
102 // the number we can get hold of right now.
103 std::uint64_t bits_available() const { return (first_ == last_) ? 0 : 8; }
104
105 std::uint8_t operator*() const { return *first_; }
106
107 // Prefix
108 byte_source_iterators& operator++() {
109 ++first_;
110 return *this;
111 }
112
113 // Postfix operator ++ does not work with input iterators so we
114 // do not provide it
115
116 // Making copies does not work if we are using input iterators so forbid
117 // copy construction and assigment
118 byte_source_iterators(byte_source_iterators const&) = delete;
119 byte_source_iterators& operator=(byte_source_iterators const&) = delete;
120
121private:
122 I first_;
123 I const last_;
124};
125
126/*
127A source of bytes. The input is an iterator and the number of *bits* the
128source can provide. Unlike byte_source_iterators we know the length
129up front
130*/
131template <typename I>
132class byte_source_iterator_n {
133public:
134 byte_source_iterator_n(I const& first, std::uint64_t num_bits)
135 : first_(first), num_bits_(num_bits) {
136 static_assert(sizeof(typename std::iterator_traits<I>::value_type) == sizeof(std::uint8_t),
137 "Iterator must supply bytes.");
138 }
139
140 // The last byte might not be complete
141 std::uint64_t bits_available() const { return (num_bits_ > 8u) ? 8u : num_bits_; }
142
143 std::uint8_t operator*() const { return *first_; }
144
145 // Prefix
146 byte_source_iterator_n& operator++() {
147 ++first_;
148 num_bits_ -= bits_available();
149 return *this;
150 }
151
152 // Postfix operator ++ does not work with input iterators so we
153 // do not provide it
154
155 // Making copies does not work if we are using input iterators so forbid
156 // copy construction and assigment
157 byte_source_iterator_n(byte_source_iterator_n const&) = delete;
158 byte_source_iterator_n& operator=(byte_source_iterator_n const&) = delete;
159
160private:
161 I first_;
162 std::uint64_t num_bits_;
163};
164
165/**************************************************************************************************/
166
167template <typename HashTraits, typename ByteSource>
168std::uint64_t stuff_into_state(typename HashTraits::message_block_type& state,
169 std::uint16_t& stuff_bit_offset, std::uint64_t num_bits,
170 ByteSource& byte_source) {
171
172 typedef HashTraits traits_type;
173 typedef typename traits_type::message_block_type::value_type value_type;
174
175 constexpr std::size_t value_size_k = sizeof(value_type);
176 constexpr std::size_t value_bitsize_k = value_size_k * 8;
177
178 /*
179 We are given the stuff bit offset in terms of the whole message block. From there we need to
180 derive which element of the array we are going to stuff into, and the shift within that element.
181 Then we stuff bytes from *first, decreasing the internal shift until we hit zero (stuffing from
182 most significant bit to least significant). Then we advance to the next element, reset the shift
183 to far-right, and keep going.
184
185 For values that come in less than a byte the high bits are where the value is stored, not the
186 low bits.
187 */
188
189 std::size_t element = stuff_bit_offset / value_bitsize_k;
190 std::size_t shift = value_bitsize_k - 8 - // most sig bit, less bitsizeof(*first)
191 stuff_bit_offset % value_bitsize_k; // bits already stuffed.
192 value_type* dst(&state[element]);
193
194 /*
195 As soon as we've gone once through this loop, we'll be on a byte boundary. If we don't go
196 through the loop we'll be off a byte boundary and will have to shift the next byte appropriately
197 (it should shift 0 when we've been through this loop, effectively a nop.)
198 */
199
200 std::uint64_t n_stuffed_bits = 0;
201
202 while (num_bits >= 8 && byte_source.bits_available() >= 8) {
203 *dst |= (value_type(*byte_source) & value_type(0xff)) << shift;
204
205 ++byte_source;
206
207 if (shift == 0) {
208 ++dst;
209
210 shift = value_bitsize_k - 8;
211 } else {
212 shift -= 8;
213 }
214
215 stuff_bit_offset += 8;
216 n_stuffed_bits += 8;
217 num_bits -= 8;
218 }
219
220 // sub-byte leftovers which need to be shifted into place.
221 if (num_bits && byte_source.bits_available()) {
222 num_bits = std::min(num_bits, byte_source.bits_available());
223 /*
224 dst is a window of size value_bitsize_k. The message ends somewhere in the window
225 [ value_bitsize_k .. 1 ], meaning our leftovers get their high order bit pushed to position
226 [ value_bitsize_k - 1 .. 0 ]. Since we know the value is in the low-8-bits of a
227 value_bitsize_k-sized window, we need to shift the value either up or down, depending on
228 where the message ended.
229
230 message_end is the bit location of the last bit of the message. This can be value_bitsize_k,
231 implying the message ended on the value_type boundary.
232 */
233 std::size_t message_end(value_bitsize_k - (stuff_bit_offset % value_bitsize_k));
234 value_type v(*byte_source & 0xff); // our value in the low 8 bits.
235
236 ++byte_source;
237
238 if (message_end < 8) // shift down
239 v >>= 8 - message_end;
240 else if (message_end > 8) // shift up
241 v <<= message_end - 8;
242
243 *dst |= v;
244 ADOBE_ASSERT(num_bits < 8);
245 stuff_bit_offset += static_cast<std::uint16_t>(num_bits);
246 n_stuffed_bits += static_cast<std::uint16_t>(num_bits);
247 }
248 return n_stuffed_bits;
249}
250
251/**************************************************************************************************/
252/*
253We keep a running message block as state, along with info about the total message length to this
254point, as well as the number of bits stuffed in the current message block. Whenever the user wants
255to update the message they pass in some data, which we use to stuff the current message block. When
256that block fills to capacity we digest it and reset the state to prepare to digest the next message
257block. In the end there is work to be done with whatever data might be left over. In finalize, then,
258we add the spec'd 1-bit, zero-pad the message if need be, append the length of the message, and
259digest that final block. The user gets whatever comes out.
260
261This routine expects whole-byte input until the end of the message, at which point the remainder of
262the message can be a subset of 8 bytes. If you're going to be busting up a messages into chunks to
263hash it, then you need to do so at the byte boundary until the last chunk.
264*/
265template <typename HashTraits, typename ByteSource>
266void block_and_digest(typename HashTraits::message_block_type& state, std::uint16_t& stuffed_size,
267 std::uint64_t& message_size, typename HashTraits::state_digest_type& digest,
268 ByteSource& byte_source) {
269 typedef HashTraits traits_type;
270
271 // The size of the message block in bits. Either 512 or 1024.
272 constexpr std::size_t message_blocksize_k = traits_type::message_blocksize_k;
273
274 /*
275 The SHA description has three phases for preparing to digest a message:
276 - padding
277 - parsing (aka blocking)
278 - hash initialization
279
280 All messages are composed of the following:
281 - the message (length: num_bits bits)
282 - a 1-bit (length: 1 bit)
283 - zero padding (varies)
284 - the number of bits of the message (max_message_bitsize_k bits)
285
286 This is the padding and blocking phase. Pack the message into 512- or 1024-bit blocks for
287 digest, padding the message out with a varible number of zero bits such that the last message
288 block is also 512- or 1024-bits long. All blocks will be 100% message except for the last block
289 in the digest That last block, then, will be:
290 - zero-or-more bits of message
291 - the 1 bit
292 - zero-or-more bits of zero-bit padding
293 - the length of the message (max_message_bitsize_k bits)
294 */
295 std::size_t bits_available(message_blocksize_k - stuffed_size);
296
297 while (byte_source.bits_available() > 0) {
298 std::uint64_t const bits_stuffed =
299 stuff_into_state<traits_type>(state, stuffed_size, bits_available, byte_source);
300
301 // If we have a full message block then digest it
302 if (bits_stuffed == bits_available) {
303 traits_type::digest_message_block(digest, state, stuffed_size);
304 }
305
306 message_size += bits_stuffed;
307 bits_available = message_blocksize_k;
308 }
309}
310
311/**************************************************************************************************/
312
313template <bool overshift, typename message_block_type>
314struct shift_down {
315 void operator()(message_block_type&, std::uint64_t,
316 typename message_block_type::value_type) const {}
317};
318
319template <typename message_block_type>
320struct shift_down<false, message_block_type> {
321 void operator()(message_block_type& state, std::uint64_t message_size,
322 typename message_block_type::value_type value_type_mask) const {
323 constexpr std::size_t value_bitsize_k = sizeof(typename message_block_type::value_type) * 8;
324
325 if (message_size > value_type_mask) {
326 state[14] = (message_size >> value_bitsize_k) & value_type_mask;
327 }
328 }
329};
330
331/**************************************************************************************************/
332
333template <typename HashTraits>
334typename HashTraits::digest_type finalize(typename HashTraits::message_block_type& state,
335 std::uint16_t stuffed_size, std::uint64_t message_size,
336 typename HashTraits::state_digest_type& digest) {
337 /*
338 A couple things we have to do in this routine:
339 - add a single 1-bit to the end of the message
340 - pad out the final block to message_blocksize_k bits, less
341 the size of the message
342 - add the size of the message to the end.
343
344 There are concessions we make for when these three elements cause us to cross over the block
345 boundary, requiring us to digest more than one block as we finalize.
346 */
347
348 typedef HashTraits traits_type;
349 typedef typename traits_type::message_block_type message_block_type;
350 typedef typename message_block_type::value_type value_type;
351
352 // Maximum length of message in bits (2^n); this is n. Either 64 or 128.
353 constexpr std::size_t max_message_bitsize_k = traits_type::max_message_bitsize_k;
354 // The size of the message block in bits. Either 512 or 1024.
355 constexpr std::size_t message_blocksize_k = traits_type::message_blocksize_k;
356
357 constexpr std::size_t value_size_k = sizeof(value_type);
358 constexpr std::size_t value_bitsize_k = value_size_k * 8;
359
360 /*
361 Stuff into state needs to operate from the assumption that it is taking the most significant
362 bits of a value and stuffing them into the message. As such our 1-bit here needs to be in the
363 MSB, hence 0x80 and not 1.
364 */
365 std::uint8_t one_bit(0x80);
366 std::uint8_t* one_bit_ptr(&one_bit);
367
368 byte_source_iterator_n<std::uint8_t*> bit_source(one_bit_ptr, 1);
369 stuff_into_state<traits_type>(state, stuffed_size, 1, bit_source);
370
371 /*
372 If that one bit pushed us to the message block boundary, congratulations. Digest the message and
373 reset the machine. Do NOT update the message length - the end bit isn't counted as part of the
374 message.
375 */
376 if (stuffed_size == message_blocksize_k)
377 traits_type::digest_message_block(digest, state, stuffed_size);
378
379 /*
380 Now that we have the last block with (maybe) enough space, find the end and insert the length of
381 the message. Fortunately we have a routine for that.
382
383 Note that if there is not enough space to insert the length of the message (i.e., offset will be
384 less than stuffed_size) we need to digest the block and try again with an empty one.
385 */
386 constexpr std::size_t length_offset(message_blocksize_k - max_message_bitsize_k);
387
388 /*
389 The length of the message will always go into message block elements 14 and/or 15. (i.e., the
390 last two.) State block 15 gets the first half of the size, and state block 14 gets the second
391 half.
392
393 In the event we dont have enough room at the end of the message block to add the length of the
394 message, digest the block as-is (that is, with some amount of zero-padding at the end), then
395 clear it and process another block whose contents are just the length of the message.
396 */
397 if (stuffed_size > length_offset)
398 traits_type::digest_message_block(digest, state, stuffed_size);
399
400 constexpr value_type value_type_mask = static_cast<value_type>(-1);
401
402 /*
403 If the message length is longer than what will fit in the last element of the message block,
404 slice the high bits of the length off and stuff them into the next-to-last element. Note that
405 because of the checks above, we are guaranteed the space will be zero-padded, so we can write
406 over it OK.
407
408 The 15th block requires a shift down of the message size, which in the SHA-512 case is a 64-bit
409 shift of a 64-bit value, which is undefined according to the C++ standard. (This step is were we
410 to store message_size as a 128-bit value, as is allowed by the SHA standard.) As such we derive
411 the overshift boolean and give the compiler the freedom to elide the overshift-and-assignment at
412 compile-time, eliminating the undefined behavior.
413 */
414 constexpr bool overshift = value_bitsize_k >= (sizeof(message_size) * 8);
415 shift_down<overshift, message_block_type>()(state, message_size, value_type_mask);
416
417 state[15] = message_size & value_type_mask;
418
419 // Digest the final block of this message.
420 traits_type::digest_message_block(digest, state, stuffed_size);
421
422 /*
423 Once the finalized block(s) have been digested, copy the result to the digest type and get outta
424 here. Note that this could crop the number of bits between the state digest and the resulting
425 digest, depending on the requirements of the hash algorithm being used.
426 */
427 typedef typename HashTraits::digest_type digest_type;
428
429 digest_type result = {{0}};
430
431 std::memcpy(&result[0], &digest[0], sizeof(digest_type));
432
433 return result;
434}
435
436/**************************************************************************************************/
437
438template <typename HashTraits>
439void sha_2_digest_message_block(typename HashTraits::state_digest_type& digest,
440 typename HashTraits::message_block_type& message_block,
441 std::uint16_t& stuffed_size) {
442 /*
443 The "sha_2" in the name of this function is in reference to the second generation of SHA
444 algorithms (224, 256, 384, and 512), all of which have the same message block process
445 implementation.
446 */
447
448 typedef HashTraits traits_type;
449 typedef typename traits_type::schedule_type schedule_type;
450 typedef typename traits_type::state_digest_type::value_type digest_value_type;
451
452 schedule_type schedule;
453
454 std::copy(message_block.begin(), message_block.end(), &schedule[0]);
455
456 for (std::size_t t(message_block.size()); t < schedule.size(); ++t)
457 schedule[t] = traits_type::small_sigma_1(schedule[t - 2]) + schedule[t - 7] +
458 traits_type::small_sigma_0(schedule[t - 15]) + schedule[t - 16];
459
460 digest_value_type a(digest[0]);
461 digest_value_type b(digest[1]);
462 digest_value_type c(digest[2]);
463 digest_value_type d(digest[3]);
464 digest_value_type e(digest[4]);
465 digest_value_type f(digest[5]);
466 digest_value_type g(digest[6]);
467 digest_value_type h(digest[7]);
468
469 for (std::size_t t(0); t < schedule.size(); ++t) {
470 digest_value_type T1 = h + traits_type::big_sigma_1(e) + implementation::ch(e, f, g) +
471 traits_type::k(t) + schedule[t];
472 digest_value_type T2 = traits_type::big_sigma_0(a) + implementation::maj(a, b, c);
473 h = g;
474 g = f;
475 f = e;
476 e = d + T1;
477 d = c;
478 c = b;
479 b = a;
480 a = T1 + T2;
481 }
482
483 digest[0] += a;
484 digest[1] += b;
485 digest[2] += c;
486 digest[3] += d;
487 digest[4] += e;
488 digest[5] += f;
489 digest[6] += g;
490 digest[7] += h;
491
492 // clears potentially sensitive information
493 schedule = {{0}};
494
495 // reset the state machine to digest the upcoming block
496 message_block = {{0}};
497 stuffed_size = 0;
498}
499
500/**************************************************************************************************/
501
502struct sha1_traits_t {
503 typedef std::array<std::uint32_t, 5> state_digest_type;
504 typedef std::array<std::uint32_t, 16> message_block_type;
505 typedef std::array<std::uint32_t, 80> schedule_type;
506 typedef state_digest_type digest_type;
507
508 static constexpr std::size_t max_message_bitsize_k = 64;
509 static constexpr std::size_t message_blocksize_k = 512;
510
511 static constexpr state_digest_type initial_state() {
512 return {{0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0}};
513 }
514
515 static inline void digest_message_block(state_digest_type& digest,
516 message_block_type& message_block,
517 std::uint16_t& stuffed_size) {
518 schedule_type schedule;
519 constexpr std::uint_fast8_t schedule_size = static_cast<std::uint_fast8_t>(schedule.size());
520
521 std::memcpy(&schedule[0], &message_block[0], sizeof(message_block_type));
522
523 for (std::size_t t(message_block.size()); t < schedule_size; ++t)
524 schedule[t] = implementation::rotl<1>(schedule[t - 3] ^ schedule[t - 8] ^
525 schedule[t - 14] ^ schedule[t - 16]);
526
527 std::uint32_t a(digest[0]);
528 std::uint32_t b(digest[1]);
529 std::uint32_t c(digest[2]);
530 std::uint32_t d(digest[3]);
531 std::uint32_t e(digest[4]);
532 std::uint32_t T(0);
533
534 // Manually unrolling the loop in this fasion
535 // improves the digest speed by about 20%.
536
537#define A_ROUND(t, F, k) \
538 T = implementation::rotl<5>(a) + F(b, c, d) + e + std::uint32_t(k) + schedule[t]; \
539 e = d; \
540 d = c; \
541 c = implementation::rotl<30>(b); \
542 b = a; \
543 a = T
544
545#define FIVE_ROUNDS(t, F, k) \
546 A_ROUND((t + 0), F, k); \
547 A_ROUND((t + 1), F, k); \
548 A_ROUND((t + 2), F, k); \
549 A_ROUND((t + 3), F, k); \
550 A_ROUND((t + 4), F, k)
551
552#define TWENTY_ROUNDS(t, F, k) \
553 FIVE_ROUNDS((t + 0), F, k); \
554 FIVE_ROUNDS((t + 5), F, k); \
555 FIVE_ROUNDS((t + 10), F, k); \
556 FIVE_ROUNDS((t + 15), F, k)
557
558 TWENTY_ROUNDS(0, implementation::ch, 0x5a827999);
559 TWENTY_ROUNDS(20, implementation::parity, 0x6ed9eba1);
560 TWENTY_ROUNDS(40, implementation::maj, 0x8f1bbcdc);
561 TWENTY_ROUNDS(60, implementation::parity, 0xca62c1d6);
562
563 digest[0] += a;
564 digest[1] += b;
565 digest[2] += c;
566 digest[3] += d;
567 digest[4] += e;
568
569 // clears potentially sensitive information
570 schedule = {{0}};
571
572 // reset the state machine to digest the upcoming block
573 message_block = {{0}};
574 stuffed_size = 0;
575 }
576};
577
578/**************************************************************************************************/
579
580struct sha256_traits_t {
581 typedef std::array<std::uint32_t, 8> state_digest_type;
582 typedef std::array<std::uint32_t, 16> message_block_type;
583 typedef std::array<std::uint32_t, 64> schedule_type;
584 typedef state_digest_type digest_type;
585
586 static constexpr std::size_t max_message_bitsize_k = 64;
587 static constexpr std::size_t message_blocksize_k = 512;
588
589 static constexpr state_digest_type initial_state() {
590 return {{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
591 0x5be0cd19}};
592 }
593
594 static inline void digest_message_block(state_digest_type& digest,
595 message_block_type& message_block,
596 std::uint16_t& stuffed_size) {
597 sha_2_digest_message_block<sha256_traits_t>(digest, message_block, stuffed_size);
598 }
599
600 static inline std::uint32_t big_sigma_0(std::uint32_t x) {
601 return implementation::rotr<2>(x) ^ implementation::rotr<13>(x) ^
602 implementation::rotr<22>(x);
603 }
604
605 static inline std::uint32_t big_sigma_1(std::uint32_t x) {
606 return implementation::rotr<6>(x) ^ implementation::rotr<11>(x) ^
607 implementation::rotr<25>(x);
608 }
609
610 static inline std::uint32_t small_sigma_0(std::uint32_t x) {
611 return implementation::rotr<7>(x) ^ implementation::rotr<18>(x) ^ implementation::shr<3>(x);
612 }
613
614 static inline std::uint32_t small_sigma_1(std::uint32_t x) {
615 return implementation::rotr<17>(x) ^ implementation::rotr<19>(x) ^
616 implementation::shr<10>(x);
617 }
618
619 static inline std::uint32_t k(std::size_t t) {
620 static const std::uint32_t k_set[] = {
621 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4,
622 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,
623 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f,
624 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
625 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
626 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
627 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116,
628 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
629 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
630 0xc67178f2};
631
632 assert(t < 64);
633
634 return k_set[t];
635 }
636};
637
638/**************************************************************************************************/
639
640struct sha224_traits_t : public sha256_traits_t {
641 typedef std::array<std::uint32_t, 7> digest_type;
642
643 static constexpr state_digest_type initial_state() {
644 return {{0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7,
645 0xbefa4fa4}};
646 }
647};
648
649/**************************************************************************************************/
650
651struct sha512_traits_t {
652 typedef std::array<std::uint64_t, 8> state_digest_type;
653 typedef std::array<std::uint64_t, 16> message_block_type;
654 typedef std::array<std::uint64_t, 80> schedule_type;
655 typedef state_digest_type digest_type;
656
657 static constexpr std::size_t max_message_bitsize_k = 128;
658 static constexpr std::size_t message_blocksize_k = 1024;
659
660 static constexpr state_digest_type initial_state() {
661 return {{0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
662 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
663 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL}};
664 }
665
666 static inline void digest_message_block(state_digest_type& digest,
667 message_block_type& message_block,
668 std::uint16_t& stuffed_size) {
669 sha_2_digest_message_block<sha512_traits_t>(digest, message_block, stuffed_size);
670 }
671
672 static inline std::uint64_t big_sigma_0(std::uint64_t x) {
673 return implementation::rotr<28>(x) ^ implementation::rotr<34>(x) ^
674 implementation::rotr<39>(x);
675 }
676
677 static inline std::uint64_t big_sigma_1(std::uint64_t x) {
678 return implementation::rotr<14>(x) ^ implementation::rotr<18>(x) ^
679 implementation::rotr<41>(x);
680 }
681
682 static inline std::uint64_t small_sigma_0(std::uint64_t x) {
683 return implementation::rotr<1>(x) ^ implementation::rotr<8>(x) ^ implementation::shr<7>(x);
684 }
685
686 static inline std::uint64_t small_sigma_1(std::uint64_t x) {
687 return implementation::rotr<19>(x) ^ implementation::rotr<61>(x) ^
688 implementation::shr<6>(x);
689 }
690
691 static inline std::uint64_t k(std::size_t t) {
692 static const std::uint64_t k_set[] = {
693 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
694 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
695 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
696 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
697 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
698 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
699 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
700 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
701 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
702 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
703 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
704 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
705 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
706 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
707 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
708 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
709 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
710 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
711 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
712 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
713 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
714 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
715 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
716 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
717 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
718 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
719 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
720
721 assert(t < 80);
722
723 return k_set[t];
724 }
725};
726
727/**************************************************************************************************/
728
729struct sha384_traits_t : public sha512_traits_t {
730 typedef std::array<std::uint64_t, 6> digest_type;
731
732 static constexpr state_digest_type initial_state() {
733 return {{0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL,
734 0x152fecd8f70e5939ULL, 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
735 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL}};
736 }
737};
738
739/**************************************************************************************************/
740
741#endif
742
743/**************************************************************************************************/
744
745} // namespace implementation
746
747/**************************************************************************************************/
763template <class Traits>
764class sha {
765public:
766#if !defined(ADOBE_NO_DOCUMENTATION)
767 typedef Traits traits_type;
768#endif
769
778 typedef typename traits_type::digest_type digest_type;
779
786 : message_size_m(0), state_m({{0}}), state_digest_m(traits_type::initial_state()),
787 stuffed_size_m(0) {}
788
807 template <typename I>
808 inline void update(I first, I last) {
809 // We can only update if the current state is byte aligned
810 assert(stuffed_size_m % 8 == 0);
811
812 implementation::byte_source_iterators<I> byte_source(first, last);
813 implementation::block_and_digest<traits_type>(state_m, stuffed_size_m, message_size_m,
814 state_digest_m, byte_source);
815 }
816
835 template <typename I>
836 inline void update(I first, std::uint64_t num_bits) {
837 // We can only update if the current state is byte aligned
838 assert(stuffed_size_m % 8 == 0);
839
840 implementation::byte_source_iterator_n<I> byte_source(first, num_bits);
841 implementation::block_and_digest<traits_type>(state_m, stuffed_size_m, message_size_m,
842 state_digest_m, byte_source);
843 }
844
851 std::uint64_t message_size(message_size_m);
852 typename traits_type::message_block_type state(state_m);
853 typename traits_type::state_digest_type state_digest(state_digest_m);
854 std::uint16_t stuffed_size(stuffed_size_m);
855
856 return implementation::finalize<traits_type>(state, stuffed_size, message_size,
857 state_digest);
858 }
859
875 template <typename I>
876 static inline digest_type digest(I first, I last) {
877 sha instance;
878
879 instance.update(first, last);
880
881 return instance.finalize();
882 }
883
898 template <typename I>
899 static inline digest_type digest(I first, std::uint64_t num_bits) {
900 sha instance;
901
902 instance.update(first, num_bits);
903
904 return instance.finalize();
905 }
906
914 static std::string to_string(const typename traits_type::digest_type& digest,
915 bool spaces = false) {
916 typedef typename traits_type::digest_type::value_type value_type;
917
918 constexpr const char* lut_k = "0123456789abcdef";
919 constexpr std::size_t size_k = sizeof(value_type);
920 constexpr std::size_t bitsize_k = implementation::bitsizeof<value_type>();
921
922 bool first(true);
923 std::string result;
924
925 for (const auto& element : digest) {
926 if (!first && spaces)
927 result += ' ';
928
929 first = false;
930
931 for (std::size_t i(0); i < size_k; ++i) {
932 // shifting instead of a char* pointer walk avoids endian issues
933 char c((element >> (bitsize_k - (i + 1) * 8)) & 0xff);
934 char hi(lut_k[(c >> 4) & 0xf]);
935 char lo(lut_k[c & 0xf]);
936
937 result += hi;
938 result += lo;
939 }
940 }
941
942 return result;
943 }
944
945 inline std::string to_string(bool spaces = false) { return to_string(finalize(), spaces); }
946
947#ifndef ADOBE_NO_DOCUMENTATION
948private:
949 // ordered to try and maximize fastest cache alignment. This
950 // could be improved.
951 std::uint64_t message_size_m;
952 typename traits_type::message_block_type state_m;
953 typename traits_type::state_digest_type state_digest_m;
954 std::uint16_t stuffed_size_m;
955#endif
956};
957
958/**************************************************************************************************/
959
965
967
973
975
981
983
989
991
997
999
1000/**************************************************************************************************/
1001
1002} // namespace adobe
1003
1004/**************************************************************************************************/
1005
1006#endif
1007
1008/**************************************************************************************************/
#define ADOBE_ASSERT(p)
Definition cassert.hpp:32
static std::string to_string(const typename traits_type::digest_type &digest, bool spaces=false)
Definition sha.hpp:914
Traits traits_type
Definition sha.hpp:767
std::string to_string(bool spaces=false)
Definition sha.hpp:945
std::tuple_element< I, T > element
Deprecated, use std::tuple_element instead.
sha< implementation::sha256_traits_t > sha256_t
A bit-oriented implementation of the SHA-256 Secure Hash Algorithm.
Definition sha.hpp:982
void update(I first, std::uint64_t num_bits)
Definition sha.hpp:836
digest_type finalize()
Definition sha.hpp:850
sha< implementation::sha512_traits_t > sha512_t
A bit-oriented implementation of the SHA-512 Secure Hash Algorithm.
Definition sha.hpp:998
static digest_type digest(I first, std::uint64_t num_bits)
Definition sha.hpp:899
sha< implementation::sha1_traits_t > sha1_t
A bit-oriented implementation of the SHA-1 Secure Hash Algorithm.
Definition sha.hpp:966
traits_type::digest_type digest_type
Definition sha.hpp:778
static digest_type digest(I first, I last)
Definition sha.hpp:876
sha< implementation::sha384_traits_t > sha384_t
A bit-oriented implementation of the SHA-384 Secure Hash Algorithm.
Definition sha.hpp:990
void update(I first, I last)
Definition sha.hpp:808
sha< implementation::sha224_traits_t > sha224_t
A bit-oriented implementation of the SHA-224 Secure Hash Algorithm.
Definition sha.hpp:974
#define TWENTY_ROUNDS(t, F, k)