sha.hpp
Go to the documentation of this file.
00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 00004 or a copy at http://stlab.adobe.com/licenses.html) 00005 */ 00006 00007 /*************************************************************************************************/ 00008 00009 #ifndef ADOBE_SHA_HPP 00010 #define ADOBE_SHA_HPP 00011 00012 /*************************************************************************************************/ 00013 00014 #include <adobe/config.hpp> 00015 00016 #include <boost/array.hpp> 00017 #include <boost/cstdint.hpp> 00018 #include <boost/static_assert.hpp> 00019 00020 #include <stdexcept> 00021 #include <limits> 00022 #include <cstring> 00023 00024 /*************************************************************************************************/ 00025 00026 namespace adobe { 00027 00222 /*************************************************************************************************/ 00223 00224 class sha1_t; 00225 class sha224_t; 00226 class sha256_t; 00227 class sha384_t; 00228 class sha512_t; 00229 00230 /*************************************************************************************************/ 00231 00232 namespace implementation { 00233 00234 /*************************************************************************************************/ 00235 00236 #if !defined(ADOBE_NO_DOCUMENTATION) 00237 00238 /*************************************************************************************************/ 00239 00240 template <typename HashT> 00241 struct sha_traits; 00242 00243 /*************************************************************************************************/ 00244 00245 template <typename I> // I models InputIterator 00246 inline boost::uint64_t long_distance(I first, I last) 00247 { 00248 boost::uint64_t result(0); 00249 00250 while (first != last) 00251 { 00252 ++result; 00253 00254 ++first; 00255 } 00256 00257 return result; 00258 } 00259 00260 /*************************************************************************************************/ 00261 00262 template <typename I> // I models InputIterator 00263 struct bit_packer 00264 { 00265 typedef typename std::iterator_traits<I>::value_type value_type; 00266 00267 BOOST_STATIC_ASSERT((sizeof(value_type) == 1)); 00268 00269 bit_packer(I first, I last) : 00270 first_m(first), bitsize_m(long_distance(first, last)) 00271 { } 00272 00273 bit_packer(I first, boost::uint64_t bitsize) : 00274 first_m(first), bitsize_m(bitsize) 00275 { } 00276 00277 template <typename T> 00278 inline std::size_t operator () (T& result) 00279 { return byte_pack(result); } 00280 00281 private: 00282 template <typename T> 00283 std::size_t byte_pack(T& result) 00284 { 00285 std::size_t to_pack(sizeof(T)); 00286 00287 result = 0; 00288 00289 while (to_pack != 0 && bitsize_m != 0) 00290 { 00291 std::size_t shift_count(8 * (to_pack - 1)); 00292 T mask(T(255) << shift_count); 00293 00294 result |= (T(*first_m) << shift_count) & mask; 00295 00296 if (bitsize_m >= 8) 00297 { 00298 bitsize_m -= 8; 00299 } 00300 else 00301 { 00302 std::size_t remaining(static_cast<std::size_t>(to_pack * 8 - bitsize_m)); 00303 00304 bitsize_m = 0; 00305 00306 return remaining; 00307 } 00308 00309 ++first_m; 00310 --to_pack; 00311 } 00312 00313 return to_pack * 8; 00314 } 00315 00316 I first_m; 00317 boost::uint64_t bitsize_m; 00318 }; 00319 00320 /*************************************************************************************************/ 00321 00322 template <typename T> 00323 struct bitsizeof 00324 { enum { value = sizeof(T) * 8 }; }; 00325 00326 /*************************************************************************************************/ 00327 00328 template <std::size_t N, typename T> 00329 inline T shr(const T& x) 00330 { 00331 BOOST_STATIC_ASSERT((N < bitsizeof<T>::value)); 00332 00333 return x >> N; 00334 } 00335 00336 template <std::size_t N, typename T> 00337 inline T rotr(const T& x) 00338 { 00339 BOOST_STATIC_ASSERT((N < bitsizeof<T>::value)); 00340 00341 enum { l_shift = bitsizeof<T>::value - N }; 00342 00343 return (x >> N) | (x << l_shift); 00344 } 00345 00346 template <std::size_t N, typename T> 00347 inline T rotl(const T& x) 00348 { 00349 BOOST_STATIC_ASSERT((N < bitsizeof<T>::value)); 00350 00351 enum { r_shift = bitsizeof<T>::value - N }; 00352 00353 return (x << N) | (x >> r_shift); 00354 } 00355 00356 /*************************************************************************************************/ 00357 00358 template <typename T> 00359 inline T ch(T x, T y, T z) 00360 { return (x & y) ^ (~x & z); } 00361 00362 template <typename T> 00363 inline T parity(T x, T y, T z) 00364 { return x ^ y ^ z; } 00365 00366 template <typename T> 00367 inline T maj(T x, T y, T z) 00368 { return (x & y) ^ (x & z) ^ (y & z); } 00369 00370 /*************************************************************************************************/ 00371 00372 template <bool UseMB14, typename HashTraits> 00373 struct message_block_part_14_set_t 00374 { 00375 typedef HashTraits traits_type; 00376 typedef typename traits_type::hash_type hash_type; 00377 typedef typename traits_type::message_block_type message_block_type; 00378 typedef typename message_block_type::value_type message_block_value_type; 00379 00380 enum { half_max_message_bitsize_k = traits_type::max_message_bitsize_k / 2 }; 00381 00382 void operator () (message_block_value_type& mbp14, boost::uint64_t num_bits) 00383 { 00384 message_block_value_type message_block_value_type_max(std::numeric_limits<message_block_value_type>::max()); 00385 00386 mbp14 = static_cast<message_block_value_type>((num_bits >> (half_max_message_bitsize_k)) & message_block_value_type_max); 00387 } 00388 }; 00389 00390 /*************************************************************************************************/ 00391 00392 template <typename HashTraits> 00393 struct message_block_part_14_set_t<false, HashTraits> 00394 { 00395 typedef HashTraits traits_type; 00396 typedef typename traits_type::message_block_type message_block_type; 00397 typedef typename message_block_type::value_type message_block_value_type; 00398 00399 void operator () (message_block_value_type& mbp14, boost::uint64_t) 00400 { mbp14 = 0; } 00401 }; 00402 00403 /*************************************************************************************************/ 00404 00405 template <typename HashTraits, typename I> 00406 void block_and_digest(typename HashTraits::digest_type& digest, I first, boost::uint64_t num_bits) 00407 { 00408 typedef HashTraits traits_type; 00409 typedef typename traits_type::hash_type hash_type; 00410 typedef typename traits_type::message_block_type message_block_type; 00411 typedef typename message_block_type::value_type message_block_value_type; 00412 00413 enum 00414 { 00415 max_message_bitsize_k = traits_type::max_message_bitsize_k, 00416 half_max_message_bitsize_k = max_message_bitsize_k / 2, 00417 message_blocksize_k = traits_type::message_blocksize_k, 00418 use_mb_14 = half_max_message_bitsize_k < bitsizeof<boost::uint64_t>::value 00419 }; 00420 00421 message_block_value_type message_block_value_type_max(std::numeric_limits<message_block_value_type>::max()); 00422 message_block_type message_block; 00423 boost::uint64_t message_size(num_bits + max_message_bitsize_k); 00424 boost::uint64_t num_blocks(message_size / message_blocksize_k + 1); 00425 bool in_padding(false); 00426 bit_packer<I> bits(first, num_bits); 00427 00428 while (num_blocks != 0) 00429 { 00430 for (std::size_t i(0); i < 16; ++i) 00431 { 00432 if (!in_padding) 00433 { 00434 std::size_t unset_bits(bits(message_block[i])); 00435 00436 if (unset_bits != 0) 00437 { 00438 message_block[i] |= message_block_value_type(1) << (unset_bits - 1); 00439 00440 in_padding = true; 00441 } 00442 } 00443 else 00444 { 00445 if (num_blocks == 1) 00446 { 00447 // REVISIT (fbrereto) : According to the SHA standard the message length in the 00448 // 1024-block-size case can be up to 2^128 bits long, 00449 // but we only support messages up to 2^64 in length. In 00450 // all instances when padding in the generic case, block 00451 // part 14 would be: 00452 // mbp14 = (num_bits >> (half_max_message_bitsize_k)) & 00453 // message_block_value_type_max 00454 // But in the 1024-block-size case 00455 // half_max_message_bitsize_k == num_bits, and we will get 00456 // a compiler error basically saying "hey, you're 00457 // overshifting this value to 0", which would be fine in 00458 // this case because the number should be set to 0, but 00459 // the compiler is still (rightfully) noisy about it. This 00460 // workaround forces the right thing to do in that it sets 00461 // message block part 14 to zero in this special 00462 // 1024-block-size case, thus sliencing the compiler. 00463 00464 if (i == 14) 00465 message_block_part_14_set_t<use_mb_14, traits_type>()(message_block[i], num_bits); 00466 else if (i == 15) 00467 message_block[i] = static_cast<message_block_value_type>(num_bits & message_block_value_type_max); 00468 else 00469 message_block[i] = 0; 00470 } 00471 else 00472 message_block[i] = 0; 00473 } 00474 } 00475 00476 sha_traits<hash_type>().digest_message_block(digest, message_block); 00477 00478 --num_blocks; 00479 } 00480 00481 // clears potentioally sensitive information 00482 std::memset(&message_block, 0, sizeof(message_block)); 00483 } 00484 00485 /*************************************************************************************************/ 00486 00487 template <typename HashTraits> 00488 void sha_2_digest_message_block(typename HashTraits::digest_type& digest, 00489 const typename HashTraits::message_block_type& message_block) 00490 { 00491 // The "sha_2" in the name of this function is in 00492 // reference to the second generation of SHA algorithms 00493 // (224, 256, 384, and 512), all of which have the same 00494 // message block process implementation. 00495 00496 typedef HashTraits traits_type; 00497 typedef typename traits_type::hash_type hash_type; 00498 typedef typename traits_type::message_block_type message_block_type; 00499 typedef typename traits_type::schedule_type schedule_type; 00500 typedef typename hash_type::digest_type::value_type digest_value_type; 00501 00502 schedule_type schedule; 00503 00504 adobe::copy(message_block, &schedule[0]); 00505 00506 for (std::size_t t(message_block_type::static_size); t < schedule_type::static_size; ++t) 00507 schedule[t] = traits_type::small_sigma_1(schedule[t - 2]) + schedule[t - 7] + 00508 traits_type::small_sigma_0(schedule[t - 15]) + schedule[t - 16]; 00509 00510 digest_value_type a(digest[0]); 00511 digest_value_type b(digest[1]); 00512 digest_value_type c(digest[2]); 00513 digest_value_type d(digest[3]); 00514 digest_value_type e(digest[4]); 00515 digest_value_type f(digest[5]); 00516 digest_value_type g(digest[6]); 00517 digest_value_type h(digest[7]); 00518 00519 for (std::size_t t(0); t < schedule.size(); ++t) 00520 { 00521 digest_value_type T1 = h + 00522 traits_type::big_sigma_1(e) + 00523 implementation::ch(e, f, g) + 00524 traits_type::k(t) + 00525 schedule[t]; 00526 digest_value_type T2 = traits_type::big_sigma_0(a) + 00527 implementation::maj(a, b, c); 00528 h = g; 00529 g = f; 00530 f = e; 00531 e = d + T1; 00532 d = c; 00533 c = b; 00534 b = a; 00535 a = T1 + T2; 00536 } 00537 00538 digest[0] += a; 00539 digest[1] += b; 00540 digest[2] += c; 00541 digest[3] += d; 00542 digest[4] += e; 00543 digest[5] += f; 00544 digest[6] += g; 00545 digest[7] += h; 00546 00547 // clears potentioally sensitive information 00548 std::memset(&schedule, 0, sizeof(schedule)); 00549 } 00550 00551 /*************************************************************************************************/ 00552 00553 template <> 00554 struct sha_traits<sha1_t> 00555 { 00556 typedef class sha1_t hash_type; 00557 typedef boost::array<boost::uint32_t, 5> digest_type; 00558 typedef boost::array<boost::uint32_t, 16> message_block_type; 00559 typedef boost::array<boost::uint32_t, 80> schedule_type; 00560 00561 enum 00562 { 00563 max_message_bitsize_k = 64, 00564 message_blocksize_k = 512 00565 }; 00566 00567 static void reset_digest(digest_type& digest) 00568 { 00569 digest[0] = 0x67452301; 00570 digest[1] = 0xefcdab89; 00571 digest[2] = 0x98badcfe; 00572 digest[3] = 0x10325476; 00573 digest[4] = 0xc3d2e1f0; 00574 } 00575 00576 static void digest_message_block(digest_type& digest, const message_block_type& message_block) 00577 { 00578 schedule_type schedule; 00579 00580 adobe::copy(message_block, &schedule[0]); 00581 00582 for (std::size_t t(message_block_type::static_size); t < schedule_type::static_size; ++t) 00583 schedule[t] = implementation::rotl<1>( schedule[t - 3] ^ schedule[t - 8] ^ 00584 schedule[t - 14] ^ schedule[t - 16]); 00585 00586 boost::uint32_t a(digest[0]); 00587 boost::uint32_t b(digest[1]); 00588 boost::uint32_t c(digest[2]); 00589 boost::uint32_t d(digest[3]); 00590 boost::uint32_t e(digest[4]); 00591 00592 for (std::size_t t(0); t < schedule.size(); ++t) 00593 { 00594 boost::uint32_t T = implementation::rotl<5>(a) + 00595 f(t, b, c, d) + 00596 e + 00597 k(t) + 00598 schedule[t]; 00599 e = d; 00600 d = c; 00601 c = implementation::rotl<30>(b); 00602 b = a; 00603 a = T; 00604 } 00605 00606 digest[0] += a; 00607 digest[1] += b; 00608 digest[2] += c; 00609 digest[3] += d; 00610 digest[4] += e; 00611 00612 // clears potentioally sensitive information 00613 std::memset(&schedule, 0, sizeof(schedule)); 00614 } 00615 00616 private: 00617 static boost::uint32_t f( std::size_t t, 00618 boost::uint32_t x, 00619 boost::uint32_t y, 00620 boost::uint32_t z) 00621 { 00622 assert (t < 80); 00623 00624 if (t <= 19) return implementation::ch(x, y, z); 00625 else if (t <= 39) return implementation::parity(x, y, z); 00626 else if (t <= 59) return implementation::maj(x, y, z); 00627 00628 return implementation::parity(x, y, z); 00629 } 00630 00631 static boost::uint32_t k(std::size_t t) 00632 { 00633 assert(t < 80); 00634 00635 if (t <= 19) return 0x5a827999; 00636 else if (t <= 39) return 0x6ed9eba1; 00637 else if (t <= 59) return 0x8f1bbcdc; 00638 00639 return 0xca62c1d6; 00640 } 00641 }; 00642 00643 /*************************************************************************************************/ 00644 00645 template <> 00646 struct sha_traits<sha256_t> 00647 { 00648 typedef class sha256_t hash_type; 00649 typedef boost::array<boost::uint32_t, 8> digest_type; 00650 typedef boost::array<boost::uint32_t, 16> message_block_type; 00651 typedef boost::array<boost::uint32_t, 64> schedule_type; 00652 00653 enum 00654 { 00655 max_message_bitsize_k = 64, 00656 message_blocksize_k = 512 00657 }; 00658 00659 static void reset_digest(digest_type& digest) 00660 { 00661 digest[0] = 0x6a09e667; 00662 digest[1] = 0xbb67ae85; 00663 digest[2] = 0x3c6ef372; 00664 digest[3] = 0xa54ff53a; 00665 digest[4] = 0x510e527f; 00666 digest[5] = 0x9b05688c; 00667 digest[6] = 0x1f83d9ab; 00668 digest[7] = 0x5be0cd19; 00669 } 00670 00671 static void digest_message_block(digest_type& digest, const message_block_type& message_block) 00672 { sha_2_digest_message_block<sha_traits<hash_type> >(digest, message_block); } 00673 00674 static boost::uint32_t big_sigma_0(boost::uint32_t x) 00675 { return implementation::rotr<2>(x) ^ implementation::rotr<13>(x) ^ implementation::rotr<22>(x); } 00676 00677 static boost::uint32_t big_sigma_1(boost::uint32_t x) 00678 { return implementation::rotr<6>(x) ^ implementation::rotr<11>(x) ^ implementation::rotr<25>(x); } 00679 00680 static boost::uint32_t small_sigma_0(boost::uint32_t x) 00681 { return implementation::rotr<7>(x) ^ implementation::rotr<18>(x) ^ implementation::shr<3>(x); } 00682 00683 static boost::uint32_t small_sigma_1(boost::uint32_t x) 00684 { return implementation::rotr<17>(x) ^ implementation::rotr<19>(x) ^ implementation::shr<10>(x); } 00685 00686 static boost::uint32_t k(std::size_t t) 00687 { 00688 static const boost::uint32_t k_set[] = 00689 { 00690 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 00691 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 00692 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 00693 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 00694 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 00695 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 00696 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 00697 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 00698 }; 00699 00700 assert (t < 64); 00701 00702 return k_set[t]; 00703 } 00704 }; 00705 00706 /*************************************************************************************************/ 00707 00708 template <> 00709 struct sha_traits<sha224_t> 00710 { 00711 typedef class sha224_t hash_type; 00712 typedef sha_traits<sha256_t>::digest_type digest_type; 00713 typedef sha_traits<sha256_t>::message_block_type message_block_type; 00714 typedef sha_traits<sha256_t>::schedule_type schedule_type; 00715 00716 enum 00717 { 00718 max_message_bitsize_k = sha_traits<sha256_t>::max_message_bitsize_k, 00719 message_blocksize_k = sha_traits<sha256_t>::message_blocksize_k 00720 }; 00721 00722 static void reset_digest(digest_type& digest) 00723 { 00724 digest[0] = 0xc1059ed8; 00725 digest[1] = 0x367cd507; 00726 digest[2] = 0x3070dd17; 00727 digest[3] = 0xf70e5939; 00728 digest[4] = 0xffc00b31; 00729 digest[5] = 0x68581511; 00730 digest[6] = 0x64f98fa7; 00731 digest[7] = 0xbefa4fa4; 00732 } 00733 00734 static void digest_message_block(digest_type& digest, const message_block_type& message_block) 00735 { sha_2_digest_message_block<sha_traits<hash_type> >(digest, message_block); } 00736 00737 static boost::uint32_t big_sigma_0(boost::uint32_t x) 00738 { return sha_traits<sha256_t>::big_sigma_0(x); } 00739 00740 static boost::uint32_t big_sigma_1(boost::uint32_t x) 00741 { return sha_traits<sha256_t>::big_sigma_1(x); } 00742 00743 static boost::uint32_t small_sigma_0(boost::uint32_t x) 00744 { return sha_traits<sha256_t>::small_sigma_0(x); } 00745 00746 static boost::uint32_t small_sigma_1(boost::uint32_t x) 00747 { return sha_traits<sha256_t>::small_sigma_1(x); } 00748 00749 static boost::uint32_t k(std::size_t x) 00750 { return sha_traits<sha256_t>::k(x); } 00751 }; 00752 00753 /*************************************************************************************************/ 00754 00755 template <> 00756 struct sha_traits<sha512_t> 00757 { 00758 typedef class sha512_t hash_type; 00759 typedef boost::array<boost::uint64_t, 8> digest_type; 00760 typedef boost::array<boost::uint64_t, 16> message_block_type; 00761 typedef boost::array<boost::uint64_t, 80> schedule_type; 00762 00763 enum 00764 { 00765 max_message_bitsize_k = 128, 00766 message_blocksize_k = 1024 00767 }; 00768 00769 static void reset_digest(digest_type& digest) 00770 { 00771 digest[0] = 0x6a09e667f3bcc908ULL; 00772 digest[1] = 0xbb67ae8584caa73bULL; 00773 digest[2] = 0x3c6ef372fe94f82bULL; 00774 digest[3] = 0xa54ff53a5f1d36f1ULL; 00775 digest[4] = 0x510e527fade682d1ULL; 00776 digest[5] = 0x9b05688c2b3e6c1fULL; 00777 digest[6] = 0x1f83d9abfb41bd6bULL; 00778 digest[7] = 0x5be0cd19137e2179ULL; 00779 } 00780 00781 static void digest_message_block(digest_type& digest, const message_block_type& message_block) 00782 { sha_2_digest_message_block<sha_traits<hash_type> >(digest, message_block); } 00783 00784 static boost::uint64_t big_sigma_0(boost::uint64_t x) 00785 { return implementation::rotr<28>(x) ^ implementation::rotr<34>(x) ^ implementation::rotr<39>(x); } 00786 00787 static boost::uint64_t big_sigma_1(boost::uint64_t x) 00788 { return implementation::rotr<14>(x) ^ implementation::rotr<18>(x) ^ implementation::rotr<41>(x); } 00789 00790 static boost::uint64_t small_sigma_0(boost::uint64_t x) 00791 { return implementation::rotr<1>(x) ^ implementation::rotr<8>(x) ^ implementation::shr<7>(x); } 00792 00793 static boost::uint64_t small_sigma_1(boost::uint64_t x) 00794 { return implementation::rotr<19>(x) ^ implementation::rotr<61>(x) ^ implementation::shr<6>(x); } 00795 00796 static boost::uint64_t k(std::size_t t) 00797 { 00798 static const boost::uint64_t k_set[] = 00799 { 00800 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 00801 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 00802 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 00803 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 00804 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 00805 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 00806 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 00807 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 00808 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 00809 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 00810 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 00811 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 00812 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 00813 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 00814 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 00815 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 00816 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 00817 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 00818 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 00819 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL 00820 }; 00821 00822 assert (t < 80); 00823 00824 return k_set[t]; 00825 } 00826 }; 00827 00828 /*************************************************************************************************/ 00829 00830 template <> 00831 struct sha_traits<sha384_t> 00832 { 00833 typedef class sha384_t hash_type; 00834 typedef sha_traits<sha512_t>::digest_type digest_type; 00835 typedef sha_traits<sha512_t>::message_block_type message_block_type; 00836 typedef sha_traits<sha512_t>::schedule_type schedule_type; 00837 00838 enum 00839 { 00840 max_message_bitsize_k = sha_traits<sha512_t>::max_message_bitsize_k, 00841 message_blocksize_k = sha_traits<sha512_t>::message_blocksize_k 00842 }; 00843 00844 static void reset_digest(digest_type& digest) 00845 { 00846 digest[0] = 0xcbbb9d5dc1059ed8ULL; 00847 digest[1] = 0x629a292a367cd507ULL; 00848 digest[2] = 0x9159015a3070dd17ULL; 00849 digest[3] = 0x152fecd8f70e5939ULL; 00850 digest[4] = 0x67332667ffc00b31ULL; 00851 digest[5] = 0x8eb44a8768581511ULL; 00852 digest[6] = 0xdb0c2e0d64f98fa7ULL; 00853 digest[7] = 0x47b5481dbefa4fa4ULL; 00854 } 00855 00856 static void digest_message_block(digest_type& digest, const message_block_type& message_block) 00857 { sha_2_digest_message_block<sha_traits<hash_type> >(digest, message_block); } 00858 00859 static boost::uint64_t big_sigma_0(boost::uint64_t x) 00860 { return sha_traits<sha512_t>::big_sigma_0(x); } 00861 00862 static boost::uint64_t big_sigma_1(boost::uint64_t x) 00863 { return sha_traits<sha512_t>::big_sigma_1(x); } 00864 00865 static boost::uint64_t small_sigma_0(boost::uint64_t x) 00866 { return sha_traits<sha512_t>::small_sigma_0(x); } 00867 00868 static boost::uint64_t small_sigma_1(boost::uint64_t x) 00869 { return sha_traits<sha512_t>::small_sigma_1(x); } 00870 00871 static boost::uint64_t k(std::size_t x) 00872 { return sha_traits<sha512_t>::k(x); } 00873 }; 00874 00875 /*************************************************************************************************/ 00876 00877 #endif 00878 00879 /*************************************************************************************************/ 00880 00881 } // namespace implementation 00882 00883 /*************************************************************************************************/ 00884 00885 class sha1_t 00886 { 00887 public: 00888 #if !defined(ADOBE_NO_DOCUMENTATION) 00889 typedef implementation::sha_traits<sha1_t> traits_type; 00890 #endif 00891 typedef traits_type::digest_type digest_type; 00892 00893 template <typename I> 00894 inline digest_type digest(I first, I last) 00895 { 00896 enum { ibits_k = implementation::bitsizeof<typename std::iterator_traits<I>::value_type>::value }; 00897 00898 return digest(first, implementation::long_distance(first, last) * ibits_k); 00899 } 00900 00901 template <typename I> 00902 inline digest_type digest(I first, boost::uint64_t num_bits) 00903 { 00904 traits_type().reset_digest(digest_m); 00905 00906 implementation::block_and_digest<traits_type>(digest_m, first, num_bits); 00907 00908 return digest_m; 00909 } 00910 00911 private: 00912 digest_type digest_m; 00913 }; 00914 00915 /*************************************************************************************************/ 00916 00917 class sha224_t 00918 { 00919 public: 00920 #if !defined(ADOBE_NO_DOCUMENTATION) 00921 typedef implementation::sha_traits<sha224_t> traits_type; 00922 #endif 00923 typedef boost::array<boost::uint32_t, 7> digest_type; 00924 00925 template <typename I> 00926 inline digest_type digest(I first, I last) 00927 { 00928 enum { ibits_k = implementation::bitsizeof<typename std::iterator_traits<I>::value_type>::value }; 00929 00930 return digest(first, implementation::long_distance(first, last) * ibits_k); 00931 } 00932 00933 template <typename I> 00934 inline digest_type digest(I first, boost::uint64_t num_bits) 00935 { 00936 traits_type().reset_digest(digest_m); 00937 00938 implementation::block_and_digest<traits_type>(digest_m, first, num_bits); 00939 00940 return crop_digest(digest_m); 00941 } 00942 00943 private: 00944 inline digest_type crop_digest(traits_type::digest_type& digest) 00945 { 00946 digest_type result; 00947 00948 std::copy(digest.begin(), digest.begin() + digest_type::static_size, &result[0]); 00949 00950 return result; 00951 } 00952 00953 traits_type::digest_type digest_m; 00954 }; 00955 00956 /*************************************************************************************************/ 00957 00958 class sha256_t 00959 { 00960 public: 00961 #if !defined(ADOBE_NO_DOCUMENTATION) 00962 typedef implementation::sha_traits<sha256_t> traits_type; 00963 #endif 00964 typedef traits_type::digest_type digest_type; 00965 00966 template <typename I> 00967 inline digest_type digest(I first, I last) 00968 { 00969 enum { ibits_k = implementation::bitsizeof<typename std::iterator_traits<I>::value_type>::value }; 00970 00971 return digest(first, implementation::long_distance(first, last) * ibits_k); 00972 } 00973 00974 template <typename I> 00975 inline digest_type digest(I first, boost::uint64_t num_bits) 00976 { 00977 traits_type().reset_digest(digest_m); 00978 00979 implementation::block_and_digest<traits_type>(digest_m, first, num_bits); 00980 00981 return digest_m; 00982 } 00983 00984 private: 00985 digest_type digest_m; 00986 }; 00987 00988 /*************************************************************************************************/ 00989 00990 class sha512_t 00991 { 00992 public: 00993 #if !defined(ADOBE_NO_DOCUMENTATION) 00994 typedef implementation::sha_traits<sha512_t> traits_type; 00995 #endif 00996 typedef traits_type::digest_type digest_type; 00997 00998 template <typename I> 00999 inline digest_type digest(I first, I last) 01000 { 01001 enum { ibits_k = implementation::bitsizeof<typename std::iterator_traits<I>::value_type>::value }; 01002 01003 return digest(first, implementation::long_distance(first, last) * ibits_k); 01004 } 01005 01006 template <typename I> 01007 inline digest_type digest(I first, boost::uint64_t num_bits) 01008 { 01009 traits_type().reset_digest(digest_m); 01010 01011 implementation::block_and_digest<traits_type>(digest_m, first, num_bits); 01012 01013 return digest_m; 01014 } 01015 01016 private: 01017 digest_type digest_m; 01018 }; 01019 01020 /*************************************************************************************************/ 01021 01022 class sha384_t 01023 { 01024 public: 01025 #if !defined(ADOBE_NO_DOCUMENTATION) 01026 typedef implementation::sha_traits<sha384_t> traits_type; 01027 #endif 01028 typedef boost::array<boost::uint64_t, 6> digest_type; 01029 01030 template <typename I> 01031 inline digest_type digest(I first, I last) 01032 { 01033 enum { ibits_k = implementation::bitsizeof<typename std::iterator_traits<I>::value_type>::value }; 01034 01035 return digest(first, implementation::long_distance(first, last) * ibits_k); 01036 } 01037 01038 template <typename I> 01039 inline digest_type digest(I first, boost::uint64_t num_bits) 01040 { 01041 traits_type().reset_digest(digest_m); 01042 01043 implementation::block_and_digest<traits_type>(digest_m, first, num_bits); 01044 01045 return crop_digest(digest_m); 01046 } 01047 01048 private: 01049 inline digest_type crop_digest(traits_type::digest_type& digest) 01050 { 01051 digest_type result; 01052 01053 std::copy(digest.begin(), digest.begin() + digest_type::static_size, &result[0]); 01054 01055 return result; 01056 } 01057 01058 traits_type::digest_type digest_m; 01059 }; 01060 01061 /*************************************************************************************************/ 01062 01063 } // namespace adobe 01064 01065 /*************************************************************************************************/ 01066 01067 #endif 01068 01069 /*************************************************************************************************/ |