sha1.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. #ifndef BOOST_HASH2_SHA1_HPP_INCLUDED
  2. #define BOOST_HASH2_SHA1_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. // SHA1 message digest algorithm, https://tools.ietf.org/html/rfc3174
  8. #include <boost/hash2/hmac.hpp>
  9. #include <boost/hash2/digest.hpp>
  10. #include <boost/hash2/detail/read.hpp>
  11. #include <boost/hash2/detail/write.hpp>
  12. #include <boost/hash2/detail/rot.hpp>
  13. #include <boost/hash2/detail/memcpy.hpp>
  14. #include <boost/hash2/detail/memset.hpp>
  15. #include <boost/assert.hpp>
  16. #include <boost/config.hpp>
  17. #include <cstdint>
  18. #include <array>
  19. #include <cstring>
  20. #include <cstddef>
  21. namespace boost
  22. {
  23. namespace hash2
  24. {
  25. class sha1_160
  26. {
  27. private:
  28. std::uint32_t state_[ 5 ] = { 0x67452301u, 0xefcdab89u, 0x98badcfeu, 0x10325476u, 0xc3d2e1f0u };
  29. static constexpr int N = 64;
  30. unsigned char buffer_[ N ] = {};
  31. std::size_t m_ = 0; // == n_ % N
  32. std::uint64_t n_ = 0;
  33. private:
  34. static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void R1( std::uint32_t a, std::uint32_t & b, std::uint32_t c, std::uint32_t d, std::uint32_t & e, std::uint32_t w[], unsigned char const block[ 64 ], int i )
  35. {
  36. w[ i ] = detail::read32be( block + i * 4 );
  37. std::uint32_t f = (b & c) | (~b & d);
  38. e += detail::rotl( a, 5 ) + f + 0x5A827999 + w[ i ];
  39. b = detail::rotl( b, 30 );
  40. }
  41. static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR std::uint32_t W( std::uint32_t w[], int i )
  42. {
  43. return w[ i ] = detail::rotl( w[ i - 3 ] ^ w[ i - 8 ] ^ w[ i - 14 ] ^ w[ i - 16 ], 1 );
  44. }
  45. static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void R2( std::uint32_t a, std::uint32_t & b, std::uint32_t c, std::uint32_t d, std::uint32_t & e, std::uint32_t w[], int i )
  46. {
  47. std::uint32_t f = (b & c) | (~b & d);
  48. e += detail::rotl( a, 5 ) + f + 0x5A827999 + W( w, i );
  49. b = detail::rotl( b, 30 );
  50. }
  51. static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void R3( std::uint32_t a, std::uint32_t & b, std::uint32_t c, std::uint32_t d, std::uint32_t & e, std::uint32_t w[], int i )
  52. {
  53. std::uint32_t f = b ^ c ^ d;
  54. e += detail::rotl( a, 5 ) + f + 0x6ED9EBA1 + W( w, i );
  55. b = detail::rotl( b, 30 );
  56. }
  57. static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void R4( std::uint32_t a, std::uint32_t & b, std::uint32_t c, std::uint32_t d, std::uint32_t & e, std::uint32_t w[], int i )
  58. {
  59. std::uint32_t f = (b & c) | (b & d) | (c & d);
  60. e += detail::rotl( a, 5 ) + f + 0x8F1BBCDC + W( w, i );
  61. b = detail::rotl( b, 30 );
  62. }
  63. static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void R5( std::uint32_t a, std::uint32_t & b, std::uint32_t c, std::uint32_t d, std::uint32_t & e, std::uint32_t w[], int i )
  64. {
  65. std::uint32_t f = b ^ c ^ d;
  66. e += detail::rotl( a, 5 ) + f + 0xCA62C1D6 + W( w, i );
  67. b = detail::rotl( b, 30 );
  68. }
  69. BOOST_CXX14_CONSTEXPR void transform( unsigned char const block[ 64 ] )
  70. {
  71. std::uint32_t a = state_[ 0 ];
  72. std::uint32_t b = state_[ 1 ];
  73. std::uint32_t c = state_[ 2 ];
  74. std::uint32_t d = state_[ 3 ];
  75. std::uint32_t e = state_[ 4 ];
  76. std::uint32_t w[ 80 ] = {};
  77. R1( a, b, c, d, e, w, block, 0 );
  78. R1( e, a, b, c, d, w, block, 1 );
  79. R1( d, e, a, b, c, w, block, 2 );
  80. R1( c, d, e, a, b, w, block, 3 );
  81. R1( b, c, d, e, a, w, block, 4 );
  82. R1( a, b, c, d, e, w, block, 5 );
  83. R1( e, a, b, c, d, w, block, 6 );
  84. R1( d, e, a, b, c, w, block, 7 );
  85. R1( c, d, e, a, b, w, block, 8 );
  86. R1( b, c, d, e, a, w, block, 9 );
  87. R1( a, b, c, d, e, w, block, 10 );
  88. R1( e, a, b, c, d, w, block, 11 );
  89. R1( d, e, a, b, c, w, block, 12 );
  90. R1( c, d, e, a, b, w, block, 13 );
  91. R1( b, c, d, e, a, w, block, 14 );
  92. R1( a, b, c, d, e, w, block, 15 );
  93. R2( e, a, b, c, d, w, 16 );
  94. R2( d, e, a, b, c, w, 17 );
  95. R2( c, d, e, a, b, w, 18 );
  96. R2( b, c, d, e, a, w, 19 );
  97. R3( a, b, c, d, e, w, 20 );
  98. R3( e, a, b, c, d, w, 21 );
  99. R3( d, e, a, b, c, w, 22 );
  100. R3( c, d, e, a, b, w, 23 );
  101. R3( b, c, d, e, a, w, 24 );
  102. R3( a, b, c, d, e, w, 25 );
  103. R3( e, a, b, c, d, w, 26 );
  104. R3( d, e, a, b, c, w, 27 );
  105. R3( c, d, e, a, b, w, 28 );
  106. R3( b, c, d, e, a, w, 29 );
  107. R3( a, b, c, d, e, w, 30 );
  108. R3( e, a, b, c, d, w, 31 );
  109. R3( d, e, a, b, c, w, 32 );
  110. R3( c, d, e, a, b, w, 33 );
  111. R3( b, c, d, e, a, w, 34 );
  112. R3( a, b, c, d, e, w, 35 );
  113. R3( e, a, b, c, d, w, 36 );
  114. R3( d, e, a, b, c, w, 37 );
  115. R3( c, d, e, a, b, w, 38 );
  116. R3( b, c, d, e, a, w, 39 );
  117. R4( a, b, c, d, e, w, 40 );
  118. R4( e, a, b, c, d, w, 41 );
  119. R4( d, e, a, b, c, w, 42 );
  120. R4( c, d, e, a, b, w, 43 );
  121. R4( b, c, d, e, a, w, 44 );
  122. R4( a, b, c, d, e, w, 45 );
  123. R4( e, a, b, c, d, w, 46 );
  124. R4( d, e, a, b, c, w, 47 );
  125. R4( c, d, e, a, b, w, 48 );
  126. R4( b, c, d, e, a, w, 49 );
  127. R4( a, b, c, d, e, w, 50 );
  128. R4( e, a, b, c, d, w, 51 );
  129. R4( d, e, a, b, c, w, 52 );
  130. R4( c, d, e, a, b, w, 53 );
  131. R4( b, c, d, e, a, w, 54 );
  132. R4( a, b, c, d, e, w, 55 );
  133. R4( e, a, b, c, d, w, 56 );
  134. R4( d, e, a, b, c, w, 57 );
  135. R4( c, d, e, a, b, w, 58 );
  136. R4( b, c, d, e, a, w, 59 );
  137. R5( a, b, c, d, e, w, 60 );
  138. R5( e, a, b, c, d, w, 61 );
  139. R5( d, e, a, b, c, w, 62 );
  140. R5( c, d, e, a, b, w, 63 );
  141. R5( b, c, d, e, a, w, 64 );
  142. R5( a, b, c, d, e, w, 65 );
  143. R5( e, a, b, c, d, w, 66 );
  144. R5( d, e, a, b, c, w, 67 );
  145. R5( c, d, e, a, b, w, 68 );
  146. R5( b, c, d, e, a, w, 69 );
  147. R5( a, b, c, d, e, w, 70 );
  148. R5( e, a, b, c, d, w, 71 );
  149. R5( d, e, a, b, c, w, 72 );
  150. R5( c, d, e, a, b, w, 73 );
  151. R5( b, c, d, e, a, w, 74 );
  152. R5( a, b, c, d, e, w, 75 );
  153. R5( e, a, b, c, d, w, 76 );
  154. R5( d, e, a, b, c, w, 77 );
  155. R5( c, d, e, a, b, w, 78 );
  156. R5( b, c, d, e, a, w, 79 );
  157. state_[ 0 ] += a;
  158. state_[ 1 ] += b;
  159. state_[ 2 ] += c;
  160. state_[ 3 ] += d;
  161. state_[ 4 ] += e;
  162. }
  163. public:
  164. typedef digest<20> result_type;
  165. static constexpr std::size_t block_size = 64;
  166. sha1_160() = default;
  167. explicit BOOST_CXX14_CONSTEXPR sha1_160( std::uint64_t seed )
  168. {
  169. if( seed != 0 )
  170. {
  171. unsigned char tmp[ 8 ] = {};
  172. detail::write64le( tmp, seed );
  173. update( tmp, 8 );
  174. result();
  175. }
  176. }
  177. BOOST_CXX14_CONSTEXPR sha1_160( unsigned char const * p, std::size_t n )
  178. {
  179. if( n != 0 )
  180. {
  181. update( p, n );
  182. result();
  183. }
  184. }
  185. sha1_160( void const * p, std::size_t n ): sha1_160( static_cast<unsigned char const*>( p ), n )
  186. {
  187. }
  188. BOOST_CXX14_CONSTEXPR void update( unsigned char const* p, std::size_t n )
  189. {
  190. BOOST_ASSERT( m_ == n_ % N );
  191. if( n == 0 ) return;
  192. n_ += n;
  193. if( m_ > 0 )
  194. {
  195. std::size_t k = N - m_;
  196. if( n < k )
  197. {
  198. k = n;
  199. }
  200. detail::memcpy( buffer_ + m_, p, k );
  201. p += k;
  202. n -= k;
  203. m_ += k;
  204. if( m_ < N ) return;
  205. BOOST_ASSERT( m_ == N );
  206. transform( buffer_ );
  207. m_ = 0;
  208. detail::memset( buffer_, 0, N );
  209. }
  210. BOOST_ASSERT( m_ == 0 );
  211. while( n >= N )
  212. {
  213. transform( p );
  214. p += N;
  215. n -= N;
  216. }
  217. BOOST_ASSERT( n < N );
  218. if( n > 0 )
  219. {
  220. detail::memcpy( buffer_, p, n );
  221. m_ = n;
  222. }
  223. BOOST_ASSERT( m_ == n_ % N );
  224. }
  225. void update( void const* pv, std::size_t n )
  226. {
  227. unsigned char const* p = static_cast<unsigned char const*>( pv );
  228. update( p, n );
  229. }
  230. BOOST_CXX14_CONSTEXPR result_type result()
  231. {
  232. BOOST_ASSERT( m_ == n_ % N );
  233. unsigned char bits[ 8 ] = {};
  234. detail::write64be( bits, n_ * 8 );
  235. std::size_t k = m_ < 56? 56 - m_: 120 - m_;
  236. unsigned char padding[ 64 ] = { 0x80 };
  237. update( padding, k );
  238. update( bits, 8 );
  239. BOOST_ASSERT( m_ == 0 );
  240. result_type digest;
  241. for( int i = 0; i < 5; ++i )
  242. {
  243. detail::write32be( digest.data() + i * 4, state_[ i ] );
  244. }
  245. return digest;
  246. }
  247. };
  248. using hmac_sha1_160 = hmac<sha1_160>;
  249. } // namespace hash2
  250. } // namespace boost
  251. #endif // #ifndef BOOST_HASH2_SHA1_HPP_INCLUDED