25 namespace implementation {
29 #if !defined(ADOBE_NO_DOCUMENTATION)
34 constexpr std::size_t bitsizeof() {
40 template <std::
size_t N,
typename T>
42 static_assert(N < bitsizeof<T>(),
"shr size mismatch.");
47 template <std::
size_t N,
typename T>
49 static_assert(N < bitsizeof<T>(),
"rotr size mismatch.");
51 constexpr std::size_t l_shift = bitsizeof<T>() - N;
53 return (x >> N) | (x << l_shift);
56 template <std::
size_t N,
typename T>
58 static_assert(N < bitsizeof<T>(),
"rotl size mismatch.");
60 constexpr std::size_t r_shift = bitsizeof<T>() - N;
62 return (x << N) | (x >> r_shift);
68 inline T ch(T x, T y, T z) {
69 return (x & y) ^ (~x & z);
73 inline T parity(T x, T y, T z) {
78 inline T maj(T x, T y, T z) {
79 return (x & y) ^ (x & z) ^ (y & z);
88 class byte_source_iterators
91 byte_source_iterators( I
const& first, I
const& last )
94 static_assert(
sizeof(
typename std::iterator_traits<I>::value_type) ==
sizeof(std::uint8_t),
"Iterator must supply bytes.");
102 std::size_t bits_available()
const {
103 return ( first_ == last_ ) ? 0 : 8;
106 std::uint8_t operator *()
const {
111 byte_source_iterators& operator ++() {
121 byte_source_iterators( byte_source_iterators
const& ) =
delete;
122 byte_source_iterators& operator =( byte_source_iterators
const& ) =
delete;
135 template <
typename I>
136 class byte_source_iterator_n
139 byte_source_iterator_n( I
const& first, std::size_t num_bits )
141 , num_bits_( num_bits ) {
142 static_assert(
sizeof(
typename std::iterator_traits<I>::value_type) ==
sizeof(std::uint8_t),
"Iterator must supply bytes.");
146 std::size_t bits_available()
const {
147 return ( num_bits_ > 8 ) ? 8 : num_bits_;
150 std::uint8_t operator *()
const {
155 byte_source_iterator_n& operator ++() {
157 num_bits_ -= bits_available();
166 byte_source_iterator_n( byte_source_iterator_n
const& ) =
delete;
167 byte_source_iterator_n& operator =( byte_source_iterator_n
const& ) =
delete;
172 std::size_t num_bits_;
177 template <
typename HashTraits,
typename ByteSource>
178 std::uint64_t stuff_into_state(
typename HashTraits::message_block_type& state,
179 std::uint16_t& stuff_bit_offset, std::size_t num_bits,
180 ByteSource& byte_source) {
182 typedef HashTraits traits_type;
183 typedef typename traits_type::message_block_type::value_type value_type;
185 constexpr std::size_t value_size_k =
sizeof(value_type);
186 constexpr std::size_t value_bitsize_k = value_size_k * 8;
199 std::size_t element = stuff_bit_offset / value_bitsize_k;
200 std::size_t shift = value_bitsize_k - 8 -
201 stuff_bit_offset % value_bitsize_k;
202 value_type* dst(&state[element]);
210 std::uint64_t n_stuffed_bits = 0;
212 while (num_bits >= 8 && byte_source.bits_available() >= 8) {
213 *dst |= (value_type(*byte_source) & value_type(0xff)) << shift;
220 shift = value_bitsize_k - 8;
225 stuff_bit_offset += 8;
231 if (num_bits && byte_source.bits_available()) {
232 num_bits = std::min(num_bits, byte_source.bits_available());
243 std::size_t message_end(value_bitsize_k - (stuff_bit_offset % value_bitsize_k));
244 value_type v(*byte_source & 0xff);
249 v >>= 8 - message_end;
250 else if (message_end > 8)
251 v <<= message_end - 8;
254 stuff_bit_offset += num_bits;
255 n_stuffed_bits += num_bits;
257 return n_stuffed_bits;
274 template <
typename HashTraits,
typename ByteSource>
275 void block_and_digest(
typename HashTraits::message_block_type& state, std::uint16_t& stuffed_size,
276 std::uint64_t& message_size,
typename HashTraits::state_digest_type& digest,
277 ByteSource& byte_source ) {
278 typedef HashTraits traits_type;
281 constexpr std::size_t message_blocksize_k = traits_type::message_blocksize_k;
304 std::size_t bits_available(message_blocksize_k - stuffed_size);
306 while (byte_source.bits_available() > 0) {
307 std::uint64_t
const bits_stuffed = stuff_into_state<traits_type>(state, stuffed_size, bits_available, byte_source);
310 if( bits_stuffed == bits_available ) {
311 traits_type::digest_message_block(digest, state, stuffed_size);
314 message_size += bits_stuffed;
315 bits_available = message_blocksize_k;
321 template <
typename HashTraits>
322 typename HashTraits::digest_type finalize(
typename HashTraits::message_block_type& state,
323 std::uint16_t stuffed_size, std::uint64_t message_size,
324 typename HashTraits::state_digest_type& digest) {
336 typedef HashTraits traits_type;
337 typedef typename traits_type::message_block_type message_block_type;
338 typedef typename message_block_type::value_type value_type;
341 constexpr std::size_t max_message_bitsize_k = traits_type::max_message_bitsize_k;
343 constexpr std::size_t message_blocksize_k = traits_type::message_blocksize_k;
345 constexpr std::size_t value_size_k =
sizeof(value_type);
346 constexpr std::size_t value_bitsize_k = value_size_k * 8;
353 std::uint8_t one_bit(0x80);
354 std::uint8_t* one_bit_ptr(&one_bit);
356 byte_source_iterator_n< std::uint8_t* > bit_source( one_bit_ptr, 1 );
357 stuff_into_state<traits_type>(state, stuffed_size, 1, bit_source);
364 if (stuffed_size == message_blocksize_k)
365 traits_type::digest_message_block(digest, state, stuffed_size);
374 constexpr std::size_t length_offset(message_blocksize_k - max_message_bitsize_k);
385 if (stuffed_size > length_offset)
386 traits_type::digest_message_block(digest, state, stuffed_size);
388 constexpr value_type value_type_mask =
static_cast<value_type
>(-1);
402 constexpr
bool overshift = value_bitsize_k >= (
sizeof(message_size) * 8);
404 if (!overshift && message_size > value_type_mask)
405 state[14] = (message_size >> value_bitsize_k) & value_type_mask;
407 state[15] = message_size & value_type_mask;
410 traits_type::digest_message_block(digest, state, stuffed_size);
417 typedef typename HashTraits::digest_type digest_type;
419 digest_type result = {{0}};
421 std::memcpy(&result[0], &digest[0],
sizeof(digest_type));
428 template <
typename HashTraits>
429 void sha_2_digest_message_block(
typename HashTraits::state_digest_type& digest,
430 typename HashTraits::message_block_type& message_block,
431 std::uint16_t& stuffed_size) {
438 typedef HashTraits traits_type;
439 typedef typename traits_type::message_block_type message_block_type;
440 typedef typename traits_type::schedule_type schedule_type;
441 typedef typename traits_type::state_digest_type::value_type digest_value_type;
443 schedule_type schedule;
445 std::copy(message_block.begin(), message_block.end(), &schedule[0]);
447 for (std::size_t t(message_block.size()); t < schedule.size(); ++t)
448 schedule[t] = traits_type::small_sigma_1(schedule[t - 2]) + schedule[t - 7] +
449 traits_type::small_sigma_0(schedule[t - 15]) + schedule[t - 16];
451 digest_value_type a(digest[0]);
452 digest_value_type b(digest[1]);
453 digest_value_type c(digest[2]);
454 digest_value_type d(digest[3]);
455 digest_value_type e(digest[4]);
456 digest_value_type f(digest[5]);
457 digest_value_type g(digest[6]);
458 digest_value_type h(digest[7]);
460 for (std::size_t t(0); t < schedule.size(); ++t) {
461 digest_value_type T1 = h + traits_type::big_sigma_1(e) + implementation::ch(e, f, g) +
462 traits_type::k(t) + schedule[t];
463 digest_value_type T2 = traits_type::big_sigma_0(a) + implementation::maj(a, b, c);
487 message_block = {{0}};
493 struct sha1_traits_t {
494 typedef std::array<std::uint32_t, 5> state_digest_type;
495 typedef std::array<std::uint32_t, 16> message_block_type;
496 typedef std::array<std::uint32_t, 80> schedule_type;
497 typedef state_digest_type digest_type;
499 static constexpr std::size_t max_message_bitsize_k = 64;
500 static constexpr std::size_t message_blocksize_k = 512;
502 static constexpr state_digest_type initial_state() {
503 return {{0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0}};
506 static inline void digest_message_block(state_digest_type& digest,
507 message_block_type& message_block,
508 std::uint16_t& stuffed_size) {
509 typedef typename schedule_type::value_type schedule_word;
511 schedule_type schedule;
512 constexpr std::uint_fast8_t schedule_size = schedule.size();
514 std::memcpy(&schedule[0], &message_block[0],
sizeof(message_block_type));
516 for (std::size_t t(message_block.size()); t < schedule_size; ++t)
517 schedule[t] = implementation::rotl<1>(schedule[t - 3] ^ schedule[t - 8] ^
518 schedule[t - 14] ^ schedule[t - 16]);
520 std::uint32_t a(digest[0]);
521 std::uint32_t b(digest[1]);
522 std::uint32_t c(digest[2]);
523 std::uint32_t d(digest[3]);
524 std::uint32_t e(digest[4]);
530 #define A_ROUND(t, F, k) \
531 T = implementation::rotl<5>(a) + F(b, c, d) + e + std::uint32_t(k) + schedule[t]; \
534 c = implementation::rotl<30>(b); \
538 #define FIVE_ROUNDS(t, F, k) \
539 A_ROUND((t + 0), F, k); \
540 A_ROUND((t + 1), F, k); \
541 A_ROUND((t + 2), F, k); \
542 A_ROUND((t + 3), F, k); \
543 A_ROUND((t + 4), F, k)
545 #define TWENTY_ROUNDS(t, F, k) \
546 FIVE_ROUNDS((t + 0), F, k); \
547 FIVE_ROUNDS((t + 5), F, k); \
548 FIVE_ROUNDS((t + 10), F, k); \
549 FIVE_ROUNDS((t + 15), F, k)
551 TWENTY_ROUNDS(0, implementation::ch, 0x5a827999);
552 TWENTY_ROUNDS(20, implementation::parity, 0x6ed9eba1);
553 TWENTY_ROUNDS(40, implementation::maj, 0x8f1bbcdc);
554 TWENTY_ROUNDS(60, implementation::parity, 0xca62c1d6);
566 message_block = {{0}};
573 struct sha256_traits_t {
574 typedef std::array<std::uint32_t, 8> state_digest_type;
575 typedef std::array<std::uint32_t, 16> message_block_type;
576 typedef std::array<std::uint32_t, 64> schedule_type;
577 typedef state_digest_type digest_type;
579 static constexpr std::size_t max_message_bitsize_k = 64;
580 static constexpr std::size_t message_blocksize_k = 512;
582 static constexpr state_digest_type initial_state() {
583 return {{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
584 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}};
587 static inline void digest_message_block(state_digest_type& digest,
588 message_block_type& message_block,
589 std::uint16_t& stuffed_size) {
590 sha_2_digest_message_block<sha256_traits_t>(digest, message_block, stuffed_size);
593 static inline std::uint32_t big_sigma_0(std::uint32_t x) {
594 return implementation::rotr<2>(x) ^ implementation::rotr<13>(x) ^
595 implementation::rotr<22>(x);
598 static inline std::uint32_t big_sigma_1(std::uint32_t x) {
599 return implementation::rotr<6>(x) ^ implementation::rotr<11>(x) ^
600 implementation::rotr<25>(x);
603 static inline std::uint32_t small_sigma_0(std::uint32_t x) {
604 return implementation::rotr<7>(x) ^ implementation::rotr<18>(x) ^ implementation::shr<3>(x);
607 static inline std::uint32_t small_sigma_1(std::uint32_t x) {
608 return implementation::rotr<17>(x) ^ implementation::rotr<19>(x) ^
609 implementation::shr<10>(x);
612 static inline std::uint32_t k(std::size_t t) {
613 static const std::uint32_t k_set[] = {
614 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4,
615 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,
616 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f,
617 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
618 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
619 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
620 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116,
621 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
622 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
633 struct sha224_traits_t :
public sha256_traits_t {
634 typedef std::array<std::uint32_t, 7> digest_type;
636 static constexpr state_digest_type initial_state() {
637 return {{0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
638 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}};
644 struct sha512_traits_t {
645 typedef std::array<std::uint64_t, 8> state_digest_type;
646 typedef std::array<std::uint64_t, 16> message_block_type;
647 typedef std::array<std::uint64_t, 80> schedule_type;
648 typedef state_digest_type digest_type;
650 static constexpr std::size_t max_message_bitsize_k = 128;
651 static constexpr std::size_t message_blocksize_k = 1024;
653 static constexpr state_digest_type initial_state() {
654 return {{0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
655 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
656 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL}};
659 static inline void digest_message_block(state_digest_type& digest,
660 message_block_type& message_block,
661 std::uint16_t& stuffed_size) {
662 sha_2_digest_message_block<sha512_traits_t>(digest, message_block, stuffed_size);
665 static inline std::uint64_t big_sigma_0(std::uint64_t x) {
666 return implementation::rotr<28>(x) ^ implementation::rotr<34>(x) ^
667 implementation::rotr<39>(x);
670 static inline std::uint64_t big_sigma_1(std::uint64_t x) {
671 return implementation::rotr<14>(x) ^ implementation::rotr<18>(x) ^
672 implementation::rotr<41>(x);
675 static inline std::uint64_t small_sigma_0(std::uint64_t x) {
676 return implementation::rotr<1>(x) ^ implementation::rotr<8>(x) ^ implementation::shr<7>(x);
679 static inline std::uint64_t small_sigma_1(std::uint64_t x) {
680 return implementation::rotr<19>(x) ^ implementation::rotr<61>(x) ^
681 implementation::shr<6>(x);
684 static inline std::uint64_t k(std::size_t t) {
685 static const std::uint64_t k_set[] = {
686 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
687 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
688 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
689 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
690 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
691 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
692 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
693 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
694 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
695 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
696 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
697 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
698 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
699 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
700 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
701 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
702 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
703 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
704 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
705 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
706 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
707 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
708 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
709 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
710 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
711 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
712 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
722 struct sha384_traits_t :
public sha512_traits_t {
723 typedef std::array<std::uint64_t, 6> digest_type;
725 static constexpr state_digest_type initial_state() {
726 return {{0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL,
727 0x152fecd8f70e5939ULL, 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
728 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL}};
756 template <
class Traits>
759 #if !defined(ADOBE_NO_DOCUMENTATION)
760 typedef Traits traits_type;
779 : message_size_m(0), state_m({{0}}), state_digest_m(traits_type::initial_state()),
800 template <
typename I>
803 assert(stuffed_size_m % 8 == 0);
805 implementation::byte_source_iterators< I > byte_source(first, last);
806 implementation::block_and_digest<traits_type>(state_m, stuffed_size_m, message_size_m,
807 state_digest_m, byte_source);
828 template <
typename I>
829 inline void update(I first, std::uint64_t num_bits) {
831 assert(stuffed_size_m % 8 == 0);
833 implementation::byte_source_iterator_n< I > byte_source(first, num_bits);
834 implementation::block_and_digest<traits_type>(state_m, stuffed_size_m, message_size_m,
835 state_digest_m, byte_source);
844 std::uint64_t message_size(message_size_m);
845 typename traits_type::message_block_type state(state_m);
846 typename traits_type::state_digest_type state_digest(state_digest_m);
847 std::uint16_t stuffed_size(stuffed_size_m);
849 return implementation::finalize<traits_type>(state, stuffed_size, message_size,
868 template <
typename I>
869 static inline digest_type
digest(I first, I last) {
872 instance.
update(first, last);
891 template <
typename I>
892 static inline digest_type
digest(I first, std::uint64_t num_bits) {
895 instance.
update(first, num_bits);
908 bool spaces =
false) {
909 typedef typename traits_type::digest_type::value_type value_type;
911 constexpr
const char* lut_k =
"0123456789abcdef";
912 constexpr std::size_t size_k =
sizeof(value_type);
913 constexpr std::size_t bitsize_k = implementation::bitsizeof<value_type>();
918 for (
const auto& element : digest) {
919 if (!first && spaces)
924 for (std::size_t i(0); i < size_k; ++i) {
926 char c((element >> (bitsize_k - (i + 1) * 8)) & 0xff);
927 char hi(lut_k[(c >> 4) & 0xf]);
928 char lo(lut_k[c & 0xf]);
940 #ifndef ADOBE_NO_DOCUMENTATION
944 std::uint64_t message_size_m;
945 typename traits_type::message_block_type state_m;
946 typename traits_type::state_digest_type state_digest_m;
947 std::uint16_t stuffed_size_m;
static std::string to_string(const typename traits_type::digest_type &digest, bool spaces=false)
sha< implementation::sha384_traits_t > sha384_t
A bit-oriented implementation of the SHA-384 Secure Hash Algorithm.
void update(I first, std::uint64_t num_bits)
sha< implementation::sha224_traits_t > sha224_t
A bit-oriented implementation of the SHA-224 Secure Hash Algorithm.
traits_type::digest_type digest_type
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.
std::string to_string(bool spaces=false)
void update(I first, I last)
sha< implementation::sha512_traits_t > sha512_t
A bit-oriented implementation of the SHA-512 Secure Hash Algorithm.
sha< implementation::sha256_traits_t > sha256_t
A bit-oriented implementation of the SHA-256 Secure Hash Algorithm.
static digest_type digest(I first, I last)