sha1.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #ifndef BOOST_UUID_DETAIL_SHA1_HPP_INCLUDED
  2. #define BOOST_UUID_DETAIL_SHA1_HPP_INCLUDED
  3. // Copyright 2007 Andy Tompkins.
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // https://www.boost.org/LICENSE_1_0.txt)
  7. #include <boost/uuid/detail/endian.hpp>
  8. #include <boost/uuid/detail/static_assert.hpp>
  9. #include <boost/uuid/uuid.hpp> // for version
  10. #include <cstddef>
  11. #include <stdexcept>
  12. #include <string>
  13. namespace boost {
  14. namespace uuids {
  15. namespace detail {
  16. BOOST_UUID_STATIC_ASSERT(sizeof(unsigned char)*8 == 8);
  17. BOOST_UUID_STATIC_ASSERT(sizeof(unsigned int)*8 == 32);
  18. inline unsigned int left_rotate(unsigned int x, std::size_t n)
  19. {
  20. return (x<<n) ^ (x>> (32-n));
  21. }
  22. class sha1
  23. {
  24. public:
  25. typedef unsigned char digest_type[ 20 ];
  26. public:
  27. sha1();
  28. void reset();
  29. void process_byte(unsigned char byte);
  30. void process_block(void const* bytes_begin, void const* bytes_end);
  31. void process_bytes(void const* buffer, std::size_t byte_count);
  32. void get_digest(digest_type& digest);
  33. unsigned char get_version() const;
  34. private:
  35. void process_block();
  36. void process_byte_impl(unsigned char byte);
  37. private:
  38. unsigned int h_[5];
  39. unsigned char block_[64];
  40. std::size_t block_byte_index_;
  41. std::size_t bit_count_low;
  42. std::size_t bit_count_high;
  43. };
  44. inline sha1::sha1()
  45. {
  46. reset();
  47. }
  48. inline void sha1::reset()
  49. {
  50. h_[0] = 0x67452301;
  51. h_[1] = 0xEFCDAB89;
  52. h_[2] = 0x98BADCFE;
  53. h_[3] = 0x10325476;
  54. h_[4] = 0xC3D2E1F0;
  55. block_byte_index_ = 0;
  56. bit_count_low = 0;
  57. bit_count_high = 0;
  58. }
  59. inline void sha1::process_byte(unsigned char byte)
  60. {
  61. process_byte_impl(byte);
  62. // size_t max value = 0xFFFFFFFF
  63. //if (bit_count_low + 8 >= 0x100000000) { // would overflow
  64. //if (bit_count_low >= 0x100000000-8) {
  65. if (bit_count_low < 0xFFFFFFF8) {
  66. bit_count_low += 8;
  67. } else {
  68. bit_count_low = 0;
  69. ++bit_count_high;
  70. }
  71. }
  72. inline void sha1::process_byte_impl(unsigned char byte)
  73. {
  74. block_[block_byte_index_++] = byte;
  75. if (block_byte_index_ == 64) {
  76. block_byte_index_ = 0;
  77. process_block();
  78. }
  79. }
  80. inline void sha1::process_block(void const* bytes_begin, void const* bytes_end)
  81. {
  82. unsigned char const* begin = static_cast<unsigned char const*>(bytes_begin);
  83. unsigned char const* end = static_cast<unsigned char const*>(bytes_end);
  84. for(; begin != end; ++begin) {
  85. process_byte(*begin);
  86. }
  87. }
  88. inline void sha1::process_bytes(void const* buffer, std::size_t byte_count)
  89. {
  90. unsigned char const* b = static_cast<unsigned char const*>(buffer);
  91. process_block(b, b+byte_count);
  92. }
  93. inline void sha1::process_block()
  94. {
  95. unsigned int w[80];
  96. for (std::size_t i=0; i<16; ++i) {
  97. w[i] = (block_[i*4 + 0] << 24);
  98. w[i] |= (block_[i*4 + 1] << 16);
  99. w[i] |= (block_[i*4 + 2] << 8);
  100. w[i] |= (block_[i*4 + 3]);
  101. }
  102. for (std::size_t i=16; i<80; ++i) {
  103. w[i] = left_rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
  104. }
  105. unsigned int a = h_[0];
  106. unsigned int b = h_[1];
  107. unsigned int c = h_[2];
  108. unsigned int d = h_[3];
  109. unsigned int e = h_[4];
  110. for (std::size_t i=0; i<80; ++i) {
  111. unsigned int f;
  112. unsigned int k;
  113. if (i<20) {
  114. f = (b & c) | (~b & d);
  115. k = 0x5A827999;
  116. } else if (i<40) {
  117. f = b ^ c ^ d;
  118. k = 0x6ED9EBA1;
  119. } else if (i<60) {
  120. f = (b & c) | (b & d) | (c & d);
  121. k = 0x8F1BBCDC;
  122. } else {
  123. f = b ^ c ^ d;
  124. k = 0xCA62C1D6;
  125. }
  126. unsigned temp = left_rotate(a, 5) + f + e + k + w[i];
  127. e = d;
  128. d = c;
  129. c = left_rotate(b, 30);
  130. b = a;
  131. a = temp;
  132. }
  133. h_[0] += a;
  134. h_[1] += b;
  135. h_[2] += c;
  136. h_[3] += d;
  137. h_[4] += e;
  138. }
  139. inline unsigned char sha1::get_version() const
  140. {
  141. // RFC 4122 Section 4.1.3
  142. return uuid::version_name_based_sha1;
  143. }
  144. inline void sha1::get_digest(digest_type& digest)
  145. {
  146. // append the bit '1' to the message
  147. process_byte_impl(0x80);
  148. // append k bits '0', where k is the minimum number >= 0
  149. // such that the resulting message length is congruent to 56 (mod 64)
  150. // check if there is enough space for padding and bit_count
  151. if (block_byte_index_ > 56) {
  152. // finish this block
  153. while (block_byte_index_ != 0) {
  154. process_byte_impl(0);
  155. }
  156. // one more block
  157. while (block_byte_index_ < 56) {
  158. process_byte_impl(0);
  159. }
  160. } else {
  161. while (block_byte_index_ < 56) {
  162. process_byte_impl(0);
  163. }
  164. }
  165. // append length of message (before pre-processing)
  166. // as a 64-bit big-endian integer
  167. process_byte_impl( static_cast<unsigned char>((bit_count_high>>24) & 0xFF) );
  168. process_byte_impl( static_cast<unsigned char>((bit_count_high>>16) & 0xFF) );
  169. process_byte_impl( static_cast<unsigned char>((bit_count_high>>8 ) & 0xFF) );
  170. process_byte_impl( static_cast<unsigned char>((bit_count_high) & 0xFF) );
  171. process_byte_impl( static_cast<unsigned char>((bit_count_low>>24) & 0xFF) );
  172. process_byte_impl( static_cast<unsigned char>((bit_count_low>>16) & 0xFF) );
  173. process_byte_impl( static_cast<unsigned char>((bit_count_low>>8 ) & 0xFF) );
  174. process_byte_impl( static_cast<unsigned char>((bit_count_low) & 0xFF) );
  175. // get final digest
  176. detail::store_big_u32( digest + 0, h_[0] );
  177. detail::store_big_u32( digest + 4, h_[1] );
  178. detail::store_big_u32( digest + 8, h_[2] );
  179. detail::store_big_u32( digest + 12, h_[3] );
  180. detail::store_big_u32( digest + 16, h_[4] );
  181. }
  182. }}} // namespace boost::uuids::detail
  183. #endif // #ifndef BOOST_UUID_DETAIL_SHA1_HPP_INCLUDED