sha1.hpp 6.0 KB

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