Back to home page

EIC code displayed by LXR

 
 

    


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

0001 #ifndef BOOST_HASH2_SHA3_HPP_INCLUDED
0002 #define BOOST_HASH2_SHA3_HPP_INCLUDED
0003 
0004 // Copyright 2025 Christian Mazakas.
0005 // Distributed under the Boost Software License, Version 1.0.
0006 // https://www.boost.org/LICENSE_1_0.txt
0007 //
0008 
0009 // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
0010 // https://github.com/XKCP/XKCP/blob/master/Standalone/CompactFIPS202/C/Keccak-readable-and-compact.c
0011 // https://keccak.team/files/Keccak-reference-3.0.pdf
0012 
0013 #include <boost/hash2/digest.hpp>
0014 #include <boost/hash2/hmac.hpp>
0015 #include <boost/hash2/detail/keccak.hpp>
0016 #include <boost/assert.hpp>
0017 #include <boost/config.hpp>
0018 #include <cstdint>
0019 
0020 namespace boost
0021 {
0022 namespace hash2
0023 {
0024 namespace detail
0025 {
0026 
0027 template<std::uint8_t PaddingDelim, int C, int D>
0028 struct keccak_base
0029 {
0030 private:
0031 
0032     static constexpr int R = 1600 - C;
0033 
0034     unsigned char state_[ 200 ] = {};
0035     std::size_t m_ = 0;
0036 
0037     bool finalized_ = false;
0038 
0039 public:
0040 
0041     using result_type = digest<D / 8>;
0042     static constexpr std::size_t block_size = R / 8;
0043 
0044     void update( void const* pv, std::size_t n )
0045     {
0046         unsigned char const* p = static_cast<unsigned char const*>( pv );
0047         update( p, n );
0048     }
0049 
0050     BOOST_HASH2_SHA3_CONSTEXPR void update( unsigned char const* p, std::size_t n )
0051     {
0052         finalized_ = false;
0053 
0054         auto const block_len = R / 8;
0055 
0056         if( m_ > 0 )
0057         {
0058             std::size_t k = block_len - m_;
0059 
0060             if( n < k )
0061             {
0062                 k = n;
0063             }
0064 
0065             for( std::size_t i = 0; i < k; ++i )
0066             {
0067                 state_[ m_ + i ] ^= p[ i ];
0068             }
0069 
0070             p += k;
0071             n -= k;
0072             m_ += k;
0073 
0074             if( m_ < block_len ) return;
0075 
0076             BOOST_ASSERT( m_ == block_len );
0077 
0078             keccak_permute( state_ );
0079             m_ = 0;
0080         }
0081 
0082         while( n >= block_len )
0083         {
0084             for( int i = 0; i < block_len; ++i )
0085             {
0086                 state_[ i ] ^= p[ i ];
0087             }
0088 
0089             keccak_permute( state_ );
0090 
0091             p += block_len;
0092             n -= block_len;
0093         }
0094 
0095         BOOST_ASSERT( n < block_len );
0096 
0097         if( n > 0 )
0098         {
0099             for( std::size_t i = 0; i < n; ++i )
0100             {
0101                 state_[ i ] ^= p[ i ];
0102             }
0103 
0104             m_ = n;
0105         }
0106 
0107         BOOST_ASSERT( m_ == n % block_len );
0108     }
0109 
0110     BOOST_HASH2_SHA3_CONSTEXPR result_type result()
0111     {
0112         result_type digest;
0113 
0114         if( !finalized_ )
0115         {
0116             state_[ m_ ] ^= PaddingDelim;
0117             state_[ R / 8 - 1 ] ^= 0x80;
0118 
0119             m_ = 0;
0120             finalized_ = true;
0121         }
0122 
0123         keccak_permute( state_ );
0124         detail::memcpy( digest.data(), state_, digest.size() );
0125 
0126         return digest;
0127     }
0128 };
0129 
0130 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
0131 
0132 template<std::uint8_t PaddingDelim, int C, int D>
0133 constexpr std::size_t keccak_base<PaddingDelim, C, D>::block_size;
0134 
0135 #endif
0136 
0137 } // namespace detail
0138 
0139 class sha3_224: public detail::keccak_base<0x06, 2 * 224, 224>
0140 {
0141 public:
0142 
0143     BOOST_HASH2_SHA3_CONSTEXPR sha3_224()
0144     {
0145     }
0146 
0147     BOOST_HASH2_SHA3_CONSTEXPR explicit sha3_224( std::uint64_t seed )
0148     {
0149         if( seed != 0 )
0150         {
0151             unsigned char tmp[ 8 ] = {};
0152 
0153             detail::write64le( tmp, seed );
0154             update( tmp, 8 );
0155 
0156             result();
0157             update( tmp, 0 ); // sets finalized_ to false
0158         }
0159     }
0160 
0161     BOOST_HASH2_SHA3_CONSTEXPR sha3_224( unsigned char const * p, std::size_t n )
0162     {
0163         if( n != 0 )
0164         {
0165             update( p, n );
0166             result();
0167             update( p, 0 ); // sets finalized_ to false
0168         }
0169     }
0170 
0171     sha3_224( void const * p, std::size_t n ): sha3_224( static_cast<unsigned char const*>( p ), n )
0172     {
0173     }
0174 };
0175 
0176 class sha3_256: public detail::keccak_base<0x06, 2 * 256, 256>
0177 {
0178 public:
0179 
0180     BOOST_HASH2_SHA3_CONSTEXPR sha3_256()
0181     {
0182     }
0183 
0184     BOOST_HASH2_SHA3_CONSTEXPR explicit sha3_256( std::uint64_t seed )
0185     {
0186         if( seed != 0 )
0187         {
0188             unsigned char tmp[ 8 ] = {};
0189 
0190             detail::write64le( tmp, seed );
0191             update( tmp, 8 );
0192 
0193             result();
0194             update( tmp, 0 ); // sets finalized_ to false
0195         }
0196     }
0197 
0198     BOOST_HASH2_SHA3_CONSTEXPR sha3_256( unsigned char const * p, std::size_t n )
0199     {
0200         if( n != 0 )
0201         {
0202             update( p, n );
0203             result();
0204             update( p, 0 ); // sets finalized_ to false
0205         }
0206     }
0207 
0208     sha3_256( void const * p, std::size_t n ): sha3_256( static_cast<unsigned char const*>( p ), n )
0209     {
0210     }
0211 };
0212 
0213 class sha3_384: public detail::keccak_base<0x06, 2 * 384, 384>
0214 {
0215 public:
0216 
0217     BOOST_HASH2_SHA3_CONSTEXPR sha3_384()
0218     {
0219     }
0220 
0221     BOOST_HASH2_SHA3_CONSTEXPR explicit sha3_384( std::uint64_t seed )
0222     {
0223         if( seed != 0 )
0224         {
0225             unsigned char tmp[ 8 ] = {};
0226 
0227             detail::write64le( tmp, seed );
0228             update( tmp, 8 );
0229 
0230             result();
0231             update( tmp, 0 ); // sets finalized_ to false
0232         }
0233     }
0234 
0235     BOOST_HASH2_SHA3_CONSTEXPR sha3_384( unsigned char const * p, std::size_t n )
0236     {
0237         if( n != 0 )
0238         {
0239             update( p, n );
0240             result();
0241             update( p, 0 ); // sets finalized_ to false
0242         }
0243     }
0244 
0245     sha3_384( void const * p, std::size_t n ): sha3_384( static_cast<unsigned char const*>( p ), n )
0246     {
0247     }
0248 };
0249 
0250 class sha3_512: public detail::keccak_base<0x06, 2 * 512, 512>
0251 {
0252 public:
0253 
0254     BOOST_HASH2_SHA3_CONSTEXPR sha3_512()
0255     {
0256     }
0257 
0258     BOOST_HASH2_SHA3_CONSTEXPR explicit sha3_512( std::uint64_t seed )
0259     {
0260         if( seed != 0 )
0261         {
0262             unsigned char tmp[ 8 ] = {};
0263 
0264             detail::write64le( tmp, seed );
0265             update( tmp, 8 );
0266 
0267             result();
0268             update( tmp, 0 ); // sets finalized_ to false
0269         }
0270     }
0271 
0272     BOOST_HASH2_SHA3_CONSTEXPR sha3_512( unsigned char const * p, std::size_t n )
0273     {
0274         if( n != 0 )
0275         {
0276             update( p, n );
0277             result();
0278             update( p, 0 ); // sets finalized_ to false
0279         }
0280     }
0281 
0282     sha3_512( void const * p, std::size_t n ): sha3_512( static_cast<unsigned char const*>( p ), n )
0283     {
0284     }
0285 };
0286 
0287 class shake_128: public detail::keccak_base<0x1f, 256, 1600 - 256>
0288 {
0289 public:
0290 
0291     BOOST_HASH2_SHA3_CONSTEXPR shake_128()
0292     {
0293     }
0294 
0295     BOOST_HASH2_SHA3_CONSTEXPR explicit shake_128( std::uint64_t seed )
0296     {
0297         if( seed != 0 )
0298         {
0299             unsigned char tmp[ 8 ] = {};
0300 
0301             detail::write64le( tmp, seed );
0302             update( tmp, 8 );
0303 
0304             result();
0305             update( tmp, 0 ); // sets finalized_ to false
0306         }
0307     }
0308 
0309     BOOST_HASH2_SHA3_CONSTEXPR shake_128( unsigned char const * p, std::size_t n )
0310     {
0311         if( n != 0 )
0312         {
0313             update( p, n );
0314             result();
0315             update( p, 0 ); // sets finalized_ to false
0316         }
0317     }
0318 
0319     shake_128( void const * p, std::size_t n ): shake_128( static_cast<unsigned char const*>( p ), n )
0320     {
0321     }
0322 };
0323 
0324 class shake_256: public detail::keccak_base<0x1f, 512, 1600 - 512>
0325 {
0326 public:
0327 
0328     BOOST_HASH2_SHA3_CONSTEXPR shake_256()
0329     {
0330     }
0331 
0332     BOOST_HASH2_SHA3_CONSTEXPR explicit shake_256( std::uint64_t seed )
0333     {
0334         if( seed != 0 )
0335         {
0336             unsigned char tmp[ 8 ] = {};
0337 
0338             detail::write64le( tmp, seed );
0339             update( tmp, 8 );
0340 
0341             result();
0342             update( tmp, 0 ); // sets finalized_ to false
0343         }
0344     }
0345 
0346     BOOST_HASH2_SHA3_CONSTEXPR shake_256( unsigned char const * p, std::size_t n )
0347     {
0348         if( n != 0 )
0349         {
0350             update( p, n );
0351             result();
0352             update( p, 0 ); // sets finalized_ to false
0353         }
0354     }
0355 
0356     shake_256( void const * p, std::size_t n ): shake_256( static_cast<unsigned char const*>( p ), n )
0357     {
0358     }
0359 };
0360 
0361 using hmac_sha3_224 = hmac<sha3_224>;
0362 using hmac_sha3_256 = hmac<sha3_256>;
0363 using hmac_sha3_384 = hmac<sha3_384>;
0364 using hmac_sha3_512 = hmac<sha3_512>;
0365 
0366 } // namespace hash2
0367 } // namespace boost
0368 
0369 #endif // BOOST_HASH2_SHA3_HPP_INCLUDED