161 lines
3.7 KiB
C++
161 lines
3.7 KiB
C++
#ifndef BOOST_UUID_DETAIL_CHACHA20_HPP_INCLUDED
|
|
#define BOOST_UUID_DETAIL_CHACHA20_HPP_INCLUDED
|
|
|
|
// Copyright 2024 Peter Dimov
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// https://www.boost.org/LICENSE_1_0.txt
|
|
|
|
#include <limits>
|
|
#include <cstdint>
|
|
#include <cstddef>
|
|
|
|
namespace boost {
|
|
namespace uuids {
|
|
namespace detail {
|
|
|
|
class chacha20_12
|
|
{
|
|
private:
|
|
|
|
std::uint32_t state_[ 16 ];
|
|
std::uint32_t block_[ 16 ];
|
|
std::size_t index_;
|
|
|
|
private:
|
|
|
|
static inline std::uint32_t rotl( std::uint32_t x, int n ) noexcept
|
|
{
|
|
return ( x << n ) | ( x >> (32 - n) );
|
|
}
|
|
|
|
static inline void quarter_round( std::uint32_t (&x)[ 16 ], int a, int b, int c, int d ) noexcept
|
|
{
|
|
x[ a ] += x[ b ]; x[ d ] = rotl( x[d] ^ x[a], 16 );
|
|
x[ c ] += x[ d ]; x[ b ] = rotl( x[b] ^ x[c], 12 );
|
|
x[ a ] += x[ b ]; x[ d ] = rotl( x[d] ^ x[a], 8 );
|
|
x[ c ] += x[ d ]; x[ b ] = rotl( x[b] ^ x[c], 7 );
|
|
}
|
|
|
|
void get_next_block() noexcept
|
|
{
|
|
for( int i = 0; i < 16; ++i )
|
|
{
|
|
block_[ i ] = state_[ i ];
|
|
}
|
|
|
|
for( int i = 0; i < 6; ++i )
|
|
{
|
|
quarter_round( block_, 0, 4, 8, 12 );
|
|
quarter_round( block_, 1, 5, 9, 13 );
|
|
quarter_round( block_, 2, 6, 10, 14 );
|
|
quarter_round( block_, 3, 7, 11, 15 );
|
|
quarter_round( block_, 0, 5, 10, 15 );
|
|
quarter_round( block_, 1, 6, 11, 12 );
|
|
quarter_round( block_, 2, 7, 8, 13 );
|
|
quarter_round( block_, 3, 4, 9, 14 );
|
|
}
|
|
|
|
for( int i = 0; i < 16; ++i )
|
|
{
|
|
block_[ i ] += state_[ i ];
|
|
}
|
|
|
|
if( ++state_[ 12 ] == 0 ) ++state_[ 13 ];
|
|
}
|
|
|
|
public:
|
|
|
|
using result_type = std::uint32_t;
|
|
|
|
chacha20_12() noexcept: index_( 16 )
|
|
{
|
|
state_[ 0 ] = 0x61707865;
|
|
state_[ 1 ] = 0x3320646e;
|
|
state_[ 2 ] = 0x79622d32;
|
|
state_[ 3 ] = 0x6b206574;
|
|
|
|
for( int i = 4; i < 16; ++i )
|
|
{
|
|
state_[ i ] = 0;
|
|
}
|
|
}
|
|
|
|
chacha20_12( std::uint32_t const (&key)[ 8 ], std::uint32_t const (&nonce)[ 2 ] ) noexcept: index_( 16 )
|
|
{
|
|
state_[ 0 ] = 0x61707865;
|
|
state_[ 1 ] = 0x3320646e;
|
|
state_[ 2 ] = 0x79622d32;
|
|
state_[ 3 ] = 0x6b206574;
|
|
|
|
for( int i = 0; i < 8; ++i )
|
|
{
|
|
state_[ i + 4 ] = key[ i ];
|
|
}
|
|
|
|
state_[ 12 ] = 0;
|
|
state_[ 13 ] = 0;
|
|
|
|
state_[ 14 ] = nonce[ 0 ];
|
|
state_[ 15 ] = nonce[ 1 ];
|
|
}
|
|
|
|
// only needed because basic_random_generator looks for it
|
|
void seed() noexcept
|
|
{
|
|
index_ = 16;
|
|
|
|
for( int i = 4; i < 16; ++i )
|
|
{
|
|
state_[ i ] = 0;
|
|
}
|
|
}
|
|
|
|
template<class Seq> void seed( Seq& seq )
|
|
{
|
|
index_ = 16;
|
|
|
|
seq.generate( state_ + 4, state_ + 16 );
|
|
|
|
// reset counter
|
|
state_[ 12 ] = 0;
|
|
state_[ 13 ] = 0;
|
|
}
|
|
|
|
// perturbs the generator state so that it no longer generates
|
|
// the same sequence; useful for e.g. moved from objects
|
|
void perturb() noexcept
|
|
{
|
|
index_ = 16;
|
|
|
|
for( int i = 12; i < 16; ++i )
|
|
{
|
|
++state_[ i ];
|
|
}
|
|
}
|
|
|
|
static constexpr result_type min() noexcept
|
|
{
|
|
return std::numeric_limits<result_type>::min();
|
|
}
|
|
|
|
static constexpr result_type max() noexcept
|
|
{
|
|
return std::numeric_limits<result_type>::max();
|
|
}
|
|
|
|
result_type operator()() noexcept
|
|
{
|
|
if( index_ == 16 )
|
|
{
|
|
get_next_block();
|
|
index_ = 0;
|
|
}
|
|
|
|
return block_[ index_++ ];
|
|
}
|
|
};
|
|
|
|
}}} // namespace boost::uuids::detail
|
|
|
|
#endif // #ifndef BOOST_UUID_DETAIL_SHA1_HPP_INCLUDED
|