sha1.hpp 5.9 KB

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