Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:33:45

0001 #ifndef BOOST_HASH2_SIPHASH_HPP_INCLUDED
0002 #define BOOST_HASH2_SIPHASH_HPP_INCLUDED
0003 
0004 // Copyright 2017, 2018 Peter Dimov.
0005 // Distributed under the Boost Software License, Version 1.0.
0006 // https://www.boost.org/LICENSE_1_0.txt
0007 //
0008 // SipHash, https://131002.net/siphash/
0009 
0010 #include <boost/hash2/detail/read.hpp>
0011 #include <boost/hash2/detail/rot.hpp>
0012 #include <boost/hash2/detail/memcpy.hpp>
0013 #include <boost/hash2/detail/memset.hpp>
0014 #include <boost/hash2/detail/config.hpp>
0015 #include <boost/assert.hpp>
0016 #include <cstdint>
0017 #include <cstring>
0018 #include <cstddef>
0019 
0020 namespace boost
0021 {
0022 namespace hash2
0023 {
0024 
0025 class siphash_64
0026 {
0027 private:
0028 
0029     std::uint64_t v0 = 0x736f6d6570736575ULL;
0030     std::uint64_t v1 = 0x646f72616e646f6dULL;
0031     std::uint64_t v2 = 0x6c7967656e657261ULL;
0032     std::uint64_t v3 = 0x7465646279746573ULL;
0033 
0034     unsigned char buffer_[ 8 ] = {};
0035     std::size_t m_ = 0; // == n_ % 8
0036 
0037     std::uint64_t n_ = 0;
0038 
0039 private:
0040 
0041     BOOST_CXX14_CONSTEXPR void sipround()
0042     {
0043         v0 += v1;
0044         v1 = detail::rotl(v1, 13);
0045         v1 ^= v0;
0046         v0 = detail::rotl(v0, 32);
0047         v2 += v3;
0048         v3 = detail::rotl(v3, 16);
0049         v3 ^= v2;
0050         v0 += v3;
0051         v3 = detail::rotl(v3, 21);
0052         v3 ^= v0;
0053         v2 += v1;
0054         v1 = detail::rotl(v1, 17);
0055         v1 ^= v2;
0056         v2 = detail::rotl(v2, 32);
0057     }
0058 
0059     BOOST_CXX14_CONSTEXPR void update_( unsigned char const * p )
0060     {
0061         std::uint64_t m = detail::read64le( p );
0062 
0063         v3 ^= m;
0064 
0065         sipround();
0066         sipround();
0067 
0068         v0 ^= m;
0069     }
0070 
0071 public:
0072 
0073     using result_type = std::uint64_t;
0074 
0075     siphash_64() = default;
0076 
0077     BOOST_CXX14_CONSTEXPR explicit siphash_64( std::uint64_t seed )
0078     {
0079         v0 ^= seed;
0080         v2 ^= seed;
0081     }
0082 
0083     BOOST_CXX14_CONSTEXPR siphash_64( unsigned char const * p, std::size_t n )
0084     {
0085         if( n == 16 )
0086         {
0087             std::uint64_t k0 = detail::read64le( p + 0 );
0088             std::uint64_t k1 = detail::read64le( p + 8 );
0089 
0090             v0 ^= k0;
0091             v1 ^= k1;
0092             v2 ^= k0;
0093             v3 ^= k1;
0094         }
0095         else if( n != 0 )
0096         {
0097             update( p, n );
0098             result();
0099         }
0100     }
0101 
0102     siphash_64( void const * p, std::size_t n ): siphash_64( static_cast<unsigned char const*>( p ), n )
0103     {
0104     }
0105 
0106     BOOST_CXX14_CONSTEXPR void update( unsigned char const* p, std::size_t n )
0107     {
0108         BOOST_ASSERT( m_ == n_ % 8 );
0109 
0110         if( n == 0 ) return;
0111 
0112         n_ += n;
0113 
0114         if( m_ > 0 )
0115         {
0116             std::size_t k = 8 - m_;
0117 
0118             if( n < k )
0119             {
0120                 k = n;
0121             }
0122 
0123             detail::memcpy( buffer_ + m_, p, k );
0124 
0125             p += k;
0126             n -= k;
0127             m_ += k;
0128 
0129             if( m_ < 8 ) return;
0130 
0131             BOOST_ASSERT( m_ == 8 );
0132 
0133             update_( buffer_ );
0134             m_ = 0;
0135 
0136             // clear buffered plaintext
0137             detail::memset( buffer_, 0, 8 );
0138         }
0139 
0140         BOOST_ASSERT( m_ == 0 );
0141 
0142         while( n >= 8 )
0143         {
0144             update_( p );
0145 
0146             p += 8;
0147             n -= 8;
0148         }
0149 
0150         BOOST_ASSERT( n < 8 );
0151 
0152         if( n > 0 )
0153         {
0154             detail::memcpy( buffer_, p, n );
0155             m_ = n;
0156         }
0157 
0158         BOOST_ASSERT( m_ == n_ % 8 );
0159     }
0160 
0161     void update( void const* pv, std::size_t n )
0162     {
0163         unsigned char const* p = static_cast<unsigned char const*>( pv );
0164         update( p, n );
0165     }
0166 
0167     BOOST_CXX14_CONSTEXPR std::uint64_t result()
0168     {
0169         BOOST_ASSERT( m_ == n_ % 8 );
0170 
0171         detail::memset( buffer_ + m_, 0, 8 - m_ );
0172 
0173         buffer_[ 7 ] = static_cast<unsigned char>( n_ & 0xFF );
0174 
0175         update_( buffer_ );
0176 
0177         v2 ^= 0xFF;
0178 
0179         sipround();
0180         sipround();
0181         sipround();
0182         sipround();
0183 
0184         n_ += 8 - m_;
0185         m_ = 0;
0186 
0187         // clear buffered plaintext
0188         detail::memset( buffer_, 0, 8 );
0189 
0190         return v0 ^ v1 ^ v2 ^ v3;
0191     }
0192 };
0193 
0194 class siphash_32
0195 {
0196 private:
0197 
0198     std::uint32_t v0 = 0;
0199     std::uint32_t v1 = 0;
0200     std::uint32_t v2 = 0x6c796765;
0201     std::uint32_t v3 = 0x74656462;
0202 
0203     unsigned char buffer_[ 4 ] = {};
0204     std::uint32_t m_ = 0; // == n_ % 4
0205 
0206     std::uint32_t n_ = 0;
0207 
0208 private:
0209 
0210     BOOST_CXX14_CONSTEXPR void sipround()
0211     {
0212         v0 += v1;
0213         v1 = detail::rotl(v1, 5);
0214         v1 ^= v0;
0215         v0 = detail::rotl(v0, 16);
0216         v2 += v3;
0217         v3 = detail::rotl(v3, 8);
0218         v3 ^= v2;
0219         v0 += v3;
0220         v3 = detail::rotl(v3, 7);
0221         v3 ^= v0;
0222         v2 += v1;
0223         v1 = detail::rotl(v1, 13);
0224         v1 ^= v2;
0225         v2 = detail::rotl(v2, 16);
0226     }
0227 
0228     BOOST_CXX14_CONSTEXPR void update_( unsigned char const * p )
0229     {
0230         std::uint32_t m = detail::read32le( p );
0231 
0232         v3 ^= m;
0233 
0234         sipround();
0235         sipround();
0236 
0237         v0 ^= m;
0238     }
0239 
0240 public:
0241 
0242     using result_type = std::uint32_t;
0243 
0244     siphash_32() = default;
0245 
0246     BOOST_CXX14_CONSTEXPR explicit siphash_32( std::uint64_t seed )
0247     {
0248         std::uint32_t k0 = static_cast<std::uint32_t>( seed );
0249         std::uint32_t k1 = static_cast<std::uint32_t>( seed >> 32 );
0250 
0251         v0 ^= k0;
0252         v1 ^= k1;
0253         v2 ^= k0;
0254         v3 ^= k1;
0255     }
0256 
0257     BOOST_CXX14_CONSTEXPR siphash_32( unsigned char const * p, std::size_t n )
0258     {
0259         if( n == 8 )
0260         {
0261             std::uint32_t k0 = detail::read32le( p + 0 );
0262             std::uint32_t k1 = detail::read32le( p + 4 );
0263 
0264             v0 ^= k0;
0265             v1 ^= k1;
0266             v2 ^= k0;
0267             v3 ^= k1;
0268         }
0269         else if( n != 0 )
0270         {
0271             update( p, n );
0272             result();
0273         }
0274     }
0275 
0276     siphash_32( void const * p, std::size_t n ): siphash_32( static_cast<unsigned char const*>( p ), n )
0277     {
0278     }
0279 
0280     BOOST_CXX14_CONSTEXPR void update( unsigned char const* p, std::size_t n )
0281     {
0282         BOOST_ASSERT( m_ == n_ % 4 );
0283 
0284         if( n == 0 ) return;
0285 
0286         n_ += static_cast<std::uint32_t>( n );
0287 
0288         if( m_ > 0 )
0289         {
0290             std::uint32_t k = 4 - m_;
0291 
0292             if( n < k )
0293             {
0294                 k = static_cast<std::uint32_t>( n );
0295             }
0296 
0297             detail::memcpy( buffer_ + m_, p, k );
0298 
0299             p += k;
0300             n -= k;
0301             m_ += k;
0302 
0303             if( m_ < 4 ) return;
0304 
0305             BOOST_ASSERT( m_ == 4 );
0306 
0307             update_( buffer_ );
0308             m_ = 0;
0309 
0310             // clear buffered plaintext
0311             detail::memset( buffer_, 0, 4 );
0312         }
0313 
0314         BOOST_ASSERT( m_ == 0 );
0315 
0316         while( n >= 4 )
0317         {
0318             update_( p );
0319 
0320             p += 4;
0321             n -= 4;
0322         }
0323 
0324         BOOST_ASSERT( n < 4 );
0325 
0326         if( n > 0 )
0327         {
0328             detail::memcpy( buffer_, p, n );
0329             m_ = static_cast<std::uint32_t>( n );
0330         }
0331 
0332         BOOST_ASSERT( m_ == n_ % 4 );
0333     }
0334 
0335     void update( void const* pv, std::size_t n )
0336     {
0337         unsigned char const* p = static_cast<unsigned char const*>( pv );
0338         update( p, n );
0339     }
0340 
0341     BOOST_CXX14_CONSTEXPR std::uint32_t result()
0342     {
0343         BOOST_ASSERT( m_ == n_ % 4 );
0344 
0345         detail::memset( buffer_ + m_, 0, 4 - m_ );
0346 
0347         buffer_[ 3 ] = static_cast<unsigned char>( n_ & 0xFF );
0348 
0349         update_( buffer_ );
0350 
0351         v2 ^= 0xFF;
0352 
0353         sipround();
0354         sipround();
0355         sipround();
0356         sipround();
0357 
0358         n_ += 4 - m_;
0359         m_ = 0;
0360 
0361         // clear buffered plaintext
0362         detail::memset( buffer_, 0, 4 );
0363 
0364         return v1 ^ v3;
0365     }
0366 };
0367 
0368 } // namespace hash2
0369 } // namespace boost
0370 
0371 #endif // #ifndef BOOST_HASH2_SIPHASH_HPP_INCLUDED