hmac.hpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #ifndef BOOST_HASH2_HMAC_HPP_INCLUDED
  2. #define BOOST_HASH2_HMAC_HPP_INCLUDED
  3. // Copyright 2017, 2018 Peter Dimov.
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // https://www.boost.org/LICENSE_1_0.txt
  6. //
  7. // HMAC message authentication algorithm, https://tools.ietf.org/html/rfc2104
  8. #include <boost/hash2/detail/write.hpp>
  9. #include <boost/hash2/detail/memcpy.hpp>
  10. #include <boost/assert.hpp>
  11. #include <boost/config.hpp>
  12. #include <boost/config/workaround.hpp>
  13. #include <cstdint>
  14. #include <cstring>
  15. #include <cstddef>
  16. #if !defined(BOOST_NO_CXX14_CONSTEXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 60000)
  17. # define BOOST_HASH2_HMAC_CONSTEXPR constexpr
  18. #else
  19. // libs/hash2/test/concept.cpp:45:7: in constexpr expansion of 'h1.boost::hash2::hmac<H>::hmac<boost::hash2::md5_128>()'
  20. // ./boost/hash2/hmac.hpp:80:13: in constexpr expansion of 'boost::hash2::hmac<H>::init<boost::hash2::md5_128>(0u, 0u)'
  21. // libs/hash2/test/concept.cpp:45:7: internal compiler error: in fold_binary_loc, at fold-const.c:9925
  22. # define BOOST_HASH2_HMAC_CONSTEXPR
  23. #endif
  24. namespace boost
  25. {
  26. namespace hash2
  27. {
  28. template<class H> class hmac
  29. {
  30. public:
  31. using result_type = typename H::result_type;
  32. static constexpr std::size_t block_size = H::block_size;
  33. private:
  34. H outer_;
  35. H inner_;
  36. private:
  37. BOOST_HASH2_HMAC_CONSTEXPR void init( unsigned char const* p, std::size_t n )
  38. {
  39. constexpr std::size_t m = block_size;
  40. unsigned char key[ m ] = {};
  41. if( n == 0 )
  42. {
  43. // memcpy from (NULL, 0) is undefined
  44. }
  45. else if( n <= m )
  46. {
  47. detail::memcpy( key, p, n );
  48. }
  49. else
  50. {
  51. H h;
  52. h.update( p, n );
  53. result_type r = h.result();
  54. detail::memcpy( key, &r[0], m < r.size()? m: r.size() );
  55. }
  56. for( std::size_t i = 0; i < m; ++i )
  57. {
  58. key[ i ] = static_cast<unsigned char>( key[ i ] ^ 0x36 );
  59. }
  60. inner_.update( key, m );
  61. for( std::size_t i = 0; i < m; ++i )
  62. {
  63. key[ i ] = static_cast<unsigned char>( key[ i ] ^ 0x36 ^ 0x5C );
  64. }
  65. outer_.update( key, m );
  66. }
  67. public:
  68. BOOST_HASH2_HMAC_CONSTEXPR hmac()
  69. {
  70. init( 0, 0 );
  71. }
  72. explicit BOOST_HASH2_HMAC_CONSTEXPR hmac( std::uint64_t seed )
  73. {
  74. if( seed == 0 )
  75. {
  76. init( 0, 0 );
  77. }
  78. else
  79. {
  80. unsigned char tmp[ 8 ] = {};
  81. detail::write64le( tmp, seed );
  82. init( tmp, 8 );
  83. }
  84. }
  85. BOOST_HASH2_HMAC_CONSTEXPR hmac( unsigned char const* p, std::size_t n )
  86. {
  87. init( p, n );
  88. }
  89. hmac( void const* p, std::size_t n )
  90. {
  91. init( static_cast<unsigned char const*>( p ), n );
  92. }
  93. BOOST_CXX14_CONSTEXPR void update( unsigned char const* p, std::size_t n )
  94. {
  95. inner_.update( p, n );
  96. }
  97. void update( void const* pv, std::size_t n )
  98. {
  99. inner_.update( pv, n );
  100. }
  101. BOOST_CXX14_CONSTEXPR result_type result()
  102. {
  103. result_type r = inner_.result();
  104. outer_.update( &r[0], r.size() );
  105. return outer_.result();
  106. }
  107. };
  108. } // namespace hash2
  109. } // namespace boost
  110. #endif // #ifndef BOOST_HASH2_HMAC_HPP_INCLUDED