28namespace implementation {
32#if !defined(ADOBE_NO_DOCUMENTATION)
37constexpr std::size_t bitsizeof() {
43template <std::
size_t N,
typename T>
45 static_assert(N < bitsizeof<T>(),
"shr size mismatch.");
50template <std::
size_t N,
typename T>
52 static_assert(N < bitsizeof<T>(),
"rotr size mismatch.");
54 constexpr std::size_t l_shift = bitsizeof<T>() - N;
56 return (x >> N) | (x << l_shift);
59template <std::
size_t N,
typename T>
61 static_assert(N < bitsizeof<T>(),
"rotl size mismatch.");
63 constexpr std::size_t r_shift = bitsizeof<T>() - N;
65 return (x << N) | (x >> r_shift);
71inline T ch(T x, T y, T z) {
72 return (x & y) ^ (~x & z);
76inline T parity(T x, T y, T z) {
81inline T maj(T x, T y, T z) {
82 return (x & y) ^ (x & z) ^ (y & z);
91class byte_source_iterators {
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.");
103 std::uint64_t bits_available()
const {
return (first_ == last_) ? 0 : 8; }
105 std::uint8_t operator*()
const {
return *first_; }
108 byte_source_iterators& operator++() {
118 byte_source_iterators(byte_source_iterators
const&) =
delete;
119 byte_source_iterators& operator=(byte_source_iterators
const&) =
delete;
132class byte_source_iterator_n {
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.");
141 std::uint64_t bits_available()
const {
return (num_bits_ > 8u) ? 8u : num_bits_; }
143 std::uint8_t operator*()
const {
return *first_; }
146 byte_source_iterator_n& operator++() {
148 num_bits_ -= bits_available();
157 byte_source_iterator_n(byte_source_iterator_n
const&) =
delete;
158 byte_source_iterator_n& operator=(byte_source_iterator_n
const&) =
delete;
162 std::uint64_t num_bits_;
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) {
172 typedef HashTraits traits_type;
173 typedef typename traits_type::message_block_type::value_type value_type;
175 constexpr std::size_t value_size_k =
sizeof(value_type);
176 constexpr std::size_t value_bitsize_k = value_size_k * 8;
189 std::size_t
element = stuff_bit_offset / value_bitsize_k;
190 std::size_t shift = value_bitsize_k - 8 -
191 stuff_bit_offset % value_bitsize_k;
192 value_type* dst(&state[
element]);
200 std::uint64_t n_stuffed_bits = 0;
202 while (num_bits >= 8 && byte_source.bits_available() >= 8) {
203 *dst |= (value_type(*byte_source) & value_type(0xff)) << shift;
210 shift = value_bitsize_k - 8;
215 stuff_bit_offset += 8;
221 if (num_bits && byte_source.bits_available()) {
222 num_bits = std::min(num_bits, byte_source.bits_available());
233 std::size_t message_end(value_bitsize_k - (stuff_bit_offset % value_bitsize_k));
234 value_type v(*byte_source & 0xff);
239 v >>= 8 - message_end;
240 else if (message_end > 8)
241 v <<= message_end - 8;
245 stuff_bit_offset +=
static_cast<std::uint16_t
>(num_bits);
246 n_stuffed_bits +=
static_cast<std::uint16_t
>(num_bits);
248 return n_stuffed_bits;
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;
272 constexpr std::size_t message_blocksize_k = traits_type::message_blocksize_k;
295 std::size_t bits_available(message_blocksize_k - stuffed_size);
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);
302 if (bits_stuffed == bits_available) {
303 traits_type::digest_message_block(digest, state, stuffed_size);
306 message_size += bits_stuffed;
307 bits_available = message_blocksize_k;
313template <
bool overshift,
typename message_block_type>
315 void operator()(message_block_type&, std::uint64_t,
316 typename message_block_type::value_type)
const {}
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;
325 if (message_size > value_type_mask) {
326 state[14] = (message_size >> value_bitsize_k) & value_type_mask;
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) {
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;
353 constexpr std::size_t max_message_bitsize_k = traits_type::max_message_bitsize_k;
355 constexpr std::size_t message_blocksize_k = traits_type::message_blocksize_k;
357 constexpr std::size_t value_size_k =
sizeof(value_type);
358 constexpr std::size_t value_bitsize_k = value_size_k * 8;
365 std::uint8_t one_bit(0x80);
366 std::uint8_t* one_bit_ptr(&one_bit);
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);
376 if (stuffed_size == message_blocksize_k)
377 traits_type::digest_message_block(digest, state, stuffed_size);
386 constexpr std::size_t length_offset(message_blocksize_k - max_message_bitsize_k);
397 if (stuffed_size > length_offset)
398 traits_type::digest_message_block(digest, state, stuffed_size);
400 constexpr value_type value_type_mask =
static_cast<value_type
>(-1);
414 constexpr bool overshift = value_bitsize_k >= (
sizeof(message_size) * 8);
415 shift_down<overshift, message_block_type>()(state, message_size, value_type_mask);
417 state[15] = message_size & value_type_mask;
420 traits_type::digest_message_block(digest, state, stuffed_size);
427 typedef typename HashTraits::digest_type digest_type;
429 digest_type result = {{0}};
431 std::memcpy(&result[0], &digest[0],
sizeof(digest_type));
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) {
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;
452 schedule_type schedule;
454 std::copy(message_block.begin(), message_block.end(), &schedule[0]);
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];
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]);
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);
496 message_block = {{0}};
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;
508 static constexpr std::size_t max_message_bitsize_k = 64;
509 static constexpr std::size_t message_blocksize_k = 512;
511 static constexpr state_digest_type initial_state() {
512 return {{0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0}};
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());
521 std::memcpy(&schedule[0], &message_block[0],
sizeof(message_block_type));
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]);
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]);
537#define A_ROUND(t, F, k) \
538 T = implementation::rotl<5>(a) + F(b, c, d) + e + std::uint32_t(k) + schedule[t]; \
541 c = implementation::rotl<30>(b); \
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)
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)
573 message_block = {{0}};
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;
586 static constexpr std::size_t max_message_bitsize_k = 64;
587 static constexpr std::size_t message_blocksize_k = 512;
589 static constexpr state_digest_type initial_state() {
590 return {{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
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);
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);
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);
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);
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);
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,
640struct sha224_traits_t :
public sha256_traits_t {
641 typedef std::array<std::uint32_t, 7> digest_type;
643 static constexpr state_digest_type initial_state() {
644 return {{0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7,
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;
657 static constexpr std::size_t max_message_bitsize_k = 128;
658 static constexpr std::size_t message_blocksize_k = 1024;
660 static constexpr state_digest_type initial_state() {
661 return {{0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
662 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
663 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL}};
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);
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);
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);
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);
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);
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};
729struct sha384_traits_t :
public sha512_traits_t {
730 typedef std::array<std::uint64_t, 6> digest_type;
732 static constexpr state_digest_type initial_state() {
733 return {{0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL,
734 0x152fecd8f70e5939ULL, 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
735 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL}};
763template <
class Traits>
766#if !defined(ADOBE_NO_DOCUMENTATION)
786 : message_size_m(0), state_m({{0}}), state_digest_m(traits_type::initial_state()),
807 template <
typename I>
810 assert(stuffed_size_m % 8 == 0);
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);
835 template <
typename I>
836 inline void update(I first, std::uint64_t num_bits) {
838 assert(stuffed_size_m % 8 == 0);
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);
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);
856 return implementation::finalize<traits_type>(state, stuffed_size, message_size,
875 template <
typename I>
879 instance.
update(first, last);
898 template <
typename I>
902 instance.
update(first, num_bits);
915 bool spaces =
false) {
916 typedef typename traits_type::digest_type::value_type value_type;
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>();
926 if (!first && spaces)
931 for (std::size_t i(0); i < size_k; ++i) {
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]);
947#ifndef ADOBE_NO_DOCUMENTATION
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;
static std::string to_string(const typename traits_type::digest_type &digest, bool spaces=false)
std::string to_string(bool spaces=false)
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.
void update(I first, std::uint64_t num_bits)
sha< implementation::sha512_traits_t > sha512_t
A bit-oriented implementation of the SHA-512 Secure Hash Algorithm.
static digest_type digest(I first, std::uint64_t num_bits)
sha< implementation::sha1_traits_t > sha1_t
A bit-oriented implementation of the SHA-1 Secure Hash Algorithm.
traits_type::digest_type digest_type
static digest_type digest(I first, I last)
sha< implementation::sha384_traits_t > sha384_t
A bit-oriented implementation of the SHA-384 Secure Hash Algorithm.
void update(I first, I last)
sha< implementation::sha224_traits_t > sha224_t
A bit-oriented implementation of the SHA-224 Secure Hash Algorithm.
#define TWENTY_ROUNDS(t, F, k)