sha1.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. // This is a byte oriented implementation
  10. // Note: this implementation does not handle message longer than
  11. // 2^32 bytes.
  12. #ifndef BOOST_UUID_SHA1_H
  13. #define BOOST_UUID_SHA1_H
  14. #include <boost/static_assert.hpp>
  15. #include <cstddef>
  16. #ifdef BOOST_NO_STDC_NAMESPACE
  17. namespace std {
  18. using ::size_t;
  19. } // namespace std
  20. #endif
  21. namespace boost {
  22. namespace uuids {
  23. namespace detail {
  24. BOOST_STATIC_ASSERT(sizeof(unsigned char)*8 == 8);
  25. BOOST_STATIC_ASSERT(sizeof(unsigned int)*8 == 32);
  26. inline unsigned int left_rotate(unsigned int x, std::size_t n)
  27. {
  28. return (x<<n) ^ (x>> (32-n));
  29. }
  30. class sha1
  31. {
  32. public:
  33. typedef unsigned int(&digest_type)[5];
  34. public:
  35. sha1();
  36. void reset();
  37. void process_byte(unsigned char byte);
  38. void process_block(void const* bytes_begin, void const* bytes_end);
  39. void process_bytes(void const* buffer, std::size_t byte_count);
  40. void get_digest(digest_type digest);
  41. private:
  42. void process_block();
  43. private:
  44. unsigned int h_[5];
  45. unsigned char block_[64];
  46. std::size_t block_byte_index_;
  47. std::size_t byte_count_;
  48. };
  49. inline sha1::sha1()
  50. {
  51. reset();
  52. }
  53. inline void sha1::reset()
  54. {
  55. h_[0] = 0x67452301;
  56. h_[1] = 0xEFCDAB89;
  57. h_[2] = 0x98BADCFE;
  58. h_[3] = 0x10325476;
  59. h_[4] = 0xC3D2E1F0;
  60. block_byte_index_ = 0;
  61. byte_count_ = 0;
  62. }
  63. inline void sha1::process_byte(unsigned char byte)
  64. {
  65. block_[block_byte_index_++] = byte;
  66. ++byte_count_;
  67. if (block_byte_index_ == 64) {
  68. block_byte_index_ = 0;
  69. process_block();
  70. }
  71. }
  72. inline void sha1::process_block(void const* bytes_begin, void const* bytes_end)
  73. {
  74. unsigned char const* begin = static_cast<unsigned char const*>(bytes_begin);
  75. unsigned char const* end = static_cast<unsigned char const*>(bytes_end);
  76. for(; begin != end; ++begin) {
  77. process_byte(*begin);
  78. }
  79. }
  80. inline void sha1::process_bytes(void const* buffer, std::size_t byte_count)
  81. {
  82. unsigned char const* b = static_cast<unsigned char const*>(buffer);
  83. process_block(b, b+byte_count);
  84. }
  85. inline void sha1::process_block()
  86. {
  87. unsigned int w[80];
  88. for (std::size_t i=0; i<16; ++i) {
  89. w[i] = (block_[i*4 + 0] << 24);
  90. w[i] |= (block_[i*4 + 1] << 16);
  91. w[i] |= (block_[i*4 + 2] << 8);
  92. w[i] |= (block_[i*4 + 3]);
  93. }
  94. for (std::size_t i=16; i<80; ++i) {
  95. w[i] = left_rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
  96. }
  97. unsigned int a = h_[0];
  98. unsigned int b = h_[1];
  99. unsigned int c = h_[2];
  100. unsigned int d = h_[3];
  101. unsigned int e = h_[4];
  102. for (std::size_t i=0; i<80; ++i) {
  103. unsigned int f;
  104. unsigned int k;
  105. if (i<20) {
  106. f = (b & c) | (~b & d);
  107. k = 0x5A827999;
  108. } else if (i<40) {
  109. f = b ^ c ^ d;
  110. k = 0x6ED9EBA1;
  111. } else if (i<60) {
  112. f = (b & c) | (b & d) | (c & d);
  113. k = 0x8F1BBCDC;
  114. } else {
  115. f = b ^ c ^ d;
  116. k = 0xCA62C1D6;
  117. }
  118. unsigned temp = left_rotate(a, 5) + f + e + k + w[i];
  119. e = d;
  120. d = c;
  121. c = left_rotate(b, 30);
  122. b = a;
  123. a = temp;
  124. }
  125. h_[0] += a;
  126. h_[1] += b;
  127. h_[2] += c;
  128. h_[3] += d;
  129. h_[4] += e;
  130. }
  131. inline void sha1::get_digest(digest_type digest)
  132. {
  133. std::size_t bit_count = byte_count_*8;
  134. // append the bit '1' to the message
  135. process_byte(0x80);
  136. // append k bits '0', where k is the minimum number >= 0
  137. // such that the resulting message length is congruent to 56 (mod 64)
  138. // check if there is enough space for padding and bit_count
  139. if (block_byte_index_ > 56) {
  140. // finish this block
  141. while (block_byte_index_ != 0) {
  142. process_byte(0);
  143. }
  144. // one more block
  145. while (block_byte_index_ < 56) {
  146. process_byte(0);
  147. }
  148. } else {
  149. while (block_byte_index_ < 56) {
  150. process_byte(0);
  151. }
  152. }
  153. // append length of message (before pre-processing)
  154. // as a 64-bit big-endian integer
  155. process_byte(0);
  156. process_byte(0);
  157. process_byte(0);
  158. process_byte(0);
  159. process_byte( static_cast<unsigned char>((bit_count>>24) & 0xFF));
  160. process_byte( static_cast<unsigned char>((bit_count>>16) & 0xFF));
  161. process_byte( static_cast<unsigned char>((bit_count>>8 ) & 0xFF));
  162. process_byte( static_cast<unsigned char>((bit_count) & 0xFF));
  163. // get final digest
  164. digest[0] = h_[0];
  165. digest[1] = h_[1];
  166. digest[2] = h_[2];
  167. digest[3] = h_[3];
  168. digest[4] = h_[4];
  169. }
  170. }}} // namespace boost::uuids::detail
  171. #endif