md5.hpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. #ifndef BOOST_HASH2_MD5_HPP_INCLUDED
  2. #define BOOST_HASH2_MD5_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. // MD5 message digest algorithm, https://tools.ietf.org/html/rfc1321
  8. #include <boost/hash2/digest.hpp>
  9. #include <boost/hash2/hmac.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/hash2/detail/config.hpp>
  16. #include <boost/assert.hpp>
  17. #include <boost/config.hpp>
  18. #include <cstdint>
  19. #include <array>
  20. #include <cstring>
  21. #include <cstddef>
  22. namespace boost
  23. {
  24. namespace hash2
  25. {
  26. class md5_128
  27. {
  28. private:
  29. std::uint32_t state_[ 4 ] = { 0x67452301u, 0xefcdab89u, 0x98badcfeu, 0x10325476u };
  30. static constexpr int N = 64;
  31. unsigned char buffer_[ N ] = {};
  32. std::size_t m_ = 0; // == n_ % N
  33. std::uint64_t n_ = 0;
  34. private:
  35. static BOOST_FORCEINLINE constexpr std::uint32_t F( std::uint32_t x, std::uint32_t y, std::uint32_t z )
  36. {
  37. return (x & y) | (~x & z);
  38. }
  39. static BOOST_FORCEINLINE constexpr std::uint32_t G( std::uint32_t x, std::uint32_t y, std::uint32_t z )
  40. {
  41. return (x & z) | (y & ~z);
  42. }
  43. static BOOST_FORCEINLINE constexpr std::uint32_t H( std::uint32_t x, std::uint32_t y, std::uint32_t z )
  44. {
  45. return x ^ y ^ z;
  46. }
  47. static BOOST_FORCEINLINE constexpr std::uint32_t I( std::uint32_t x, std::uint32_t y, std::uint32_t z )
  48. {
  49. return y ^ (x | ~z);
  50. }
  51. static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void FF( std::uint32_t & a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, int s, std::uint32_t ac )
  52. {
  53. a += F( b, c, d ) + x + ac;
  54. a = detail::rotl( a, s );
  55. a += b;
  56. }
  57. static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void GG( std::uint32_t & a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, int s, std::uint32_t ac )
  58. {
  59. a += G( b, c, d ) + x + ac;
  60. a = detail::rotl( a, s );
  61. a += b;
  62. }
  63. static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void HH( std::uint32_t & a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, int s, std::uint32_t ac )
  64. {
  65. a += H( b, c, d ) + x + ac;
  66. a = detail::rotl( a, s );
  67. a += b;
  68. }
  69. static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void II( std::uint32_t & a, std::uint32_t b, std::uint32_t c, std::uint32_t d, std::uint32_t x, int s, std::uint32_t ac )
  70. {
  71. a += I( b, c, d ) + x + ac;
  72. a = detail::rotl( a, s );
  73. a += b;
  74. }
  75. static constexpr int S11 = 7;
  76. static constexpr int S12 = 12;
  77. static constexpr int S13 = 17;
  78. static constexpr int S14 = 22;
  79. static constexpr int S21 = 5;
  80. static constexpr int S22 = 9;
  81. static constexpr int S23 = 14;
  82. static constexpr int S24 = 20;
  83. static constexpr int S31 = 4;
  84. static constexpr int S32 = 11;
  85. static constexpr int S33 = 16;
  86. static constexpr int S34 = 23;
  87. static constexpr int S41 = 6;
  88. static constexpr int S42 = 10;
  89. static constexpr int S43 = 15;
  90. static constexpr int S44 = 21;
  91. BOOST_CXX14_CONSTEXPR void transform( unsigned char const block[ 64 ] )
  92. {
  93. std::uint32_t a = state_[ 0 ];
  94. std::uint32_t b = state_[ 1 ];
  95. std::uint32_t c = state_[ 2 ];
  96. std::uint32_t d = state_[ 3 ];
  97. std::uint32_t x[ 16 ] = {};
  98. for( int i = 0; i < 16; ++i )
  99. {
  100. x[ i ] = detail::read32le( block + i * 4 );
  101. }
  102. FF( a, b, c, d, x[ 0], S11, 0xd76aa478 );
  103. FF( d, a, b, c, x[ 1], S12, 0xe8c7b756 );
  104. FF( c, d, a, b, x[ 2], S13, 0x242070db );
  105. FF( b, c, d, a, x[ 3], S14, 0xc1bdceee );
  106. FF( a, b, c, d, x[ 4], S11, 0xf57c0faf );
  107. FF( d, a, b, c, x[ 5], S12, 0x4787c62a );
  108. FF( c, d, a, b, x[ 6], S13, 0xa8304613 );
  109. FF( b, c, d, a, x[ 7], S14, 0xfd469501 );
  110. FF( a, b, c, d, x[ 8], S11, 0x698098d8 );
  111. FF( d, a, b, c, x[ 9], S12, 0x8b44f7af );
  112. FF( c, d, a, b, x[10], S13, 0xffff5bb1 );
  113. FF( b, c, d, a, x[11], S14, 0x895cd7be );
  114. FF( a, b, c, d, x[12], S11, 0x6b901122 );
  115. FF( d, a, b, c, x[13], S12, 0xfd987193 );
  116. FF( c, d, a, b, x[14], S13, 0xa679438e );
  117. FF( b, c, d, a, x[15], S14, 0x49b40821 );
  118. GG( a, b, c, d, x[ 1], S21, 0xf61e2562 );
  119. GG( d, a, b, c, x[ 6], S22, 0xc040b340 );
  120. GG( c, d, a, b, x[11], S23, 0x265e5a51 );
  121. GG( b, c, d, a, x[ 0], S24, 0xe9b6c7aa );
  122. GG( a, b, c, d, x[ 5], S21, 0xd62f105d );
  123. GG( d, a, b, c, x[10], S22, 0x2441453 );
  124. GG( c, d, a, b, x[15], S23, 0xd8a1e681 );
  125. GG( b, c, d, a, x[ 4], S24, 0xe7d3fbc8 );
  126. GG( a, b, c, d, x[ 9], S21, 0x21e1cde6 );
  127. GG( d, a, b, c, x[14], S22, 0xc33707d6 );
  128. GG( c, d, a, b, x[ 3], S23, 0xf4d50d87 );
  129. GG( b, c, d, a, x[ 8], S24, 0x455a14ed );
  130. GG( a, b, c, d, x[13], S21, 0xa9e3e905 );
  131. GG( d, a, b, c, x[ 2], S22, 0xfcefa3f8 );
  132. GG( c, d, a, b, x[ 7], S23, 0x676f02d9 );
  133. GG( b, c, d, a, x[12], S24, 0x8d2a4c8a );
  134. HH( a, b, c, d, x[ 5], S31, 0xfffa3942 );
  135. HH( d, a, b, c, x[ 8], S32, 0x8771f681 );
  136. HH( c, d, a, b, x[11], S33, 0x6d9d6122 );
  137. HH( b, c, d, a, x[14], S34, 0xfde5380c );
  138. HH( a, b, c, d, x[ 1], S31, 0xa4beea44 );
  139. HH( d, a, b, c, x[ 4], S32, 0x4bdecfa9 );
  140. HH( c, d, a, b, x[ 7], S33, 0xf6bb4b60 );
  141. HH( b, c, d, a, x[10], S34, 0xbebfbc70 );
  142. HH( a, b, c, d, x[13], S31, 0x289b7ec6 );
  143. HH( d, a, b, c, x[ 0], S32, 0xeaa127fa );
  144. HH( c, d, a, b, x[ 3], S33, 0xd4ef3085 );
  145. HH( b, c, d, a, x[ 6], S34, 0x4881d05 );
  146. HH( a, b, c, d, x[ 9], S31, 0xd9d4d039 );
  147. HH( d, a, b, c, x[12], S32, 0xe6db99e5 );
  148. HH( c, d, a, b, x[15], S33, 0x1fa27cf8 );
  149. HH( b, c, d, a, x[ 2], S34, 0xc4ac5665 );
  150. II( a, b, c, d, x[ 0], S41, 0xf4292244 );
  151. II( d, a, b, c, x[ 7], S42, 0x432aff97 );
  152. II( c, d, a, b, x[14], S43, 0xab9423a7 );
  153. II( b, c, d, a, x[ 5], S44, 0xfc93a039 );
  154. II( a, b, c, d, x[12], S41, 0x655b59c3 );
  155. II( d, a, b, c, x[ 3], S42, 0x8f0ccc92 );
  156. II( c, d, a, b, x[10], S43, 0xffeff47d );
  157. II( b, c, d, a, x[ 1], S44, 0x85845dd1 );
  158. II( a, b, c, d, x[ 8], S41, 0x6fa87e4f );
  159. II( d, a, b, c, x[15], S42, 0xfe2ce6e0 );
  160. II( c, d, a, b, x[ 6], S43, 0xa3014314 );
  161. II( b, c, d, a, x[13], S44, 0x4e0811a1 );
  162. II( a, b, c, d, x[ 4], S41, 0xf7537e82 );
  163. II( d, a, b, c, x[11], S42, 0xbd3af235 );
  164. II( c, d, a, b, x[ 2], S43, 0x2ad7d2bb );
  165. II( b, c, d, a, x[ 9], S44, 0xeb86d391 );
  166. state_[ 0 ] += a;
  167. state_[ 1 ] += b;
  168. state_[ 2 ] += c;
  169. state_[ 3 ] += d;
  170. }
  171. public:
  172. using result_type = digest<16>;
  173. static constexpr std::size_t block_size = 64;
  174. md5_128() = default;
  175. BOOST_CXX14_CONSTEXPR explicit md5_128( std::uint64_t seed )
  176. {
  177. if( seed != 0 )
  178. {
  179. unsigned char tmp[ 8 ] = {};
  180. detail::write64le( tmp, seed );
  181. update( tmp, 8 );
  182. result();
  183. }
  184. }
  185. BOOST_CXX14_CONSTEXPR md5_128( unsigned char const * p, std::size_t n )
  186. {
  187. if( n != 0 )
  188. {
  189. update( p, n );
  190. result();
  191. }
  192. }
  193. md5_128( void const * p, std::size_t n ): md5_128( static_cast<unsigned char const*>( p ), n )
  194. {
  195. }
  196. BOOST_CXX14_CONSTEXPR void update( unsigned char const* p, std::size_t n )
  197. {
  198. BOOST_ASSERT( m_ == n_ % N );
  199. if( n == 0 ) return;
  200. n_ += n;
  201. if( m_ > 0 )
  202. {
  203. std::size_t k = N - m_;
  204. if( n < k )
  205. {
  206. k = n;
  207. }
  208. detail::memcpy( buffer_ + m_, p, k );
  209. p += k;
  210. n -= k;
  211. m_ += k;
  212. if( m_ < N ) return;
  213. BOOST_ASSERT( m_ == N );
  214. transform( buffer_ );
  215. m_ = 0;
  216. detail::memset( buffer_, 0, N );
  217. }
  218. BOOST_ASSERT( m_ == 0 );
  219. while( n >= N )
  220. {
  221. transform( p );
  222. p += N;
  223. n -= N;
  224. }
  225. BOOST_ASSERT( n < N );
  226. if( n > 0 )
  227. {
  228. detail::memcpy( buffer_, p, n );
  229. m_ = n;
  230. }
  231. BOOST_ASSERT( m_ == n_ % N );
  232. }
  233. void update( void const* pv, std::size_t n )
  234. {
  235. unsigned char const* p = static_cast<unsigned char const*>( pv );
  236. update( p, n );
  237. }
  238. BOOST_CXX14_CONSTEXPR result_type result()
  239. {
  240. BOOST_ASSERT( m_ == n_ % N );
  241. unsigned char bits[ 8 ] = {};
  242. detail::write64le( bits, n_ * 8 );
  243. std::size_t k = m_ < 56? 56 - m_: 120 - m_;
  244. unsigned char padding[ 64 ] = { 0x80 };
  245. update( padding, k );
  246. update( bits, 8 );
  247. BOOST_ASSERT( m_ == 0 );
  248. result_type digest = {{}};
  249. for( int i = 0; i < 4; ++i )
  250. {
  251. detail::write32le( digest.data() + i * 4, state_[ i ] );
  252. }
  253. return digest;
  254. }
  255. };
  256. using hmac_md5_128 = hmac<md5_128>;
  257. } // namespace hash2
  258. } // namespace boost
  259. #endif // #ifndef BOOST_HASH2_MD5_HPP_INCLUDED