2
0
mirror of https://github.com/boostorg/hash2.git synced 2026-01-31 08:12:17 +00:00

Merge branch 'develop' into gh-pages

This commit is contained in:
Peter Dimov
2024-11-07 03:08:08 +02:00
20 changed files with 565 additions and 248 deletions

View File

@@ -53,7 +53,6 @@ are being tested on [Github Actions](https://github.com/pdimov/hash2/actions/) a
## Planned Additions
* Support for endian-independent hashing
* A `std::hash`-compatible adaptor
## License

View File

@@ -59,8 +59,8 @@ Normally, non-cryptographic hash functions have an integer `result_type`,
and cryptographic hash functions have an array-like `result_type`, but
that's not required.
The provided utility function `get_integral_result_type` can be used to
obtain an integer hash value from any valid `result_type`.
The provided utility function `get_integral_result` can be used to obtain
an integer hash value from any valid `result_type`.
### block_size

View File

@@ -22,5 +22,88 @@ using hmac_ripemd_160 = hmac<ripemd_160>;
} // namespace boost
```
This header implements the https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf[RIPEMD-160] algorithm.
## ripemd_160
```
class ripemd_160
{
using result_type = digest<20>;
static constexpr int block_size = 64;
constexpr ripemd_160();
explicit constexpr ripemd_160( std::uint64_t seed );
constexpr ripemd_160( unsigned char const* p, std::size_t n );
void update( void const * pv, std::size_t n );
constexpr void update( unsigned char const* p, std::size_t n );
constexpr result_type result();
};
```
### Constructors
```
constexpr ripemd_160();
```
Default constructor.
Effects: ::
Initializes the internal state of the RIPEMD-160 algorithm to its initial values.
```
explicit constexpr ripemd_160( std::uint64_t seed );
```
Constructor taking an integral seed value.
Effects: ::
Initializes the state as if by default construction, then if `seed` is not zero, performs `update(p, 8); result();` where `p` points to a little-endian representation of the value of `seed`.
Remarks: ::
By convention, if `seed` is zero, the effect of this constructor is the same as default construction.
```
constexpr ripemd_160( unsigned char const* p, std::size_t n );
```
Constructor taking a byte sequence seed.
Effects: ::
Initializes the state as if by default construction, then if `n` is not zero, performs `update(p, n); result()`.
Remarks: ::
By convention, if `n` is zero, the effect of this constructor is the same as default construction.
### update
```
void update( void const* p, std::size_t n );
constexpr void update( unsigned char const* p, std::size_t n );
```
Effects: ::
Updates the internal state of the RIPEMD-160 algorithm from the byte sequence `[p, p+n)`.
Remarks: ::
Consecutive calls to `update` are equivalent to a single call with the concatenated byte sequences of the individual calls.
### result
```
constexpr result_type result();
```
Effects: ::
Pads the accumulated message and finalizes the RIPEMD-160 digest.
Returns: ::
The RIPEMD-160 digest of the message formed from the byte sequences of the preceding calls to `update`.
Remarks: ::
Repeated calls to `result()` return a pseudorandom sequence of `result_type` values, effectively extending the output.

View File

@@ -8,11 +8,28 @@
// HMAC message authentication algorithm, https://tools.ietf.org/html/rfc2104
#include <boost/hash2/detail/write.hpp>
#include <boost/hash2/detail/memcpy.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#include <cstdint>
#include <cstring>
#include <cstddef>
#if !defined(BOOST_NO_CXX14_CONSTEXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 60000)
# define BOOST_HASH2_HMAC_CONSTEXPR constexpr
#else
// libs/hash2/test/concept.cpp:45:7: in constexpr expansion of 'h1.boost::hash2::hmac<H>::hmac<boost::hash2::md5_128>()'
// ./boost/hash2/hmac.hpp:80:13: in constexpr expansion of 'boost::hash2::hmac<H>::init<boost::hash2::md5_128>(0u, 0u)'
// libs/hash2/test/concept.cpp:45:7: internal compiler error: in fold_binary_loc, at fold-const.c:9925
# define BOOST_HASH2_HMAC_CONSTEXPR
#endif
namespace boost
{
namespace hash2
@@ -22,9 +39,8 @@ template<class H> class hmac
{
public:
typedef typename H::result_type result_type;
static const int block_size = H::block_size;
using result_type = typename H::result_type;
static constexpr int block_size = H::block_size;
private:
@@ -33,9 +49,9 @@ private:
private:
void init( unsigned char const * p, std::size_t n )
BOOST_HASH2_HMAC_CONSTEXPR void init( unsigned char const* p, std::size_t n )
{
int const m = block_size;
constexpr std::size_t m = block_size;
unsigned char key[ m ] = {};
@@ -45,27 +61,26 @@ private:
}
else if( n <= m )
{
std::memcpy( key, p, n );
detail::memcpy( key, p, n );
}
else
{
H h;
h.update( p, n );
result_type r = h.result();
std::memcpy( key, &r[0], r.size() );
detail::memcpy( key, &r[0], m < r.size()? m: r.size() );
}
for( int i = 0; i < m; ++i )
for( std::size_t i = 0; i < m; ++i )
{
key[ i ] = static_cast<unsigned char>( key[ i ] ^ 0x36 );
}
inner_.update( key, m );
for( int i = 0; i < m; ++i )
for( std::size_t i = 0; i < m; ++i )
{
key[ i ] = static_cast<unsigned char>( key[ i ] ^ 0x36 ^ 0x5C );
}
@@ -75,12 +90,12 @@ private:
public:
hmac()
BOOST_HASH2_HMAC_CONSTEXPR hmac()
{
init( 0, 0 );
}
explicit hmac( std::uint64_t seed )
explicit BOOST_HASH2_HMAC_CONSTEXPR hmac( std::uint64_t seed )
{
if( seed == 0 )
{
@@ -88,24 +103,29 @@ public:
}
else
{
unsigned char tmp[ 8 ];
unsigned char tmp[ 8 ] = {};
detail::write64le( tmp, seed );
init( tmp, 8 );
}
}
hmac( unsigned char const * p, std::size_t n )
BOOST_HASH2_HMAC_CONSTEXPR hmac( unsigned char const* p, std::size_t n )
{
init( p, n );
}
void update( void const * pv, std::size_t n )
BOOST_CXX14_CONSTEXPR void update( unsigned char const* p, std::size_t n )
{
inner_.update( p, n );
}
void update( void const* pv, std::size_t n )
{
inner_.update( pv, n );
}
result_type result()
BOOST_CXX14_CONSTEXPR result_type result()
{
result_type r = inner_.result();

View File

@@ -9,13 +9,14 @@
// RIPEMD-160 message digest algorithm, https://www.esat.kuleuven.be/cosic/publications/article-317.pdf
#include <boost/hash2/hmac.hpp>
#include <boost/hash2/digest.hpp>
#include <boost/hash2/detail/read.hpp>
#include <boost/hash2/detail/write.hpp>
#include <boost/hash2/detail/rot.hpp>
#include <boost/hash2/detail/memset.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <cstdint>
#include <array>
#include <cstring>
#include <cstddef>
@@ -39,83 +40,83 @@ private:
private:
static BOOST_FORCEINLINE std::uint32_t F1( std::uint32_t x, std::uint32_t y, std::uint32_t z) { return x ^ y ^ z; }
static BOOST_FORCEINLINE std::uint32_t F2( std::uint32_t x, std::uint32_t y, std::uint32_t z) { return (x & y) | (~x & z); }
static BOOST_FORCEINLINE std::uint32_t F3( std::uint32_t x, std::uint32_t y, std::uint32_t z) { return (x | ~y) ^ z; }
static BOOST_FORCEINLINE std::uint32_t F4( std::uint32_t x, std::uint32_t y, std::uint32_t z) { return (x & z) | (y & ~z); }
static BOOST_FORCEINLINE std::uint32_t F5( std::uint32_t x, std::uint32_t y, std::uint32_t z) { return x ^ (y | ~z); }
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR std::uint32_t F1( std::uint32_t x, std::uint32_t y, std::uint32_t z) { return x ^ y ^ z; }
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR std::uint32_t F2( std::uint32_t x, std::uint32_t y, std::uint32_t z) { return (x & y) | (~x & z); }
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR std::uint32_t F3( std::uint32_t x, std::uint32_t y, std::uint32_t z) { return (x | ~y) ^ z; }
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR std::uint32_t F4( std::uint32_t x, std::uint32_t y, std::uint32_t z) { return (x & z) | (y & ~z); }
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR std::uint32_t F5( std::uint32_t x, std::uint32_t y, std::uint32_t z) { return x ^ (y | ~z); }
static BOOST_FORCEINLINE void R1( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void R1( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
{
a += F1(b, c, d) + x;
a = detail::rotl(a, s) + e;
c = detail::rotl(c, 10);
}
static BOOST_FORCEINLINE void R2( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void R2( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
{
a += F2(b, c, d) + x + 0x5a827999u;
a = detail::rotl(a, s) + e;
c = detail::rotl(c, 10);
}
static BOOST_FORCEINLINE void R3( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void R3( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
{
a += F3(b, c, d) + x + 0x6ed9eba1u;
a = detail::rotl(a, s) + e;
c = detail::rotl(c, 10);
}
static BOOST_FORCEINLINE void R4( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void R4( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
{
a += F4(b, c, d) + x + 0x8f1bbcdcu;
a = detail::rotl(a, s) + e;
c = detail::rotl(c, 10);
}
static BOOST_FORCEINLINE void R5( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void R5( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
{
a += F5(b, c, d) + x + 0xa953fd4eu;
a = detail::rotl(a, s) + e;
c = detail::rotl(c, 10);
}
static BOOST_FORCEINLINE void RR1( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void RR1( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
{
a += F5(b, c, d) + x + 0x50a28be6u;
a = detail::rotl(a, s) + e;
c = detail::rotl(c, 10);
}
static BOOST_FORCEINLINE void RR2( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void RR2( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
{
a += F4(b, c, d) + x + 0x5c4dd124u;
a = detail::rotl(a, s) + e;
c = detail::rotl(c, 10);
}
static BOOST_FORCEINLINE void RR3( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void RR3( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
{
a += F3(b, c, d) + x + 0x6d703ef3u;
a = detail::rotl(a, s) + e;
c = detail::rotl(c, 10);
}
static BOOST_FORCEINLINE void RR4( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void RR4( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
{
a += F2(b, c, d) + x + 0x7a6d76e9u;
a = detail::rotl(a, s) + e;
c = detail::rotl(c, 10);
}
static BOOST_FORCEINLINE void RR5( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
static BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void RR5( std::uint32_t & a, std::uint32_t b, std::uint32_t & c, std::uint32_t d, std::uint32_t e, std::uint32_t x, std::uint32_t s )
{
a += F1(b, c, d) + x;
a = detail::rotl(a, s) + e;
c = detail::rotl(c, 10);
}
void transform( unsigned char const block[ 64 ] )
BOOST_CXX14_CONSTEXPR void transform( unsigned char const block[ 64 ] )
{
std::uint32_t aa = state_[ 0 ];
std::uint32_t bb = state_[ 1 ];
@@ -129,7 +130,7 @@ private:
std::uint32_t ddd = state_[ 3 ];
std::uint32_t eee = state_[ 4 ];
std::uint32_t X[ 16 ];
std::uint32_t X[ 16 ] = {};
for( int i = 0; i < 16; ++i )
{
@@ -328,17 +329,17 @@ private:
public:
typedef std::array<unsigned char, 20> result_type;
typedef digest<20> result_type;
static constexpr int block_size = 64;
ripemd_160() = default;
explicit ripemd_160( std::uint64_t seed )
explicit BOOST_CXX14_CONSTEXPR ripemd_160( std::uint64_t seed )
{
if( seed != 0 )
{
unsigned char tmp[ 8 ];
unsigned char tmp[ 8 ] = {};
detail::write64le( tmp, seed );
update( tmp, 8 );
@@ -346,7 +347,7 @@ public:
}
}
ripemd_160( unsigned char const * p, std::size_t n )
BOOST_CXX14_CONSTEXPR ripemd_160( unsigned char const * p, std::size_t n )
{
if( n != 0 )
{
@@ -355,10 +356,8 @@ public:
}
}
void update( void const * pv, std::size_t n )
BOOST_CXX14_CONSTEXPR void update( unsigned char const* p, std::size_t n )
{
unsigned char const* p = static_cast<unsigned char const*>( pv );
BOOST_ASSERT( m_ == n_ % N );
if( n == 0 ) return;
@@ -374,7 +373,7 @@ public:
k = n;
}
std::memcpy( buffer_ + m_, p, k );
detail::memcpy( buffer_ + m_, p, k );
p += k;
n -= k;
@@ -387,7 +386,7 @@ public:
transform( buffer_ );
m_ = 0;
std::memset( buffer_, 0, N );
detail::memset( buffer_, 0, N );
}
BOOST_ASSERT( m_ == 0 );
@@ -404,18 +403,24 @@ public:
if( n > 0 )
{
std::memcpy( buffer_, p, n );
detail::memcpy( buffer_, p, n );
m_ = n;
}
BOOST_ASSERT( m_ == n_ % N );
}
result_type result()
void update( void const * pv, std::size_t n )
{
unsigned char const* p = static_cast<unsigned char const*>( pv );
update( p, n );
}
BOOST_CXX14_CONSTEXPR result_type result()
{
BOOST_ASSERT( m_ == n_ % N );
unsigned char bits[ 8 ];
unsigned char bits[ 8 ] = {};
detail::write64le( bits, n_ * 8 );

View File

@@ -108,6 +108,7 @@ run siphash_cx.cpp ;
run md5.cpp ;
run hmac_md5.cpp ;
run md5_cx.cpp ;
run hmac_md5_cx.cpp ;
run sha1.cpp ;
run hmac_sha1.cpp ;
@@ -118,6 +119,7 @@ run hmac_sha2.cpp ;
run ripemd.cpp ;
run hmac_ripemd.cpp ;
run ripemd_cx.cpp ;
# legacy
@@ -131,6 +133,7 @@ run concept.cpp ;
run plaintext_leak.cpp ;
run multiple_result.cpp ;
run integral_result.cpp ;
run quality.cpp ;
# benchmarks

View File

@@ -264,47 +264,115 @@ template<class H> void test_copy_constructible()
template<class H> void test_update()
{
unsigned char const data[ 3 ] = {};
{
H h1;
unsigned char const data[ 3 ] = { 0x01, 0x02, 0x03 };
H h2;
h2.update( data, 3 );
{
H h1;
BOOST_TEST( h1.result() != h2.result() );
H h2;
h2.update( data, 3 );
BOOST_TEST( h1.result() != h2.result() );
}
{
H h1;
h1.update( data, 3 );
H h2;
h2.update( data, 3 );
BOOST_TEST( h1.result() == h2.result() );
}
{
H h1;
h1.update( data, 3 );
H h2;
h2.update( data, 2 );
BOOST_TEST( h1.result() != h2.result() );
}
{
H h1;
h1.update( data, 3 );
H h2( h1 );
h1.update( data, 3 );
h2.update( data, 3 );
BOOST_TEST( h1.result() == h2.result() );
}
{
H h1;
h1.update( data, 3 );
H h2;
h2.update( data + 0, 1 );
h2.update( data + 1, 1 );
h2.update( data + 2, 1 );
BOOST_TEST( h1.result() == h2.result() );
}
{
H h1;
h1.update( data, 3 );
H h2;
h2.update( data + 0, 1 );
h2.update( data + 1, 1 );
h2.update( data + 2, 1 );
BOOST_TEST( h1.result() == h2.result() );
}
{
H h1;
h1.update( data, 3 );
H h2;
h2.update( data, 1 );
h2.update( data + 1, 2 );
BOOST_TEST( h1.result() == h2.result() );
}
}
{
H h1;
h1.update( data, 3 );
int const N = 95;
H h2;
h2.update( data, 3 );
unsigned char const data[ N ] = {};
BOOST_TEST( h1.result() == h2.result() );
}
{
H h1;
h1.update( data, N );
{
H h1;
h1.update( data, 3 );
H h2;
h2.update( data, N / 3 );
h2.update( data + N / 3, N - N / 3 );
H h2;
h2.update( data, 2 );
BOOST_TEST( h1.result() == h2.result() );
}
BOOST_TEST( h1.result() != h2.result() );
}
{
H h1;
h1.update( data, N );
{
H h1;
h1.update( data, 3 );
H h2;
H h2( h1 );
for( int i = 0; i < N / 5; ++i )
{
h2.update( data + i * 5, 5 );
}
h1.update( data, 3 );
h2.update( data, 3 );
BOOST_TEST( h1.result() == h2.result() );
BOOST_TEST( h1.result() == h2.result() );
}
}
}

View File

@@ -11,8 +11,6 @@
# pragma warning(disable: 4307) // integral constant overflow
#endif
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
template<class H, std::size_t N> BOOST_CXX14_CONSTEXPR typename H::result_type test( std::uint64_t seed, unsigned char const (&v)[ N ] )
{
H h( seed );
@@ -22,6 +20,18 @@ template<class H, std::size_t N> BOOST_CXX14_CONSTEXPR typename H::result_type t
return h.result();
}
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
#if defined(BOOST_NO_CXX14_CONSTEXPR)
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2)
#else
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2); STATIC_ASSERT(x1 == x2)
#endif
int main()
{
using namespace boost::hash2;
@@ -29,33 +39,17 @@ int main()
constexpr unsigned char v1[] = { 0 };
constexpr unsigned char v4[] = { 0, 1, 2, 3 };
BOOST_TEST_EQ( test<fnv1a_32>( 0, v1 ), 84696351 );
BOOST_TEST_EQ( test<fnv1a_32>( 0, v4 ), 3282719153 );
TEST_EQ( test<fnv1a_32>( 0, v1 ), 84696351 );
TEST_EQ( test<fnv1a_32>( 0, v4 ), 3282719153 );
BOOST_TEST_EQ( test<fnv1a_64>( 0, v1 ), 12638153115695167455ull );
BOOST_TEST_EQ( test<fnv1a_64>( 0, v4 ), 4932904490461320209 );
TEST_EQ( test<fnv1a_64>( 0, v1 ), 12638153115695167455ull );
TEST_EQ( test<fnv1a_64>( 0, v4 ), 4932904490461320209 );
BOOST_TEST_EQ( test<fnv1a_32>( 7, v1 ), 1695235878 );
BOOST_TEST_EQ( test<fnv1a_32>( 7, v4 ), 4085431250 );
TEST_EQ( test<fnv1a_32>( 7, v1 ), 1695235878 );
TEST_EQ( test<fnv1a_32>( 7, v4 ), 4085431250 );
BOOST_TEST_EQ( test<fnv1a_64>( 7, v1 ), 3154070194012243846 );
BOOST_TEST_EQ( test<fnv1a_64>( 7, v4 ), 9028993744456876338 );
#if !defined(BOOST_NO_CXX14_CONSTEXPR)
STATIC_ASSERT( test<fnv1a_32>( 0, v1 ) == 84696351 );
STATIC_ASSERT( test<fnv1a_32>( 0, v4 ) == 3282719153 );
STATIC_ASSERT( test<fnv1a_64>( 0, v1 ) == 12638153115695167455ull );
STATIC_ASSERT( test<fnv1a_64>( 0, v4 ) == 4932904490461320209 );
STATIC_ASSERT( test<fnv1a_32>( 7, v1 ) == 1695235878 );
STATIC_ASSERT( test<fnv1a_32>( 7, v4 ) == 4085431250 );
STATIC_ASSERT( test<fnv1a_64>( 7, v1 ) == 3154070194012243846 );
STATIC_ASSERT( test<fnv1a_64>( 7, v4 ) == 9028993744456876338 );
#endif
TEST_EQ( test<fnv1a_64>( 7, v1 ), 3154070194012243846 );
TEST_EQ( test<fnv1a_64>( 7, v4 ), 9028993744456876338 );
return boost::report_errors();
}

49
test/hmac_md5_cx.cpp Normal file
View File

@@ -0,0 +1,49 @@
// Copyright 2024 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/md5.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <array>
#if defined(BOOST_MSVC) && BOOST_MSVC < 1920
# pragma warning(disable: 4307) // integral constant overflow
#endif
template<class H, std::size_t N> BOOST_CXX14_CONSTEXPR typename H::result_type test( std::uint64_t seed, unsigned char const (&v)[ N ] )
{
H h( seed );
h.update( v, N / 3 );
h.update( v + N / 3, N - N / 3 );
return h.result();
}
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
#if defined(BOOST_NO_CXX14_CONSTEXPR) || ( defined(BOOST_GCC) && BOOST_GCC < 60000 )
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2)
#else
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2); STATIC_ASSERT(x1 == x2)
#endif
int main()
{
using namespace boost::hash2;
constexpr unsigned char v[ 95 ] = {};
BOOST_CXX14_CONSTEXPR digest<16> r1 = {{ 0x6F, 0x37, 0xD7, 0x4E, 0xD7, 0x97, 0xC2, 0x55, 0xEA, 0x1E, 0x4A, 0x46, 0xC3, 0x52, 0x39, 0xD7 }};
BOOST_CXX14_CONSTEXPR digest<16> r2 = {{ 0x68, 0xD4, 0xDF, 0x36, 0x73, 0x64, 0x42, 0xC0, 0xED, 0xE2, 0xA6, 0x15, 0x85, 0x10, 0xA4, 0x5E }};
TEST_EQ( test<hmac_md5_128>( 0, v ), r1 );
TEST_EQ( test<hmac_md5_128>( 7, v ), r2 );
return boost::report_errors();
}

View File

@@ -14,22 +14,6 @@
#include <cstddef>
#include <cstdio>
template<std::size_t N> std::string to_string( std::array<unsigned char, N> const & v )
{
std::string r;
for( std::size_t i = 0; i < N; ++i )
{
char buffer[ 8 ];
std::snprintf( buffer, sizeof( buffer ), "%02x", static_cast<int>( v[ i ] ) );
r += buffer;
}
return r;
}
template<class H> std::string digest( std::string const k, std::string const & s )
{
H h( reinterpret_cast<unsigned char const*>( k.data() ), k.size() );

View File

@@ -10,26 +10,7 @@
#include <boost/hash2/sha1.hpp>
#include <boost/core/lightweight_test.hpp>
#include <cstdint>
#include <string>
#include <cstddef>
#include <cstdio>
template<std::size_t N> std::string to_string( std::array<unsigned char, N> const & v )
{
std::string r;
for( std::size_t i = 0; i < N; ++i )
{
char buffer[ 8 ];
std::snprintf( buffer, sizeof( buffer ), "%02x", static_cast<int>( v[ i ] ) );
r += buffer;
}
return r;
}
template<class H> std::string digest( std::string const & k, std::string const & s )
{

View File

@@ -3,7 +3,6 @@
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/md5.hpp>
#include <boost/hash2/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <array>
@@ -12,18 +11,28 @@
# pragma warning(disable: 4307) // integral constant overflow
#endif
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
template<class H, std::size_t N> BOOST_CXX14_CONSTEXPR typename H::result_type test( std::uint64_t seed, unsigned char const (&v)[ N ] )
{
H h( seed );
h.update( v, N / 3 );
h.update( v, N - N / 3 );
h.update( v + N / 3, N - N / 3 );
return h.result();
}
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
#if defined(BOOST_NO_CXX14_CONSTEXPR)
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2)
#else
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2); STATIC_ASSERT(x1 == x2)
#endif
int main()
{
using namespace boost::hash2;
@@ -33,15 +42,8 @@ int main()
BOOST_CXX14_CONSTEXPR digest<16> r1 = {{ 10, 29, 252, 24, 200, 200, 56, 31, 5, 248, 173, 157, 43, 69, 9, 181 }};
BOOST_CXX14_CONSTEXPR digest<16> r2 = {{ 181, 92, 80, 91, 73, 60, 132, 154, 25, 168, 65, 211, 8, 142, 193, 207 }};
BOOST_TEST_EQ( test<md5_128>( 0, v ), r1 );
BOOST_TEST_EQ( test<md5_128>( 7, v ), r2 );
#if !defined(BOOST_NO_CXX14_CONSTEXPR)
STATIC_ASSERT( test<md5_128>( 0, v ) == r1 );
STATIC_ASSERT( test<md5_128>( 7, v ) == r2 );
#endif
TEST_EQ( test<md5_128>( 0, v ), r1 );
TEST_EQ( test<md5_128>( 7, v ), r2 );
return boost::report_errors();
}

View File

@@ -21,13 +21,16 @@ template<class H> void test()
typename H::result_type r1 = h.result();
typename H::result_type r2 = h.result();
BOOST_TEST( r1 != r2 );
BOOST_TEST( r2 != r1 );
typename H::result_type r3 = h.result();
BOOST_TEST( r2 != r3 );
BOOST_TEST( r3 != r2 );
BOOST_TEST( r3 != r1 );
typename H::result_type r4 = h.result();
BOOST_TEST( r3 != r4 );
BOOST_TEST( r4 != r3 );
BOOST_TEST( r4 != r2 );
BOOST_TEST( r4 != r1 );
}
{

87
test/quality.cpp Normal file
View File

@@ -0,0 +1,87 @@
// Copyright 2024 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/fnv1a.hpp>
#include <boost/hash2/xxhash.hpp>
#include <boost/hash2/siphash.hpp>
#include <boost/core/lightweight_test.hpp>
#include <vector>
#include <cstddef>
#include <cstdio>
template<class H> void test_bit_flip( unsigned char ch )
{
int const N = 32;
std::vector<unsigned char> v( N, static_cast<unsigned char>( ch ) );
for( int n = 1; n <= N; ++n )
{
typename H::result_type r1 = {};
{
H h;
h.update( v.data(), n );
r1 = h.result();
}
for( int j = 0; j < n * 8; ++j )
{
v[ j / 8 ] ^= 1 << ( j % 8 );
H h;
h.update( v.data(), n );
typename H::result_type r2 = h.result();
v[ j / 8 ] ^= 1 << ( j % 8 );
BOOST_TEST( r1 != r2 ) || std::fprintf( stderr, "Hash collision with bit %d flipped in %d * 0x%02X\n", j, n, ch );
}
}
}
template<class H> void test_seq_length( unsigned char ch )
{
int const N = 1024;
std::vector<unsigned char> v( N, static_cast<unsigned char>( ch ) );
typename H::result_type r[ N ] = {};
for( int n = 0; n < N; ++n )
{
H h;
h.update( v.data(), n );
r[ n ] = h.result();
for( int j = 0; j < n; ++j )
{
BOOST_TEST( r[j] != r[n] ) || std::fprintf( stderr, "Hash collision between %d * 0x%02X and %d * 0x%02X\n", j, ch, n, ch );
}
}
}
template<class H> void test()
{
for( int ch = 0; ch <= 0xFF; ++ch )
{
test_bit_flip<H>( static_cast<unsigned char>( ch ) );
test_seq_length<H>( static_cast<unsigned char>( ch ) );
}
}
int main()
{
test<boost::hash2::fnv1a_32>();
test<boost::hash2::fnv1a_64>();
test<boost::hash2::xxhash_32>();
test<boost::hash2::xxhash_64>();
test<boost::hash2::siphash_32>();
test<boost::hash2::siphash_64>();
return boost::report_errors();
}

View File

@@ -12,22 +12,6 @@
#include <cstddef>
#include <cstdio>
template<std::size_t N> std::string to_string( std::array<unsigned char, N> const & v )
{
std::string r;
for( std::size_t i = 0; i < N; ++i )
{
char buffer[ 8 ];
std::snprintf( buffer, sizeof( buffer ), "%02x", static_cast<int>( v[ i ] ) );
r += buffer;
}
return r;
}
template<class H> std::string digest( std::string const & s )
{
H h;

81
test/ripemd_cx.cpp Normal file
View File

@@ -0,0 +1,81 @@
// Copyright 2024 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/ripemd.hpp>
#include <boost/hash2/digest.hpp>
#include <boost/hash2/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#if defined(BOOST_MSVC) && BOOST_MSVC < 1920
# pragma warning(disable: 4307) // integral constant overflow
#endif
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
#if defined(BOOST_NO_CXX14_CONSTEXPR)
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2)
#else
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2); STATIC_ASSERT(x1 == x2)
#endif
template<class H, std::size_t N> BOOST_CXX14_CONSTEXPR typename H::result_type test( std::uint64_t seed, boost::hash2::digest<N> const& dgst )
{
H h( seed );
h.update( dgst.data(), N / 3 );
h.update( dgst.data() + N / 3, N - N / 3 );
return h.result();
}
BOOST_CXX14_CONSTEXPR unsigned char to_byte( char c )
{
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
return 0xff;
}
BOOST_CXX14_CONSTEXPR boost::hash2::digest<20> digest_from_hex( char const* str )
{
boost::hash2::digest<20> dgst = {};
auto* p = dgst.data();
for( int i = 0; i < 20; ++i ) {
auto c1 = to_byte( str[ 2 * i ] );
auto c2 = to_byte( str[ 2 * i + 1 ] );
p[ i ] = (c1 << 4) | c2;
}
return dgst;
}
template<std::size_t N> BOOST_CXX14_CONSTEXPR boost::hash2::digest<N - 1> digest_from_str( char const (&str)[N] )
{
boost::hash2::digest<N - 1> dgst;
for( std::size_t i = 0; i < N - 1; ++i ) {
dgst.data()[ i ] = static_cast<unsigned char>( str[ i ] );
}
return dgst;
}
int main()
{
using namespace boost::hash2;
TEST_EQ( test<ripemd_160>( 0, digest_from_str( "a" ) ), digest_from_hex( "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe" ) );
TEST_EQ( test<ripemd_160>( 0, digest_from_str( "abc" ) ), digest_from_hex( "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc" ) );
TEST_EQ( test<ripemd_160>( 0, digest_from_str( "message digest" ) ), digest_from_hex( "5d0689ef49d2fae572b881b123a85ffa21595f36" ) );
TEST_EQ( test<ripemd_160>( 0, digest_from_str( "abcdefghijklmnopqrstuvwxyz" ) ), digest_from_hex( "f71c27109c692c1b56bbdceb5b9d2865b3708dbc" ) );
TEST_EQ( test<ripemd_160>( 0, digest_from_str( "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" ) ), digest_from_hex( "12a053384a9c0c88e405a06c27dcf49ada62eb2b" ) );
TEST_EQ( test<ripemd_160>( 0, digest_from_str( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ) ), digest_from_hex( "b0e20b6e3116640286ed3a87a5713079b21f5189" ) );
TEST_EQ( test<ripemd_160>( 7, digest_from_str( "a" ) ), digest_from_hex( "7580d81d5ed1467317ce3ab9199088764a518b9d" ) );
TEST_EQ( test<ripemd_160>( 7, digest_from_str( "abc" ) ), digest_from_hex( "f5a724fe56b405db4edcb1ea46707ad78753a2e4" ) );
TEST_EQ( test<ripemd_160>( 7, digest_from_str( "message digest" ) ), digest_from_hex( "da6a32ce82c07de14ac5c2be1be3775201f07941" ) );
TEST_EQ( test<ripemd_160>( 7, digest_from_str( "abcdefghijklmnopqrstuvwxyz" ) ), digest_from_hex( "221e3b3af0671febf816397ded6f05c8a5c540d3" ) );
TEST_EQ( test<ripemd_160>( 7, digest_from_str( "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" ) ), digest_from_hex( "4578ce76d4ddec5a75288306da83f65eb963973c" ) );
TEST_EQ( test<ripemd_160>( 7, digest_from_str( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ) ), digest_from_hex( "868f80dffc5c55612afdd5f8c7c4948410134dc5" ) );
return boost::report_errors();
}

View File

@@ -6,31 +6,11 @@
#include <boost/hash2/sha1.hpp>
#include <boost/core/lightweight_test.hpp>
#include <cstdint>
#include <string>
#include <cstddef>
#include <cstdio>
template<std::size_t N> std::string to_string( std::array<unsigned char, N> const & v )
{
std::string r;
for( std::size_t i = 0; i < N; ++i )
{
char buffer[ 8 ];
std::snprintf( buffer, sizeof( buffer ), "%02x", static_cast<int>( v[ i ] ) );
r += buffer;
}
return r;
}
template<class H> std::string digest( std::string const & s )
{
H h;
h.update( s.data(), s.size() );
return to_string( h.result() );

View File

@@ -3,7 +3,6 @@
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/sha1.hpp>
#include <boost/hash2/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <array>
@@ -12,18 +11,28 @@
# pragma warning(disable: 4307) // integral constant overflow
#endif
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
template<class H, std::size_t N> BOOST_CXX14_CONSTEXPR typename H::result_type test( std::uint64_t seed, unsigned char const (&v)[ N ] )
{
H h( seed );
h.update( v, N / 3 );
h.update( v, N - N / 3 );
h.update( v + N / 3, N - N / 3 );
return h.result();
}
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
#if defined(BOOST_NO_CXX14_CONSTEXPR)
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2)
#else
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2); STATIC_ASSERT(x1 == x2)
#endif
int main()
{
using namespace boost::hash2;
@@ -33,15 +42,8 @@ int main()
BOOST_CXX14_CONSTEXPR digest<20> r1 = {{ 0xBD, 0x05, 0x7D, 0x7F, 0x49, 0x14, 0x38, 0x24, 0xE4, 0x52, 0x63, 0x14, 0x7A, 0x02, 0xA5, 0x80, 0x13, 0x7F, 0xAB, 0xEF }};
BOOST_CXX14_CONSTEXPR digest<20> r2 = {{ 0xB8, 0x90, 0x42, 0x8C, 0x88, 0xBB, 0x53, 0xD1, 0x19, 0xB9, 0x34, 0x18, 0x0D, 0xA6, 0x26, 0x5B, 0xB1, 0xEF, 0xF7, 0x58 }};
BOOST_TEST_EQ( test<sha1_160>( 0, v ), r1 );
BOOST_TEST_EQ( test<sha1_160>( 7, v ), r2 );
#if !defined(BOOST_NO_CXX14_CONSTEXPR)
STATIC_ASSERT( test<sha1_160>( 0, v ) == r1 );
STATIC_ASSERT( test<sha1_160>( 7, v ) == r2 );
#endif
TEST_EQ( test<sha1_160>( 0, v ), r1 );
TEST_EQ( test<sha1_160>( 7, v ), r2 );
return boost::report_errors();
}

View File

@@ -3,7 +3,6 @@
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/siphash.hpp>
#include <boost/hash2/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <cstring>
@@ -12,18 +11,28 @@
# pragma warning(disable: 4307) // integral constant overflow
#endif
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
template<class H, std::size_t N> BOOST_CXX14_CONSTEXPR typename H::result_type test( unsigned char const (&seed)[ 16 ], unsigned char const (&v)[ N ] )
{
H h( seed, 16 );
h.update( v, N / 3 );
h.update( v, N - N / 3 );
h.update( v + N / 3, N - N / 3 );
return h.result();
}
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
#if defined(BOOST_NO_CXX14_CONSTEXPR)
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2)
#else
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2); STATIC_ASSERT(x1 == x2)
#endif
int main()
{
using namespace boost::hash2;
@@ -33,21 +42,11 @@ int main()
constexpr unsigned char v21[ 21 ] = {};
constexpr unsigned char v45[ 45 ] = {};
BOOST_TEST_EQ( test<siphash_32>( seed, v21 ), 3273912247 );
BOOST_TEST_EQ( test<siphash_32>( seed, v45 ), 3389005632 );
TEST_EQ( test<siphash_32>( seed, v21 ), 3273912247 );
TEST_EQ( test<siphash_32>( seed, v45 ), 3389005632 );
BOOST_TEST_EQ( test<siphash_64>( seed, v21 ), 17634937937087799533ull );
BOOST_TEST_EQ( test<siphash_64>( seed, v45 ), 7083435387605517692 );
#if !defined(BOOST_NO_CXX14_CONSTEXPR)
STATIC_ASSERT( test<siphash_32>( seed, v21 ) == 3273912247 );
STATIC_ASSERT( test<siphash_32>( seed, v45 ) == 3389005632 );
STATIC_ASSERT( test<siphash_64>( seed, v21 ) == 17634937937087799533ull );
STATIC_ASSERT( test<siphash_64>( seed, v45 ) == 7083435387605517692 );
#endif
TEST_EQ( test<siphash_64>( seed, v21 ), 17634937937087799533ull );
TEST_EQ( test<siphash_64>( seed, v45 ), 7083435387605517692 );
return boost::report_errors();
}

View File

@@ -3,7 +3,6 @@
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/xxhash.hpp>
#include <boost/hash2/detail/config.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <cstring>
@@ -12,18 +11,28 @@
# pragma warning(disable: 4307) // integral constant overflow
#endif
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
template<class H, std::size_t N> BOOST_CXX14_CONSTEXPR typename H::result_type test( std::uint64_t seed, unsigned char const (&v)[ N ] )
{
H h( seed );
h.update( v, N / 3 );
h.update( v, N - N / 3 );
h.update( v + N / 3, N - N / 3 );
return h.result();
}
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
#if defined(BOOST_NO_CXX14_CONSTEXPR)
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2)
#else
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2); STATIC_ASSERT(x1 == x2)
#endif
int main()
{
using namespace boost::hash2;
@@ -31,33 +40,17 @@ int main()
constexpr unsigned char v21[ 21 ] = {};
constexpr unsigned char v45[ 45 ] = {};
BOOST_TEST_EQ( test<xxhash_32>( 0, v21 ), 86206869 );
BOOST_TEST_EQ( test<xxhash_32>( 0, v45 ), 747548280 );
TEST_EQ( test<xxhash_32>( 0, v21 ), 86206869 );
TEST_EQ( test<xxhash_32>( 0, v45 ), 747548280 );
BOOST_TEST_EQ( test<xxhash_64>( 0, v21 ), 8680240691998137788 );
BOOST_TEST_EQ( test<xxhash_64>( 0, v45 ), 4352694002423811028 );
TEST_EQ( test<xxhash_64>( 0, v21 ), 8680240691998137788 );
TEST_EQ( test<xxhash_64>( 0, v45 ), 4352694002423811028 );
BOOST_TEST_EQ( test<xxhash_32>( 7, v21 ), 2135174986 );
BOOST_TEST_EQ( test<xxhash_32>( 7, v45 ), 1547773082 );
TEST_EQ( test<xxhash_32>( 7, v21 ), 2135174986 );
TEST_EQ( test<xxhash_32>( 7, v45 ), 1547773082 );
BOOST_TEST_EQ( test<xxhash_64>( 7, v21 ), 16168826474312362322ull );
BOOST_TEST_EQ( test<xxhash_64>( 7, v45 ), 14120916949766558435ull );
#if !defined(BOOST_NO_CXX14_CONSTEXPR)
STATIC_ASSERT( test<xxhash_32>( 0, v21 ) == 86206869 );
STATIC_ASSERT( test<xxhash_32>( 0, v45 ) == 747548280 );
STATIC_ASSERT( test<xxhash_64>( 0, v21 ) == 8680240691998137788 );
STATIC_ASSERT( test<xxhash_64>( 0, v45 ) == 4352694002423811028 );
STATIC_ASSERT( test<xxhash_32>( 7, v21 ) == 2135174986 );
STATIC_ASSERT( test<xxhash_32>( 7, v45 ) == 1547773082 );
STATIC_ASSERT( test<xxhash_64>( 7, v21 ) == 16168826474312362322ull );
STATIC_ASSERT( test<xxhash_64>( 7, v45 ) == 14120916949766558435ull );
#endif
TEST_EQ( test<xxhash_64>( 7, v21 ), 16168826474312362322ull );
TEST_EQ( test<xxhash_64>( 7, v45 ), 14120916949766558435ull );
return boost::report_errors();
}