Merge pull request #48 from pmconrad/testing

Testing
This commit is contained in:
Vikram Rajkumar 2015-08-03 10:09:12 -04:00
commit d139601430
14 changed files with 284 additions and 71 deletions

View file

@ -189,6 +189,7 @@ set( fc_sources
src/log/file_appender.cpp
src/log/gelf_appender.cpp
src/log/logger_config.cpp
src/crypto/_digest_common.cpp
src/crypto/openssl.cpp
src/crypto/aes.cpp
src/crypto/crc.cpp
@ -365,6 +366,8 @@ add_executable( all_tests tests/all_tests.cpp
tests/crypto/bigint_test.cpp
tests/crypto/blind.cpp
tests/crypto/blowfish_test.cpp
tests/crypto/dh_test.cpp
tests/crypto/rand_test.cpp
tests/crypto/sha_tests.cpp
tests/network/ntp_test.cpp
tests/thread/task_cancel.cpp

View file

@ -1,11 +1,12 @@
#pragma once
#include <fc/crypto/openssl.hpp>
#include <vector>
#include <stdint.h>
namespace fc {
struct diffie_hellman {
diffie_hellman():valid(0),g(5){}
diffie_hellman():valid(0),g(5){ fc::init_openssl(); }
bool generate_params( int s, uint8_t g );
bool generate_pub_key();
bool compute_shared_key( const char* buf, uint32_t s );

View file

@ -22,11 +22,10 @@ namespace fc
{
ssl_wrapper(ssl_type* obj):obj(obj) {}
operator ssl_type*()
{
return obj;
}
operator ssl_type*() { return obj; }
operator const ssl_type*() const { return obj; }
ssl_type* operator->() { return obj; }
const ssl_type* operator->() const { return obj; }
ssl_type* obj;
};

View file

@ -0,0 +1,29 @@
#include <fc/exception/exception.hpp>
#include "_digest_common.hpp"
namespace fc { namespace detail {
static void shift_l( const uint8_t* in, uint8_t* out, std::size_t n, unsigned int i) {
if (i < n) {
memcpy( out, in + i, n-i );
} else {
i = n;
}
memset( out + (n-i), 0, i );
}
void shift_l( const char* in, char* out, std::size_t n, unsigned int i) {
const uint8_t* in8 = (uint8_t*) in;
uint8_t* out8 = (uint8_t*) out;
if (i >= 8) {
shift_l( in8, out8, n, i >> 3 );
i &= 7;
in8 = out8;
}
std::size_t p;
for( p = 0; p < n-1; ++p )
out8[p] = (in8[p] << i) | (in8[p+1]>>(8-i));
out8[p] = in8[p] << i;
}
}}

View file

@ -0,0 +1,7 @@
#pragma once
/* Common stuff for cryptographic hashes
*/
namespace fc { namespace detail {
void shift_l( const char* in, char* out, std::size_t n, unsigned int i);
}}

View file

@ -2,52 +2,45 @@
#include <openssl/dh.h>
namespace fc {
SSL_TYPE(ssl_dh, DH, DH_free)
static bool validate( const ssl_dh& dh, bool& valid ) {
int check;
DH_check(dh,&check);
return valid = !(check /*& DH_CHECK_P_NOT_SAFE_PRIME*/);
}
bool diffie_hellman::generate_params( int s, uint8_t g )
{
DH* dh = DH_generate_parameters( s, g, NULL, NULL );
ssl_dh dh = DH_generate_parameters( s, g, NULL, NULL );
p.resize( BN_num_bytes( dh->p ) );
if( p.size() )
BN_bn2bin( dh->p, (unsigned char*)&p.front() );
this->g = g;
int check;
DH_check(dh,&check);
DH_free(dh);
if( check & DH_CHECK_P_NOT_SAFE_PRIME )
return valid = false;
return valid = true;
return fc::validate( dh, valid );
}
bool diffie_hellman::validate()
{
if( !p.size() )
return valid = false;
DH* dh = DH_new();
ssl_dh dh = DH_new();
dh->p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
dh->g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
int check;
DH_check(dh,&check);
DH_free(dh);
if( check & DH_CHECK_P_NOT_SAFE_PRIME )
return valid = false;
return valid = true;
return fc::validate( dh, valid );
}
bool diffie_hellman::generate_pub_key()
{
if( !p.size() )
return valid = false;
DH* dh = DH_new();
ssl_dh dh = DH_new();
dh->p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
dh->g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
int check;
DH_check(dh,&check);
if( check & DH_CHECK_P_NOT_SAFE_PRIME )
if( !fc::validate( dh, valid ) )
{
DH_free(dh);
return valid = false;
return false;
}
DH_generate_key(dh);
@ -58,11 +51,10 @@ namespace fc {
if( priv_key.size() )
BN_bn2bin( dh->priv_key, (unsigned char*)&priv_key.front() );
DH_free(dh);
return valid = true;
return true;
}
bool diffie_hellman::compute_shared_key( const char* buf, uint32_t s ) {
DH* dh = DH_new();
ssl_dh dh = DH_new();
dh->p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
dh->pub_key = BN_bin2bn( (unsigned char*)&pub_key.front(), pub_key.size(), NULL );
dh->priv_key = BN_bin2bn( (unsigned char*)&priv_key.front(), priv_key.size(), NULL );
@ -70,22 +62,19 @@ namespace fc {
int check;
DH_check(dh,&check);
if( check & DH_CHECK_P_NOT_SAFE_PRIME )
if( !fc::validate( dh, valid ) )
{
DH_free(dh);
return valid = false;
return false;
}
BIGNUM* pk = BN_bin2bn( (unsigned char*)buf, s, NULL );
ssl_bignum pk;
BN_bin2bn( (unsigned char*)buf, s, pk );
shared_key.resize( DH_size(dh) );
DH_compute_key( (unsigned char*)&shared_key.front(), pk, dh );
BN_free(pk);
DH_free(dh);
return valid = true;
return true;
}
bool diffie_hellman::compute_shared_key( const std::vector<char>& pubk ) {
return compute_shared_key( &pubk.front(), pubk.size() );
}
}

View file

@ -8,6 +8,7 @@
#include <fc/crypto/sha256.hpp>
#include <fc/variant.hpp>
#include <vector>
#include "_digest_common.hpp"
namespace fc
{
@ -69,11 +70,7 @@ void ripemd160::encoder::reset() {
ripemd160 operator << ( const ripemd160& h1, uint32_t i ) {
ripemd160 result;
uint8_t* r = (uint8_t*)result._hash;
uint8_t* s = (uint8_t*)h1._hash;
for( uint32_t p = 0; p < sizeof(h1._hash)-1; ++p )
r[p] = s[p] << i | (s[p+1]>>(8-i));
r[19] = s[19] << i;
fc::detail::shift_l( h1.data(), result.data(), result.data_size(), i );
return result;
}
ripemd160 operator ^ ( const ripemd160& h1, const ripemd160& h2 ) {

View file

@ -5,6 +5,7 @@
#include <fc/crypto/sha1.hpp>
#include <fc/variant.hpp>
#include <vector>
#include "_digest_common.hpp"
namespace fc
{
@ -54,11 +55,7 @@ void sha1::encoder::reset() {
sha1 operator << ( const sha1& h1, uint32_t i ) {
sha1 result;
uint8_t* r = (uint8_t*)result._hash;
uint8_t* s = (uint8_t*)h1._hash;
for( uint32_t p = 0; p < sizeof(h1._hash)-1; ++p )
r[p] = s[p] << i | (s[p+1]>>(8-i));
r[19] = s[19] << i;
fc::detail::shift_l( h1.data(), result.data(), result.data_size(), i );
return result;
}
sha1 operator ^ ( const sha1& h1, const sha1& h2 ) {

View file

@ -4,7 +4,8 @@
#include <string.h>
#include <fc/crypto/sha224.hpp>
#include <fc/variant.hpp>
#include "_digest_common.hpp"
namespace fc {
sha224::sha224() { memset( _hash, 0, sizeof(_hash) ); }
@ -52,11 +53,7 @@ namespace fc {
sha224 operator << ( const sha224& h1, uint32_t i ) {
sha224 result;
uint8_t* r = (uint8_t*)&result;//result._hash;
uint8_t* s = (uint8_t*)&h1;//h1._hash;
for( uint32_t p = 0; p < sizeof(sha224)-1; ++p )
r[p] = s[p] << i | (s[p+1]>>(8-i));
r[sizeof(sha224)-1] = s[sizeof(sha224)-1] << i;
fc::detail::shift_l( h1.data(), result.data(), result.data_size(), i );
return result;
}
sha224 operator ^ ( const sha224& h1, const sha224& h2 ) {

View file

@ -5,7 +5,8 @@
#include <fc/crypto/sha256.hpp>
#include <fc/variant.hpp>
#include <fc/exception/exception.hpp>
#include "_digest_common.hpp"
namespace fc {
sha256::sha256() { memset( _hash, 0, sizeof(_hash) ); }
@ -64,11 +65,7 @@ namespace fc {
sha256 operator << ( const sha256& h1, uint32_t i ) {
sha256 result;
uint8_t* r = (uint8_t*)result._hash;
uint8_t* s = (uint8_t*)h1._hash;
for( uint32_t p = 0; p < sizeof(h1._hash)-1; ++p )
r[p] = s[p] << i | (s[p+1]>>(8-i));
r[31] = s[31] << i;
fc::detail::shift_l( h1.data(), result.data(), result.data_size(), i );
return result;
}
sha256 operator ^ ( const sha256& h1, const sha256& h2 ) {

View file

@ -4,6 +4,7 @@
#include <string.h>
#include <fc/crypto/sha512.hpp>
#include <fc/variant.hpp>
#include "_digest_common.hpp"
namespace fc {
@ -52,11 +53,7 @@ namespace fc {
sha512 operator << ( const sha512& h1, uint32_t i ) {
sha512 result;
uint8_t* r = (uint8_t*)result._hash;
uint8_t* s = (uint8_t*)h1._hash;
for( uint32_t p = 0; p < sizeof(h1._hash)-1; ++p )
r[p] = s[p] << i | (s[p+1]>>(8-i));
r[63] = s[63] << i;
fc::detail::shift_l( h1.data(), result.data(), result.data_size(), i );
return result;
}
sha512 operator ^ ( const sha512& h1, const sha512& h2 ) {

69
tests/crypto/dh_test.cpp Normal file
View file

@ -0,0 +1,69 @@
#include <boost/test/unit_test.hpp>
#include <fc/crypto/dh.hpp>
#include <fc/exception/exception.hpp>
BOOST_AUTO_TEST_SUITE(fc_crypto)
BOOST_AUTO_TEST_CASE(dh_test)
{
fc::diffie_hellman alice;
BOOST_CHECK( alice.generate_params( 128, 5 ) );
BOOST_CHECK( alice.generate_pub_key() );
fc::diffie_hellman bob;
bob.p = alice.p;
BOOST_CHECK( bob.validate() );
BOOST_CHECK( bob.generate_pub_key() );
fc::diffie_hellman charlie;
BOOST_CHECK( !charlie.validate() );
BOOST_CHECK( !charlie.generate_pub_key() );
charlie.p = alice.p;
BOOST_CHECK( charlie.validate() );
BOOST_CHECK( charlie.generate_pub_key() );
BOOST_CHECK( alice.compute_shared_key( bob.pub_key ) );
BOOST_CHECK( bob.compute_shared_key( alice.pub_key ) );
BOOST_CHECK_EQUAL( alice.shared_key.size(), bob.shared_key.size() );
BOOST_CHECK( !memcmp( alice.shared_key.data(), bob.shared_key.data(), alice.shared_key.size() ) );
std::vector<char> alice_bob = alice.shared_key;
BOOST_CHECK( alice.compute_shared_key( charlie.pub_key ) );
BOOST_CHECK( charlie.compute_shared_key( alice.pub_key ) );
BOOST_CHECK_EQUAL( alice.shared_key.size(), charlie.shared_key.size() );
BOOST_CHECK( !memcmp( alice.shared_key.data(), charlie.shared_key.data(), alice.shared_key.size() ) );
std::vector<char> alice_charlie = alice.shared_key;
BOOST_CHECK( charlie.compute_shared_key( bob.pub_key ) );
BOOST_CHECK( bob.compute_shared_key( charlie.pub_key ) );
BOOST_CHECK_EQUAL( charlie.shared_key.size(), bob.shared_key.size() );
BOOST_CHECK( !memcmp( charlie.shared_key.data(), bob.shared_key.data(), bob.shared_key.size() ) );
std::vector<char> bob_charlie = charlie.shared_key;
BOOST_CHECK_EQUAL( alice_bob.size(), alice_charlie.size() );
BOOST_CHECK( memcmp( alice_bob.data(), alice_charlie.data(), alice_bob.size() ) );
BOOST_CHECK_EQUAL( alice_bob.size(), bob_charlie.size() );
BOOST_CHECK( memcmp( alice_bob.data(), bob_charlie.data(), alice_bob.size() ) );
BOOST_CHECK_EQUAL( alice_charlie.size(), bob_charlie.size() );
BOOST_CHECK( memcmp( alice_charlie.data(), bob_charlie.data(), alice_charlie.size() ) );
alice.p.clear(); alice.p.push_back(100); alice.p.push_back(2);
BOOST_CHECK( !alice.validate() );
alice.p = bob.p;
alice.g = 9;
BOOST_CHECK( !alice.validate() );
// It ain't easy...
// alice.g = 2;
// BOOST_CHECK( alice.validate() );
// BOOST_CHECK( alice.generate_pub_key() );
// BOOST_CHECK( alice.compute_shared_key( bob.pub_key ) );
// BOOST_CHECK( bob.compute_shared_key( alice.pub_key ) );
// BOOST_CHECK_EQUAL( alice.shared_key.size(), bob.shared_key.size() );
// BOOST_CHECK( memcmp( alice.shared_key.data(), bob.shared_key.data(), alice.shared_key.size() ) );
}
BOOST_AUTO_TEST_SUITE_END()

View file

@ -0,0 +1,41 @@
#include <boost/test/unit_test.hpp>
#include <fc/crypto/rand.hpp>
static void check_randomness( const char* buffer, size_t len ) {
if (len == 0) { return; }
// count bit runs and 0's / 1's
unsigned int zc = 0, oc = 0, rc = 0, last = 2;
for (size_t k = len; k; k--) {
char c = *buffer++;
for (int i = 0; i < 8; i++) {
unsigned int bit = c & 1;
c >>= 1;
if (bit) { oc++; } else { zc++; }
if (bit != last) { rc++; last = bit; }
}
}
BOOST_CHECK_EQUAL( 8*len, zc + oc );
double E = 1 + (zc + oc) / 2.0;
double variance = (E - 1) * (E - 2) / (oc + zc - 1);
double sigma = sqrt(variance);
BOOST_CHECK( rc > E - sigma && rc < E + sigma);
}
BOOST_AUTO_TEST_SUITE(fc_crypto)
BOOST_AUTO_TEST_CASE(rand_test)
{
char buffer[128];
fc::rand_bytes( buffer, sizeof(buffer) );
check_randomness( buffer, sizeof(buffer) );
}
BOOST_AUTO_TEST_CASE(pseudo_rand_test)
{
char buffer[10013];
fc::rand_pseudo_bytes( buffer, sizeof(buffer) );
check_randomness( buffer, sizeof(buffer) );
}
BOOST_AUTO_TEST_SUITE_END()

View file

@ -1,5 +1,7 @@
#include <boost/test/unit_test.hpp>
#include <fc/crypto/digest.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/crypto/sha1.hpp>
#include <fc/crypto/sha224.hpp>
#include <fc/crypto/sha256.hpp>
@ -14,6 +16,7 @@ static const std::string TEST2("");
static const std::string TEST3("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
static const std::string TEST4("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
static char TEST5[1000001];
static const std::string TEST6("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno");
static void init_5() {
memset( TEST5, 'a', sizeof(TEST5) - 1 );
@ -30,16 +33,81 @@ void test( const char* to_hash, const std::string& expected ) {
template<typename H>
void test( const std::string& to_hash, const std::string& expected ) {
H hash = H::hash( to_hash );
BOOST_CHECK_EQUAL( expected, (std::string) hash );
test<H>( to_hash.c_str(), expected );
}
template void test<fc::sha1>( const std::string& test, const std::string& expected );
template void test<fc::sha224>( const std::string& test, const std::string& expected );
template void test<fc::sha256>( const std::string& test, const std::string& expected );
template void test<fc::sha512>( const std::string& test, const std::string& expected );
template<typename H>
void test_big( const std::string& expected ) {
typename H::encoder enc;
for (char c : TEST6) { enc.put(c); }
for (int i = 0; i < 16777215; i++) {
enc.write( TEST6.c_str(), TEST6.size() );
}
H hash = enc.result();
BOOST_CHECK_EQUAL( expected, (std::string) hash );
enc.reset();
enc.write( TEST1.c_str(), TEST1.size() );
hash = enc.result();
BOOST_CHECK( hash >= H::hash( TEST1 ) );
test<H>( TEST1, (std::string) hash );
hash = hash ^ hash;
hash.data()[hash.data_size() - 1] = 1;
for (int i = hash.data_size() * 8 - 1; i > 0; i--) {
H other = hash << i;
BOOST_CHECK( other != hash );
BOOST_CHECK( other > hash );
BOOST_CHECK( hash < other );
}
H hash2( expected );
fc::variant v;
to_variant( hash2, v );
from_variant( v, hash );
BOOST_CHECK( hash == hash2 );
H hash3( expected.substr(15) + "000000000000000" );
BOOST_CHECK( hash3 == hash2 << 60 );
}
template<typename H>
void test_stream( ) {
H hash( TEST1 );
std::stringstream stream;
stream << hash;
H other;
stream >> other;
BOOST_CHECK( hash == other );
}
template void test_big<fc::ripemd160>( const std::string& expected );
template void test_big<fc::sha1>( const std::string& expected );
template void test_big<fc::sha224>( const std::string& expected );
template void test_big<fc::sha256>( const std::string& expected );
template void test_big<fc::sha512>( const std::string& expected );
template void test_stream<fc::ripemd160>();
template void test_stream<fc::sha256>();
template void test_stream<fc::sha512>();
BOOST_AUTO_TEST_SUITE(fc_crypto)
BOOST_AUTO_TEST_CASE(ripemd160_test)
{
init_5();
test<fc::ripemd160>( TEST1, "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc" );
test<fc::ripemd160>( TEST2, "9c1185a5c5e9fc54612808977ee8f548b2258d31" );
test<fc::ripemd160>( TEST3, "12a053384a9c0c88e405a06c27dcf49ada62eb2b" );
// test<fc::ripemd160>( TEST4, "" );
test<fc::ripemd160>( TEST5, "52783243c1697bdbe16d37f97f68f08325dc1528" );
test_big<fc::ripemd160>( "29b6df855772aa9a95442bf83b282b495f9f6541" );
test_stream<fc::ripemd160>();
}
BOOST_AUTO_TEST_CASE(sha1_test)
{
init_5();
@ -48,6 +116,7 @@ BOOST_AUTO_TEST_CASE(sha1_test)
test<fc::sha1>( TEST3, "84983e441c3bd26ebaae4aa1f95129e5e54670f1" );
test<fc::sha1>( TEST4, "a49b2446a02c645bf419f995b67091253a04a259" );
test<fc::sha1>( TEST5, "34aa973cd4c4daa4f61eeb2bdbad27316534016f" );
test_big<fc::sha1>( "7789f0c9ef7bfc40d93311143dfbe69e2017f592" );
}
BOOST_AUTO_TEST_CASE(sha224_test)
@ -58,6 +127,7 @@ BOOST_AUTO_TEST_CASE(sha224_test)
test<fc::sha224>( TEST3, "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525" );
test<fc::sha224>( TEST4, "c97ca9a559850ce97a04a96def6d99a9e0e0e2ab14e6b8df265fc0b3" );
test<fc::sha224>( TEST5, "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67" );
test_big<fc::sha224>( "b5989713ca4fe47a009f8621980b34e6d63ed3063b2a0a2c867d8a85" );
}
BOOST_AUTO_TEST_CASE(sha256_test)
@ -68,6 +138,23 @@ BOOST_AUTO_TEST_CASE(sha256_test)
test<fc::sha256>( TEST3, "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" );
test<fc::sha256>( TEST4, "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1" );
test<fc::sha256>( TEST5, "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0" );
test_big<fc::sha256>( "50e72a0e26442fe2552dc3938ac58658228c0cbfb1d2ca872ae435266fcd055e" );
test_stream<fc::sha256>();
std::vector<int> test_object;
test_object.push_back( 42 );
fc::sha256 digest = fc::digest( test_object );
BOOST_CHECK( digest == fc::sha256::hash( test_object ) );
fc::sha256 other( digest.data(), digest.data_size() );
BOOST_CHECK( digest == other );
fc::sha512 yet_another = fc::sha512::hash( TEST1 );
try {
fc::sha256 fourth( yet_another.data(), yet_another.data_size() );
BOOST_FAIL( "Expected exception!" );
} catch ( fc::exception& expected ) {}
fc::sha256 fourth( "445C7A8007A93D8733188288BB320A8FE2DEBD2AE1B47F0F50BC10BAE845C094" );
BOOST_CHECK_EQUAL( "d61967f63c7dd183914a4ae452c9f6ad5d462ce3d277798075b107615c1a8a30", (std::string) fc::sha256::hash(fourth) );
}
BOOST_AUTO_TEST_CASE(sha512_test)
@ -83,6 +170,9 @@ BOOST_AUTO_TEST_CASE(sha512_test)
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" );
test<fc::sha512>( TEST5, "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
"de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b" );
test_big<fc::sha512>( "b47c933421ea2db149ad6e10fce6c7f93d0752380180ffd7f4629a712134831d"
"77be6091b819ed352c2967a2e2d4fa5050723c9630691f1a05a7281dbe6c1086" );
test_stream<fc::sha512>();
}
BOOST_AUTO_TEST_SUITE_END()