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
0005
0006
0007
0008
0009
0010
0011
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 }
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 );
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 );
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 );
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 );
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 );
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 );
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 );
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 );
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 );
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 );
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 );
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 );
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 }
0367 }
0368
0369 #endif