File indexing completed on 2025-01-30 10:02:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef BOOST_UUID_SHA1_H
0014 #define BOOST_UUID_SHA1_H
0015
0016 #include <boost/static_assert.hpp>
0017 #include <boost/throw_exception.hpp>
0018 #include <boost/uuid/uuid.hpp> // for version
0019 #include <cstddef>
0020 #include <stdexcept>
0021 #include <string>
0022
0023 #ifdef BOOST_NO_STDC_NAMESPACE
0024 namespace std {
0025 using ::size_t;
0026 }
0027 #endif
0028
0029 namespace boost {
0030 namespace uuids {
0031 namespace detail {
0032
0033 BOOST_STATIC_ASSERT(sizeof(unsigned char)*8 == 8);
0034 BOOST_STATIC_ASSERT(sizeof(unsigned int)*8 == 32);
0035
0036 inline unsigned int left_rotate(unsigned int x, std::size_t n)
0037 {
0038 return (x<<n) ^ (x>> (32-n));
0039 }
0040
0041 class sha1
0042 {
0043 public:
0044 typedef unsigned int(digest_type)[5];
0045 public:
0046 sha1();
0047
0048 void reset();
0049
0050 void process_byte(unsigned char byte);
0051 void process_block(void const* bytes_begin, void const* bytes_end);
0052 void process_bytes(void const* buffer, std::size_t byte_count);
0053
0054 void get_digest(digest_type& digest);
0055 unsigned char get_version() const;
0056
0057 private:
0058 void process_block();
0059 void process_byte_impl(unsigned char byte);
0060
0061 private:
0062 unsigned int h_[5];
0063
0064 unsigned char block_[64];
0065
0066 std::size_t block_byte_index_;
0067 std::size_t bit_count_low;
0068 std::size_t bit_count_high;
0069 };
0070
0071 inline sha1::sha1()
0072 {
0073 reset();
0074 }
0075
0076 inline void sha1::reset()
0077 {
0078 h_[0] = 0x67452301;
0079 h_[1] = 0xEFCDAB89;
0080 h_[2] = 0x98BADCFE;
0081 h_[3] = 0x10325476;
0082 h_[4] = 0xC3D2E1F0;
0083
0084 block_byte_index_ = 0;
0085 bit_count_low = 0;
0086 bit_count_high = 0;
0087 }
0088
0089 inline void sha1::process_byte(unsigned char byte)
0090 {
0091 process_byte_impl(byte);
0092
0093
0094
0095
0096 if (bit_count_low < 0xFFFFFFF8) {
0097 bit_count_low += 8;
0098 } else {
0099 bit_count_low = 0;
0100
0101 if (bit_count_high <= 0xFFFFFFFE) {
0102 ++bit_count_high;
0103 } else {
0104 BOOST_THROW_EXCEPTION(std::runtime_error("sha1 too many bytes"));
0105 }
0106 }
0107 }
0108
0109 inline void sha1::process_byte_impl(unsigned char byte)
0110 {
0111 block_[block_byte_index_++] = byte;
0112
0113 if (block_byte_index_ == 64) {
0114 block_byte_index_ = 0;
0115 process_block();
0116 }
0117 }
0118
0119 inline void sha1::process_block(void const* bytes_begin, void const* bytes_end)
0120 {
0121 unsigned char const* begin = static_cast<unsigned char const*>(bytes_begin);
0122 unsigned char const* end = static_cast<unsigned char const*>(bytes_end);
0123 for(; begin != end; ++begin) {
0124 process_byte(*begin);
0125 }
0126 }
0127
0128 inline void sha1::process_bytes(void const* buffer, std::size_t byte_count)
0129 {
0130 unsigned char const* b = static_cast<unsigned char const*>(buffer);
0131 process_block(b, b+byte_count);
0132 }
0133
0134 inline void sha1::process_block()
0135 {
0136 unsigned int w[80];
0137 for (std::size_t i=0; i<16; ++i) {
0138 w[i] = (block_[i*4 + 0] << 24);
0139 w[i] |= (block_[i*4 + 1] << 16);
0140 w[i] |= (block_[i*4 + 2] << 8);
0141 w[i] |= (block_[i*4 + 3]);
0142 }
0143 for (std::size_t i=16; i<80; ++i) {
0144 w[i] = left_rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
0145 }
0146
0147 unsigned int a = h_[0];
0148 unsigned int b = h_[1];
0149 unsigned int c = h_[2];
0150 unsigned int d = h_[3];
0151 unsigned int e = h_[4];
0152
0153 for (std::size_t i=0; i<80; ++i) {
0154 unsigned int f;
0155 unsigned int k;
0156
0157 if (i<20) {
0158 f = (b & c) | (~b & d);
0159 k = 0x5A827999;
0160 } else if (i<40) {
0161 f = b ^ c ^ d;
0162 k = 0x6ED9EBA1;
0163 } else if (i<60) {
0164 f = (b & c) | (b & d) | (c & d);
0165 k = 0x8F1BBCDC;
0166 } else {
0167 f = b ^ c ^ d;
0168 k = 0xCA62C1D6;
0169 }
0170
0171 unsigned temp = left_rotate(a, 5) + f + e + k + w[i];
0172 e = d;
0173 d = c;
0174 c = left_rotate(b, 30);
0175 b = a;
0176 a = temp;
0177 }
0178
0179 h_[0] += a;
0180 h_[1] += b;
0181 h_[2] += c;
0182 h_[3] += d;
0183 h_[4] += e;
0184 }
0185
0186 inline unsigned char sha1::get_version() const
0187 {
0188
0189 return uuid::version_name_based_sha1;
0190 }
0191
0192 inline void sha1::get_digest(digest_type& digest)
0193 {
0194
0195 process_byte_impl(0x80);
0196
0197
0198
0199
0200 if (block_byte_index_ > 56) {
0201
0202 while (block_byte_index_ != 0) {
0203 process_byte_impl(0);
0204 }
0205
0206
0207 while (block_byte_index_ < 56) {
0208 process_byte_impl(0);
0209 }
0210 } else {
0211 while (block_byte_index_ < 56) {
0212 process_byte_impl(0);
0213 }
0214 }
0215
0216
0217
0218 process_byte_impl( static_cast<unsigned char>((bit_count_high>>24) & 0xFF) );
0219 process_byte_impl( static_cast<unsigned char>((bit_count_high>>16) & 0xFF) );
0220 process_byte_impl( static_cast<unsigned char>((bit_count_high>>8 ) & 0xFF) );
0221 process_byte_impl( static_cast<unsigned char>((bit_count_high) & 0xFF) );
0222 process_byte_impl( static_cast<unsigned char>((bit_count_low>>24) & 0xFF) );
0223 process_byte_impl( static_cast<unsigned char>((bit_count_low>>16) & 0xFF) );
0224 process_byte_impl( static_cast<unsigned char>((bit_count_low>>8 ) & 0xFF) );
0225 process_byte_impl( static_cast<unsigned char>((bit_count_low) & 0xFF) );
0226
0227
0228 digest[0] = h_[0];
0229 digest[1] = h_[1];
0230 digest[2] = h_[2];
0231 digest[3] = h_[3];
0232 digest[4] = h_[4];
0233 }
0234
0235 }}}
0236
0237 #endif