Created + added test vectors, various fixes - working!
This commit is contained in:
parent
622de81402
commit
ef92e68146
4 changed files with 272 additions and 32 deletions
|
|
@ -198,7 +198,9 @@ namespace fc {
|
|||
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;
|
||||
compact_signature unblind_signature( const extended_public_key& bob,
|
||||
const blind_signature& sig,
|
||||
const fc::sha256& hash, int i ) const;
|
||||
|
||||
private:
|
||||
extended_private_key private_derive_rest( const fc::sha512& hash,
|
||||
|
|
|
|||
|
|
@ -89,6 +89,25 @@ namespace fc { namespace ecc {
|
|||
static private_key_secret order = _get_curve_order();
|
||||
return order;
|
||||
}
|
||||
|
||||
static private_key_secret _get_half_curve_order()
|
||||
{
|
||||
const ec_group& group = get_curve();
|
||||
bn_ctx ctx(BN_CTX_new());
|
||||
ssl_bignum order;
|
||||
FC_ASSERT( EC_GROUP_get_order( group, order, ctx ) );
|
||||
BN_rshift1( order, order );
|
||||
private_key_secret bin;
|
||||
FC_ASSERT( BN_num_bytes( order ) == bin.data_size() );
|
||||
FC_ASSERT( BN_bn2bin( order, (unsigned char*) bin.data() ) == bin.data_size() );
|
||||
return bin;
|
||||
}
|
||||
|
||||
const private_key_secret& get_half_curve_order()
|
||||
{
|
||||
static private_key_secret half_order = _get_half_curve_order();
|
||||
return half_order;
|
||||
}
|
||||
}
|
||||
|
||||
public_key public_key::from_key_data( const public_key_data &data ) {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ namespace fc { namespace ecc {
|
|||
fc::sha256 _right( const fc::sha512& v );
|
||||
const ec_group& get_curve();
|
||||
const private_key_secret& get_curve_order();
|
||||
const private_key_secret& get_half_curve_order();
|
||||
}
|
||||
|
||||
static const public_key_data empty_pub;
|
||||
|
|
@ -255,20 +256,24 @@ namespace fc { namespace ecc {
|
|||
*out.begin() = BN_is_bit_set( bn_y, 0 ) ? 3 : 2;
|
||||
}
|
||||
|
||||
static public_key compute_k( const private_key_secret& a, const private_key_secret& c,
|
||||
const public_key& p )
|
||||
{
|
||||
private_key_secret prod = a;
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) c.data() ) > 0 );
|
||||
invert( prod, prod );
|
||||
public_key_data P = p.serialize();
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) P.begin(), P.size(), (unsigned char*) prod.data() ) );
|
||||
return public_key( P );
|
||||
}
|
||||
// static void print(const unsigned char* data) {
|
||||
// for (int i = 0; i < 32; i++) {
|
||||
// printf("%02x", *data++);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// static void print(private_key_secret key) {
|
||||
// print((unsigned char*) key.data());
|
||||
// }
|
||||
//
|
||||
// static void print(public_key_data key) {
|
||||
// print((unsigned char*) key.begin() + 1);
|
||||
// }
|
||||
|
||||
static void canonicalize( unsigned char *int256 )
|
||||
{
|
||||
if (!(*int256 & 0x80))
|
||||
fc::sha256 biggi( (char*) int256, 32 );
|
||||
if ( detail::get_half_curve_order() >= biggi )
|
||||
{
|
||||
return; // nothing to do
|
||||
}
|
||||
|
|
@ -280,6 +285,18 @@ namespace fc { namespace ecc {
|
|||
from_bignum( bn_k, int256, 32 );
|
||||
}
|
||||
|
||||
static public_key compute_k( const private_key_secret& a, const private_key_secret& c,
|
||||
const public_key& p )
|
||||
{
|
||||
private_key_secret prod = a;
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) c.data() ) > 0 );
|
||||
invert( prod, prod );
|
||||
public_key_data P = p.serialize();
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) P.begin(), P.size(), (unsigned char*) prod.data() ) );
|
||||
// printf("K: "); print(P); printf("\n");
|
||||
return public_key( P );
|
||||
}
|
||||
|
||||
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 )
|
||||
|
|
@ -287,11 +304,11 @@ namespace fc { namespace ecc {
|
|||
private_key_secret prod;
|
||||
invert( c, prod ); // prod == c^-1
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) d.data() ) > 0 );
|
||||
// prod == c^-1 * a
|
||||
// prod == c^-1 * d
|
||||
|
||||
public_key_data accu = p;
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) prod.data() ) );
|
||||
// accu == prod * P == c^-1 * a * P
|
||||
// accu == prod * P == c^-1 * d * P
|
||||
|
||||
ec_point point_accu( EC_POINT_new( detail::get_curve() ) );
|
||||
to_point( accu, point_accu );
|
||||
|
|
@ -316,6 +333,7 @@ namespace fc { namespace ecc {
|
|||
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) prod.data() ) );
|
||||
// accu == (c^-1 * a * P + Q + b*G) * (Kx * a)^-1
|
||||
|
||||
// printf("T: "); print(accu); printf("\n");
|
||||
return public_key( accu );
|
||||
}
|
||||
|
||||
|
|
@ -342,6 +360,12 @@ namespace fc { namespace ecc {
|
|||
private_key_secret d = generate_d(i).get_secret();
|
||||
public_key_data p = bob.generate_p(i).serialize();
|
||||
public_key_data q = bob.generate_q(i).serialize();
|
||||
// printf("a: "); print(a); printf("\n");
|
||||
// printf("b: "); print(b); printf("\n");
|
||||
// printf("c: "); print(c); printf("\n");
|
||||
// printf("d: "); print(d); printf("\n");
|
||||
// printf("P: "); print(p); printf("\n");
|
||||
// printf("Q: "); print(q); printf("\n");
|
||||
return compute_t( a, b, c, d, p, q );
|
||||
}
|
||||
|
||||
|
|
@ -351,6 +375,8 @@ namespace fc { namespace ecc {
|
|||
private_key_secret b = generate_b(i).get_secret();
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) a.data(), (unsigned char*) hash.data() ) > 0 );
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) a.data(), (unsigned char*) b.data() ) > 0 );
|
||||
// printf("hash: "); print(hash); printf("\n");
|
||||
// printf("blinded: "); print(a); printf("\n");
|
||||
return a;
|
||||
}
|
||||
|
||||
|
|
@ -358,15 +384,15 @@ namespace fc { namespace ecc {
|
|||
{
|
||||
private_key_secret p_inv = derive_normal_child( 2*i ).get_secret();
|
||||
invert( p_inv, p_inv );
|
||||
// printf("p: "); print(p_inv); printf("\n");
|
||||
return p_inv;
|
||||
}
|
||||
|
||||
private_key_secret extended_private_key::compute_q( int i, const private_key_secret& p ) const
|
||||
{
|
||||
private_key_secret q = derive_normal_child( 2*i + 1 ).get_secret();
|
||||
private_key_secret p_inv;
|
||||
invert( p, p_inv );
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) q.data(), (unsigned char*) p_inv.data() ) > 0 );
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) q.data(), (unsigned char*) p.data() ) > 0 );
|
||||
// printf("q: "); print(q); printf("\n");
|
||||
return q;
|
||||
}
|
||||
|
||||
|
|
@ -376,29 +402,50 @@ namespace fc { namespace ecc {
|
|||
private_key_secret q = compute_q( i, p );
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) p.data(), (unsigned char*) hash.data() ) > 0 );
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) p.data(), (unsigned char*) q.data() ) > 0 );
|
||||
// printf("blind_sig: "); print(p); printf("\n");
|
||||
return p;
|
||||
}
|
||||
|
||||
compact_signature extended_private_key::unblind_signature( const extended_public_key& bob,
|
||||
const blind_signature& sig,
|
||||
const fc::sha256& hash,
|
||||
int i ) const
|
||||
{
|
||||
private_key_secret a = generate_a(i).get_secret();
|
||||
private_key_secret b = generate_b(i).get_secret();
|
||||
private_key_secret c = generate_c(i).get_secret();
|
||||
private_key_secret d = generate_d(i).get_secret();
|
||||
public_key p = bob.generate_p(i);
|
||||
public_key q = bob.generate_q(i);
|
||||
public_key_data k = compute_k( a, c, p );
|
||||
public_key_data t = compute_t( a, b, c, d, p, q ).serialize();
|
||||
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) c.data(), (unsigned char*) sig.data() ) > 0 );
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) c.data(), (unsigned char*) d.data() ) > 0 );
|
||||
|
||||
private_key_secret a = generate_a(i).get_secret();
|
||||
public_key p = bob.generate_p(i);
|
||||
public_key_data k = compute_k( a, c, p );
|
||||
|
||||
compact_signature result;
|
||||
*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;
|
||||
// printf("unblinded: "); print(result.begin() + 33); printf("\n");
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
unsigned char pubkey[33];
|
||||
int pklen = 33;
|
||||
if ( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) hash.data(),
|
||||
(unsigned char*) result.begin() + 1,
|
||||
pubkey, &pklen, 1, i ) )
|
||||
{
|
||||
if ( !memcmp( t.begin(), pubkey, sizeof(pubkey) ) )
|
||||
{
|
||||
*result.begin() = 27 + 4 + i;
|
||||
return result;
|
||||
// } else {
|
||||
// printf("Candidate: "); print( pubkey ); printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
FC_ASSERT( 0, "Failed to unblind - use different i" );
|
||||
}
|
||||
|
||||
commitment_type blind( const blind_factor_type& blind, uint64_t value )
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <fc/crypto/base58.hpp>
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/elliptic.hpp>
|
||||
#include <fc/crypto/openssl.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
|
||||
// See https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#Test_Vectors
|
||||
|
|
@ -36,6 +37,12 @@ static fc::string TEST2_M_0_m1_1_m2_PRIV = "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2Yvm
|
|||
static fc::string TEST2_M_0_m1_1_m2_2_PUB = "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt";
|
||||
static fc::string TEST2_M_0_m1_1_m2_2_PRIV = "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j";
|
||||
|
||||
static fc::string BLIND_K_X = "08be5c5076f8cbd1283cf98e74bff873032b9bc79a0769962bf3900f33c2df6e";
|
||||
static fc::string BLIND_T_X = "80deff382af8a8e4a5f297588e44d5bf858f30a524f74b13efcefeb54f4b3f47";
|
||||
static fc::string BLINDED_HASH = "7196e80cdafdfdfb7496323ad24bf47dda8447febd7426e444facc04940c7309";
|
||||
static fc::string BLIND_SIG = "40d6a477d849cc860df8ad159481f2ffc5b4dc3131b86a799d7d10460824dd53";
|
||||
static fc::string UNBLINDED = "700092a72a05e33509f9b068aa1d7c5336d8b5692b4157da199d7ec1e10fd7c0";
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_extended_keys_1)
|
||||
{
|
||||
char seed[16];
|
||||
|
|
@ -105,28 +112,193 @@ BOOST_AUTO_TEST_CASE(test_extended_keys_2)
|
|||
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)
|
||||
//static void print(const unsigned char* data, int len) {
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// printf("%02x", *data++);
|
||||
// }
|
||||
//}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_blinding_1)
|
||||
{
|
||||
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++ )
|
||||
for ( int i = 0; i < 30; i++ )
|
||||
{
|
||||
alice = alice.derive_child( i );
|
||||
bob = bob.derive_child( i | 0x80000000 );
|
||||
buffer[6] = '0' + i;
|
||||
buffer[5] = '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() );
|
||||
fc::ecc::compact_signature sig = alice.unblind_signature( bob_pub, blind_sig, hash, i );
|
||||
fc::ecc::public_key validate( sig, hash );
|
||||
// printf("Validated: "); print((unsigned char*) validate.serialize().begin(), 33);
|
||||
// printf("\nT: "); print((unsigned char*) t.serialize().begin(), 33); printf("\n");
|
||||
BOOST_CHECK( validate.serialize() == t.serialize() );
|
||||
} catch (const fc::exception& e) {
|
||||
printf( "Test %d: %s\n", i, e.to_string().c_str() );
|
||||
}
|
||||
alice = alice.derive_child( i );
|
||||
bob = bob.derive_child( i | 0x80000000 );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_blinding_2)
|
||||
{
|
||||
char message[7] = "test_0";
|
||||
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" );
|
||||
fc::ecc::extended_public_key bob_pub = bob.get_extended_public_key();
|
||||
fc::sha256 hash = fc::sha256::hash( message, sizeof(message) );
|
||||
|
||||
fc::ecc::public_key t = alice.blind_public_key( bob_pub, 0 );
|
||||
fc::ecc::public_key_data pub = t.serialize();
|
||||
char buffer[32];
|
||||
fc::from_hex( BLIND_T_X, buffer, sizeof(buffer) );
|
||||
BOOST_CHECK( !memcmp( pub.begin() + 1, buffer, sizeof(buffer) ) );
|
||||
|
||||
fc::ecc::blinded_hash blinded = alice.blind_hash( hash, 0 );
|
||||
fc::from_hex( BLINDED_HASH, buffer, sizeof(buffer) );
|
||||
BOOST_CHECK( !memcmp( blinded.data(), buffer, sizeof(buffer) ) );
|
||||
|
||||
fc::ecc::blind_signature blind_sig = bob.blind_sign( blinded, 0 );
|
||||
fc::from_hex( BLIND_SIG, buffer, sizeof(buffer) );
|
||||
BOOST_CHECK( !memcmp( blind_sig.data(), buffer, sizeof(buffer) ) );
|
||||
|
||||
fc::ecc::compact_signature sig = alice.unblind_signature( bob_pub, blind_sig, hash, 0 );
|
||||
fc::from_hex( BLIND_K_X, buffer, sizeof(buffer) );
|
||||
BOOST_CHECK( !memcmp( sig.begin() + 1, buffer, sizeof(buffer) ) );
|
||||
fc::from_hex( UNBLINDED, buffer, sizeof(buffer) );
|
||||
BOOST_CHECK( !memcmp( sig.begin() + 33, buffer, sizeof(buffer) ) );
|
||||
}
|
||||
|
||||
static void to_bignum(const char* data32, fc::ssl_bignum& out) {
|
||||
unsigned char dummy[33]; dummy[0] = 0;
|
||||
memcpy(dummy, data32, 32);
|
||||
BN_bin2bn((unsigned char*) data32, 32, out);
|
||||
}
|
||||
|
||||
//static void print(const fc::sha256 hash) {
|
||||
// print((unsigned char*) hash.data(), hash.data_size());
|
||||
//}
|
||||
//
|
||||
//static void print(const BIGNUM* bn) {
|
||||
// unsigned char buffer[64];
|
||||
// int len = BN_num_bytes(bn);
|
||||
// if (len > sizeof(buffer)) {
|
||||
// printf("BN too long - %d bytes?!", len);
|
||||
// return;
|
||||
// }
|
||||
// BN_bn2bin(bn, buffer);
|
||||
// print(buffer, len);
|
||||
//}
|
||||
//
|
||||
//static void print(const fc::ec_group& curve, const fc::ec_point& p, fc::bn_ctx& ctx) {
|
||||
// fc::ssl_bignum x;
|
||||
// fc::ssl_bignum y;
|
||||
// EC_POINT_get_affine_coordinates_GFp(curve, p, x, y, ctx);
|
||||
// printf("(");
|
||||
// print(x);
|
||||
// printf(", ");
|
||||
// print(y);
|
||||
// printf(")");
|
||||
//}
|
||||
|
||||
namespace fc {
|
||||
SSL_TYPE(ec_key, EC_KEY, EC_KEY_free)
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(openssl_blinding)
|
||||
{
|
||||
// Needed this "test" for producing data for debugging my libsecp256k1 implementation
|
||||
|
||||
char buffer[7] = "test_0";
|
||||
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" );
|
||||
fc::ec_group curve(EC_GROUP_new_by_curve_name(NID_secp256k1));
|
||||
fc::bn_ctx ctx(BN_CTX_new());
|
||||
fc::ssl_bignum n;
|
||||
EC_GROUP_get_order(curve, n, ctx);
|
||||
fc::ssl_bignum n_half;
|
||||
BN_rshift1(n_half, n);
|
||||
fc::ssl_bignum zero; BN_zero(zero);
|
||||
|
||||
fc::sha256 hash_ = fc::sha256::hash( buffer, sizeof(buffer) );
|
||||
fc::ssl_bignum hash; to_bignum(hash_.data(), hash);
|
||||
fc::ssl_bignum a; to_bignum(alice.derive_hardened_child(0).get_secret().data(), a);
|
||||
fc::ssl_bignum b; to_bignum(alice.derive_hardened_child(1).get_secret().data(), b);
|
||||
fc::ssl_bignum c; to_bignum(alice.derive_hardened_child(2).get_secret().data(), c);
|
||||
fc::ssl_bignum d; to_bignum(alice.derive_hardened_child(3).get_secret().data(), d);
|
||||
|
||||
fc::ec_point P(EC_POINT_new(curve));
|
||||
fc::ecc::public_key_data Pd = bob.get_extended_public_key().derive_child(0).serialize();
|
||||
fc::ssl_bignum Px; to_bignum(Pd.begin() + 1, Px);
|
||||
EC_POINT_set_compressed_coordinates_GFp(curve, P, Px, (*Pd.begin()) & 1, ctx);
|
||||
|
||||
fc::ec_point Q(EC_POINT_new(curve));
|
||||
fc::ecc::public_key_data Qd = bob.get_extended_public_key().derive_child(1).serialize();
|
||||
fc::ssl_bignum Qx; to_bignum(Qd.begin() + 1, Qx);
|
||||
EC_POINT_set_compressed_coordinates_GFp(curve, Q, Qx, (*Qd.begin()) & 1, ctx);
|
||||
|
||||
// Alice computes K = (c·a)^-1·P and public key T = (a·Kx)^-1·(b·G + Q + d·c^-1·P).
|
||||
fc::ec_point K(EC_POINT_new(curve));
|
||||
fc::ssl_bignum tmp;
|
||||
BN_mod_mul(tmp, a, c, n, ctx);
|
||||
BN_mod_inverse(tmp, tmp, n, ctx);
|
||||
EC_POINT_mul(curve, K, zero, P, tmp, ctx);
|
||||
|
||||
fc::ec_point T(EC_POINT_new(curve));
|
||||
BN_mod_inverse(tmp, c, n, ctx);
|
||||
BN_mod_mul(tmp, d, tmp, n, ctx);
|
||||
EC_POINT_mul(curve, T, b, P, tmp, ctx);
|
||||
EC_POINT_add(curve, T, T, Q, ctx);
|
||||
fc::ssl_bignum Kx;
|
||||
fc::ssl_bignum Ky;
|
||||
EC_POINT_get_affine_coordinates_GFp(curve, K, Kx, Ky, ctx);
|
||||
BN_mod_mul(tmp, a, Kx, n, ctx);
|
||||
BN_mod_inverse(tmp, tmp, n, ctx);
|
||||
EC_POINT_mul(curve, T, zero, T, tmp, ctx);
|
||||
|
||||
fc::ssl_bignum blinded;
|
||||
BN_mod_mul(blinded, a, hash, n, ctx);
|
||||
BN_mod_add(blinded, blinded, b, n, ctx);
|
||||
|
||||
fc::ssl_bignum p; to_bignum(bob.derive_normal_child(0).get_secret().data(), p);
|
||||
fc::ssl_bignum q; to_bignum(bob.derive_normal_child(1).get_secret().data(), q);
|
||||
BN_mod_inverse(p, p, n, ctx);
|
||||
BN_mod_mul(q, q, p, n, ctx);
|
||||
fc::ssl_bignum blind_sig;
|
||||
BN_mod_mul(blind_sig, p, blinded, n, ctx);
|
||||
BN_mod_add(blind_sig, blind_sig, q, n, ctx);
|
||||
|
||||
fc::ecdsa_sig sig(ECDSA_SIG_new());
|
||||
BN_copy(sig->r, Kx);
|
||||
BN_mod_mul(sig->s, c, blind_sig, n, ctx);
|
||||
BN_mod_add(sig->s, sig->s, d, n, ctx);
|
||||
|
||||
if (BN_cmp(sig->s, n_half) > 0) {
|
||||
BN_sub(sig->s, n, sig->s);
|
||||
}
|
||||
|
||||
fc::ec_key verify(EC_KEY_new());
|
||||
EC_KEY_set_public_key(verify, T);
|
||||
BOOST_CHECK( ECDSA_do_verify( (unsigned char*) hash_.data(), hash_.data_size(), sig, verify ) );
|
||||
// printf("a: "); print(a);
|
||||
// printf("\nb: "); print(b);
|
||||
// printf("\nc: "); print(c);
|
||||
// printf("\nd: "); print(d);
|
||||
// printf("\nP: "); print(curve, P, ctx);
|
||||
// printf("\nQ: "); print(curve, Q, ctx);
|
||||
// printf("\nK: "); print(curve, K, ctx);
|
||||
// printf("\nT: "); print(curve, T, ctx);
|
||||
// printf("\np: "); print(p);
|
||||
// printf("\nq: "); print(q);
|
||||
// printf("\nhash: "); print(hash_);
|
||||
// printf("\nblinded: "); print(blinded);
|
||||
// printf("\nblind_sig: "); print(blind_sig);
|
||||
// printf("\nunblinded: "); print(sig->s);
|
||||
// printf("\n");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue