Back to home page

EIC code displayed by LXR

 
 

    


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 // Copyright 2007 Andy Tompkins.
0005 // Distributed under the Boost Software License, Version 1.0. (See
0006 // accompanying file LICENSE_1_0.txt or copy at
0007 // https://www.boost.org/LICENSE_1_0.txt)
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     // size_t max value = 0xFFFFFFFF
0086     //if (bit_count_low + 8 >= 0x100000000) { // would overflow
0087     //if (bit_count_low >= 0x100000000-8) {
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     // RFC 4122 Section 4.1.3
0176         return uuid::version_name_based_sha1;
0177 }
0178 
0179 inline void sha1::get_digest(digest_type& digest)
0180 {
0181     // append the bit '1' to the message
0182     process_byte_impl(0x80);
0183 
0184     // append k bits '0', where k is the minimum number >= 0
0185     // such that the resulting message length is congruent to 56 (mod 64)
0186     // check if there is enough space for padding and bit_count
0187     if (block_byte_index_ > 56) {
0188         // finish this block
0189         while (block_byte_index_ != 0) {
0190             process_byte_impl(0);
0191         }
0192 
0193         // one more block
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     // append length of message (before pre-processing)
0204     // as a 64-bit big-endian integer
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     // get final digest
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 }}} // namespace boost::uuids::detail
0223 
0224 #endif // #ifndef BOOST_UUID_DETAIL_SHA1_HPP_INCLUDED