Added tests, fixes (sig format, canonicalization)

This commit is contained in:
Peter Conrad 2015-07-12 23:00:07 +02:00
parent 56e98e136a
commit 622de81402
3 changed files with 74 additions and 19 deletions

View file

@ -197,6 +197,7 @@ namespace fc {
public_key blind_public_key( const extended_public_key& bob, int i ) const;
blinded_hash blind_hash( const fc::sha256& hash, int i ) const;
blind_signature blind_sign( const blinded_hash& hash, int i ) const;
// WARNING! This may produce non-canonical signatures!
compact_signature unblind_signature( const extended_public_key& bob, const blind_signature& sig, int i ) const;
private:

View file

@ -178,35 +178,45 @@ namespace fc { namespace ecc {
return result;
}
static void to_bignum( const private_key_secret& in, ssl_bignum& out )
static void to_bignum( const unsigned char* in, ssl_bignum& out, unsigned int len )
{
if ( in.data()[0] & 0x80 )
if ( *in & 0x80 )
{
unsigned char buffer[33];
unsigned char buffer[len + 1];
*buffer = 0;
memcpy( buffer + 1, in.data(), 32 );
memcpy( buffer + 1, in, len );
BN_bin2bn( buffer, sizeof(buffer), out );
}
else
{
BN_bin2bn( (unsigned char*) in.data(), in.data_size(), out );
BN_bin2bn( in, len, out );
}
}
static void to_bignum( const private_key_secret& in, ssl_bignum& out )
{
to_bignum( (unsigned char*) in.data(), out, in.data_size() );
}
static void from_bignum( const ssl_bignum& in, unsigned char* out, unsigned int len )
{
unsigned int l = BN_num_bytes( in );
if ( l > len )
{
unsigned char buffer[l];
BN_bn2bin( in, buffer );
memcpy( out, buffer + l - len, len );
}
else
{
memset( out, 0, len - l );
BN_bn2bin( in, out + len - l );
}
}
static void from_bignum( const ssl_bignum& in, private_key_secret& out )
{
unsigned int len = BN_num_bytes( in );
if ( len > out.data_size() )
{
unsigned char buffer[len];
BN_bn2bin( in, buffer );
memcpy( (unsigned char*) out.data(), buffer + len - out.data_size(), out.data_size() );
}
else
{
memset( out.data(), 0, out.data_size() - len );
BN_bn2bin( in, (unsigned char*) out.data() + out.data_size() - len );
}
from_bignum( in, (unsigned char*) out.data(), out.data_size() );
}
static void invert( const private_key_secret& in, private_key_secret& out )
@ -256,6 +266,20 @@ namespace fc { namespace ecc {
return public_key( P );
}
static void canonicalize( unsigned char *int256 )
{
if (!(*int256 & 0x80))
{
return; // nothing to do
}
ssl_bignum bn_k;
to_bignum( int256, bn_k, 32 );
ssl_bignum bn_n;
to_bignum( detail::get_curve_order(), bn_n );
FC_ASSERT( BN_sub( bn_k, bn_n, bn_k ) );
from_bignum( bn_k, int256, 32 );
}
static public_key compute_t( const private_key_secret& a, const private_key_secret& b,
const private_key_secret& c, const private_key_secret& d,
const public_key_data& p, const public_key_data& q )
@ -369,8 +393,11 @@ namespace fc { namespace ecc {
public_key_data k = compute_k( a, c, p );
compact_signature result;
memcpy( result.begin(), k.begin() + 1, 32 );
memcpy( result.begin() + 32, c.data(), 32 );
*result.begin() = 27 + 4 + (*k.begin() & 1);
memcpy( result.begin() + 1, k.begin() + 1, 32 );
canonicalize( result.begin() + 1 );
memcpy( result.begin() + 33, c.data(), 32 );
canonicalize( result.begin() + 33 );
return result;
}

View file

@ -4,6 +4,7 @@
#include <fc/crypto/base58.hpp>
#include <fc/crypto/hex.hpp>
#include <fc/crypto/elliptic.hpp>
#include <fc/exception/exception.hpp>
// See https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#Test_Vectors
@ -103,3 +104,29 @@ BOOST_AUTO_TEST_CASE(test_extended_keys_2)
BOOST_CHECK_EQUAL( m_0_m1_1_m2_2.get_extended_public_key().str(), TEST2_M_0_m1_1_m2_2_PUB );
BOOST_CHECK_EQUAL( m_0_m1_1_m2.get_extended_public_key().derive_child(2).str(), TEST2_M_0_m1_1_m2_2_PUB );
}
BOOST_AUTO_TEST_CASE(test_blinding)
{
char buffer[7] = "test_";
fc::ecc::extended_private_key alice = fc::ecc::extended_private_key::generate_master( "master" );
fc::ecc::extended_private_key bob = fc::ecc::extended_private_key::generate_master( "puppet" );
for ( int i = 0; i < 10; i++ )
{
alice = alice.derive_child( i );
bob = bob.derive_child( i | 0x80000000 );
buffer[6] = '0' + i;
fc::ecc::extended_public_key bob_pub = bob.get_extended_public_key();
fc::sha256 hash = fc::sha256::hash( buffer, sizeof(buffer) );
fc::ecc::public_key t = alice.blind_public_key( bob_pub, i );
fc::ecc::blinded_hash blinded = alice.blind_hash( hash, i );
fc::ecc::blind_signature blind_sig = bob.blind_sign( blinded, i );
fc::ecc::compact_signature sig = alice.unblind_signature( bob_pub, blind_sig, i );
try {
fc::ecc::public_key validate( sig, hash );
// BOOST_CHECK_EQUAL( validate.serialize(), t.serialize() );
} catch (const fc::exception& e) {
printf( "Test %d: %s\n", i, e.to_string().c_str() );
}
}
}