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