Upgrade the secp256k1 submodule

This commit is contained in:
Eric Frias 2022-09-29 18:23:51 +00:00 committed by Dan Notestein
parent 1d47290757
commit ed12072bf4
9 changed files with 383 additions and 334 deletions

2
.gitmodules vendored
View File

@ -1,6 +1,6 @@
[submodule "secp256k1-zkp"]
path = libraries/fc/vendor/secp256k1-zkp
url = https://github.com/cryptonomex/secp256k1-zkp.git
url = https://github.com/ElementsProject/secp256k1-zkp.git
[submodule "tests_api"]
path = tests/tests_api
url = ../tests_api.git

View File

@ -83,7 +83,7 @@ else ( MSVC )
ExternalProject_Add( project_secp256k1
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/configure CPPFLAGS=${FPIC_FLAG} --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp --with-bignum=no --enable-tests=no --enable-benchmark=no
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/configure CPPFLAGS=${FPIC_FLAG} --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp --with-bignum=no --enable-tests=no --enable-benchmark=no --enable-module-recovery --enable-experimental --enable-module-generator --enable-module-rangeproof
BUILD_COMMAND make
INSTALL_COMMAND true
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp/src/project_secp256k1-build/.libs/libsecp256k1.a ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp/src/project_secp256k1-build/.libs/libsecp256k1.so

View File

@ -47,6 +47,7 @@ namespace fc {
~public_key();
// bool verify( const fc::sha256& digest, const signature& sig );
public_key_data serialize()const;
public_key_point_data serialize_ecc_point()const;
operator public_key_data()const { return serialize(); }
@ -235,8 +236,9 @@ namespace fc {
commitment_type blind( const blind_factor_type& blind, uint64_t value );
blind_factor_type blind_sum( const std::vector<blind_factor_type>& blinds, uint32_t non_neg );
/** verifies taht commnits + neg_commits + excess == 0 */
bool verify_sum( const std::vector<commitment_type>& commits, const std::vector<commitment_type>& neg_commits, int64_t excess );
/** verifies that commnits + neg_commits == 0 */
/* note: verify_sum used to take an `excess` parameter, but the underlying implementation removed it, and in practice it was always set to `0` */
bool verify_sum( const std::vector<commitment_type>& commits, const std::vector<commitment_type>& neg_commits );
bool verify_range( uint64_t& min_val, uint64_t& max_val, const commitment_type& commit, const range_proof_type& proof );
range_proof_type range_proof_sign( uint64_t min_value,
@ -259,7 +261,6 @@ namespace fc {
range_proof_info range_get_info( const range_proof_type& proof );
} // namespace ecc
void to_variant( const ecc::private_key& var, variant& vo );
void from_variant( const variant& var, ecc::private_key& vo );

View File

@ -8,7 +8,7 @@
namespace fc { namespace ecc { namespace detail {
const secp256k1_context_t* _get_context();
const secp256k1_context* _get_context();
void _init_lib();
class private_key_impl

View File

@ -1,6 +1,7 @@
#include <fc/fwd_impl.hpp>
#include <secp256k1.h>
#include <secp256k1_recovery.h>
#include "_elliptic_impl_priv.hpp"
@ -69,34 +70,52 @@ namespace fc { namespace ecc {
public_key private_key::get_public_key()const
{
FC_ASSERT( my->_key != empty_priv );
public_key_data pub;
unsigned int pk_len;
FC_ASSERT( secp256k1_ec_pubkey_create( detail::_get_context(), (unsigned char*) pub.begin(), (int*) &pk_len, (unsigned char*) my->_key.data(), 1 ) );
FC_ASSERT( pk_len == pub.size() );
return public_key(pub);
FC_ASSERT(my->_key != empty_priv);
public_key_data pub;
size_t pk_len = pub.size();
secp256k1_pubkey pubkey;
FC_ASSERT(secp256k1_ec_pubkey_create(detail::_get_context(), &pubkey, (const unsigned char*)my->_key.data()));
secp256k1_ec_pubkey_serialize(detail::_get_context(), (unsigned char*)&pub.data[0], &pk_len, &pubkey, SECP256K1_EC_COMPRESSED);
return public_key(pub);
}
static int extended_nonce_function( unsigned char *nonce32, const unsigned char *msg32,
const unsigned char *key32, unsigned int attempt,
const void *data ) {
unsigned int* extra = (unsigned int*) data;
(*extra)++;
return secp256k1_nonce_function_default( nonce32, msg32, key32, *extra, nullptr );
static int extended_nonce_function(unsigned char *nonce32,
const unsigned char *msg32,
const unsigned char *key32,
const unsigned char *algo16,
void *data, unsigned int counter)
{
unsigned int* extra = (unsigned int*) data;
(*extra)++;
return secp256k1_nonce_function_default(nonce32, msg32, key32, algo16, nullptr, *extra);
}
compact_signature private_key::sign_compact( const fc::sha256& digest, canonical_signature_type canon_type )const
{
FC_ASSERT( my->_key != empty_priv );
compact_signature result;
int recid;
unsigned int counter = 0;
do
{
FC_ASSERT( secp256k1_ecdsa_sign_compact( detail::_get_context(), (unsigned char*) digest.data(), (unsigned char*) result.begin() + 1, (unsigned char*) my->_key.data(), extended_nonce_function, &counter, &recid ));
} while( !public_key::is_canonical( result, canon_type ) );
result.begin()[0] = 27 + 4 + recid;
return result;
FC_ASSERT( my->_key != empty_priv );
compact_signature result;
int recid;
unsigned int counter = 0;
do
{
secp256k1_ecdsa_recoverable_signature sig;
FC_ASSERT(secp256k1_ecdsa_sign_recoverable(detail::_get_context(),
&sig,
(unsigned char*)digest.data(),
(unsigned char*)my->_key.data(),
extended_nonce_function,
&counter));
FC_ASSERT(secp256k1_ecdsa_recoverable_signature_serialize_compact(detail::_get_context(), (unsigned char*)result.begin() + 1,
&recid, &sig));
FC_ASSERT(recid != -1);
}
while (!public_key::is_canonical(result, canon_type));
result.begin()[0] = 27 + 4 + recid;
return result;
}
}}

View File

@ -12,6 +12,8 @@
#include <assert.h>
#include <secp256k1.h>
#include <secp256k1_recovery.h>
#include <secp256k1_rangeproof.h>
#if _WIN32
# include <malloc.h>
@ -24,13 +26,13 @@
namespace fc { namespace ecc {
namespace detail
{
const secp256k1_context_t* _get_context() {
static secp256k1_context_t* ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_RANGEPROOF | SECP256K1_CONTEXT_COMMIT );
const secp256k1_context* _get_context() {
static secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
return ctx;
}
void _init_lib() {
static const secp256k1_context_t* ctx = _get_context();
static const secp256k1_context* ctx = _get_context();
static int init_o = init_openssl();
FC_UNUSED(ctx, init_o);
}
@ -68,9 +70,17 @@ namespace fc { namespace ecc {
{
FC_ASSERT( my->_key != empty_priv );
FC_ASSERT( other.my->_key != empty_pub );
public_key_data pub(other.my->_key);
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) pub.begin(), pub.size(), (unsigned char*) my->_key.data() ) );
return fc::sha512::hash( pub.begin() + 1, pub.size() - 1 );
secp256k1_pubkey pubkey;
FC_ASSERT(secp256k1_ec_pubkey_parse(detail::_get_context(), &pubkey, (const unsigned char*)other.my->_key.begin(), other.my->_key.size()));
FC_ASSERT(secp256k1_ec_pubkey_tweak_mul(detail::_get_context(), &pubkey, (unsigned char*)my->_key.data()));
public_key_data pub;
size_t pk_len = pub.size();
FC_ASSERT(secp256k1_ec_pubkey_serialize(detail::_get_context(), (unsigned char*)pub.begin(), &pk_len, &pubkey, SECP256K1_EC_COMPRESSED));
return fc::sha512::hash(pub.begin() + 1, pub.size() - 1);
}
@ -101,11 +111,17 @@ namespace fc { namespace ecc {
public_key public_key::add( const fc::sha256& digest )const
{
FC_ASSERT( my->_key != empty_pub );
public_key_data new_key;
memcpy( new_key.begin(), my->_key.begin(), new_key.size() );
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) new_key.begin(), new_key.size(), (unsigned char*) digest.data() ) );
return public_key( new_key );
FC_ASSERT(my->_key != empty_pub);
secp256k1_pubkey pubkey;
FC_ASSERT(secp256k1_ec_pubkey_parse(detail::_get_context(), &pubkey, (const unsigned char*)my->_key.begin(), my->_key.size()));
FC_ASSERT(secp256k1_ec_pubkey_tweak_add(detail::_get_context(), &pubkey, (unsigned char*)digest.data()));
public_key_data new_key;
size_t pk_len = new_key.size();
FC_ASSERT(secp256k1_ec_pubkey_serialize(detail::_get_context(), (unsigned char*)new_key.begin(), &pk_len, &pubkey, SECP256K1_EC_COMPRESSED));
return public_key(new_key);
}
std::string public_key::to_base58() const
@ -122,13 +138,16 @@ namespace fc { namespace ecc {
public_key_point_data public_key::serialize_ecc_point()const
{
FC_ASSERT( my->_key != empty_pub );
public_key_point_data dat;
unsigned int pk_len = my->_key.size();
memcpy( dat.begin(), my->_key.begin(), pk_len );
FC_ASSERT( secp256k1_ec_pubkey_decompress( detail::_get_context(), (unsigned char *) dat.begin(), (int*) &pk_len ) );
FC_ASSERT( pk_len == dat.size() );
return dat;
FC_ASSERT(my->_key != empty_pub);
secp256k1_pubkey pubkey;
FC_ASSERT(secp256k1_ec_pubkey_parse(detail::_get_context(), &pubkey, (const unsigned char*)my->_key.begin(), my->_key.size()));
public_key_point_data dat;
size_t pk_len = dat.size();
FC_ASSERT(secp256k1_ec_pubkey_serialize(detail::_get_context(), (unsigned char*)dat.begin(), &pk_len, &pubkey, SECP256K1_EC_UNCOMPRESSED));
FC_ASSERT(pk_len == dat.size());
return dat;
}
public_key::public_key( const public_key_point_data& dat )
@ -152,76 +171,90 @@ namespace fc { namespace ecc {
my->_key = dat;
}
public_key::public_key( const compact_signature& c, const fc::sha256& digest, canonical_signature_type canon_type )
public_key::public_key(const compact_signature& c, const fc::sha256& digest, canonical_signature_type canon_type)
{
int nV = c.data[0];
if (nV<27 || nV>=35)
FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" );
int nV = c.data[0];
if (nV < 27 || nV >= 35)
FC_THROW_EXCEPTION(exception, "unable to reconstruct public key from signature");
FC_ASSERT( is_canonical( c, canon_type ), "signature is not canonical" );
FC_ASSERT(is_canonical(c, canon_type), "signature is not canonical");
unsigned int pk_len;
FC_ASSERT( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) digest.data(), (unsigned char*) c.begin() + 1, (unsigned char*) my->_key.begin(), (int*) &pk_len, 1, (*c.begin() - 27) & 3 ) );
FC_ASSERT( pk_len == my->_key.size() );
secp256k1_ecdsa_recoverable_signature sig;
FC_ASSERT(secp256k1_ecdsa_recoverable_signature_parse_compact(detail::_get_context(), &sig, (const unsigned char*)c.begin() + 1, (*c.begin() - 27) & 3));
secp256k1_pubkey recovered_key;
FC_ASSERT(secp256k1_ecdsa_recover(detail::_get_context(), &recovered_key, &sig, (unsigned char*)digest.data()));
size_t pk_len = my->_key.size();
FC_ASSERT(secp256k1_ec_pubkey_serialize(detail::_get_context(), (unsigned char*)my->_key.begin(), &pk_len, &recovered_key, SECP256K1_EC_COMPRESSED));
FC_ASSERT(pk_len == my->_key.size());
}
extended_public_key::extended_public_key( const public_key& k, const fc::sha256& c,
int child, int parent, uint8_t depth )
: public_key(k), c(c), child_num(child), parent_fp(parent), depth(depth) { }
extended_public_key::extended_public_key(const public_key& k, const fc::sha256& c, int child, int parent, uint8_t depth) :
public_key(k), c(c), child_num(child), parent_fp(parent), depth(depth)
{
}
extended_public_key extended_public_key::derive_normal_child(int i) const
{
hmac_sha512 mac;
public_key_data key = serialize();
const detail::chr37 data = detail::_derive_message( key, i );
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
fc::sha256 left = detail::_left(l);
FC_ASSERT( left < detail::get_curve_order() );
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) key.begin(), key.size(), (unsigned char*) left.data() ) > 0 );
// FIXME: check validity - if left + key == infinity then invalid
extended_public_key result( key, detail::_right(l), i, fingerprint(), depth + 1 );
return result;
public_key_data key = serialize();
const detail::chr37 data = detail::_derive_message(key, i);
fc::sha512 l = hmac_sha512().digest(c.data(), c.data_size(), data.begin(), data.size());
fc::sha256 left = detail::_left(l);
FC_ASSERT(left < detail::get_curve_order());
secp256k1_pubkey pubkey;
FC_ASSERT(secp256k1_ec_pubkey_parse(detail::_get_context(), &pubkey, (const unsigned char*)key.begin(), key.size()));
FC_ASSERT(secp256k1_ec_pubkey_tweak_add(detail::_get_context(), &pubkey, (const unsigned char*)left.data()));
size_t pk_len = key.size();
FC_ASSERT(secp256k1_ec_pubkey_serialize(detail::_get_context(), (unsigned char*)key.begin(), &pk_len, &pubkey, SECP256K1_EC_COMPRESSED));
// FIXME: check validity - if left + key == infinity then invalid
extended_public_key result(key, detail::_right(l), i, fingerprint(), depth + 1);
return result;
}
static void to_bignum( const unsigned char* in, ssl_bignum& out, unsigned int len )
static void to_bignum(const unsigned char* in, ssl_bignum& out, unsigned int len)
{
if ( *in & 0x80 )
{
unsigned char *buffer = (unsigned char*)alloca(len + 1);
*buffer = 0;
memcpy( buffer + 1, in, len );
BN_bin2bn( buffer, sizeof(buffer), out );
}
else
{
BN_bin2bn( in, len, out );
}
if (*in & 0x80)
{
unsigned char* buffer = (unsigned char*)alloca(len + 1);
*buffer = 0;
memcpy(buffer + 1, in, len);
BN_bin2bn(buffer, sizeof(buffer), out);
}
else
{
BN_bin2bn(in, len, out);
}
}
static void to_bignum( const private_key_secret& in, ssl_bignum& out )
static void to_bignum(const private_key_secret& in, ssl_bignum& out)
{
to_bignum( (unsigned char*) in.data(), out, in.data_size() );
to_bignum((unsigned char*)in.data(), out, in.data_size());
}
static void from_bignum( const ssl_bignum& in, unsigned char* out, unsigned int len )
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 = (unsigned char*)alloca(l);
BN_bn2bin( in, buffer );
memcpy( out, buffer + l - len, len );
}
else
{
memset( out, 0, len - l );
BN_bn2bin( in, out + len - l );
}
unsigned int l = BN_num_bytes(in);
if (l > len)
{
unsigned char* buffer = (unsigned char*)alloca(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 )
{
from_bignum( in, (unsigned char*) out.data(), out.data_size() );
static void from_bignum(const ssl_bignum& in, private_key_secret& out)
{
from_bignum(in, (unsigned char*)out.data(), out.data_size());
}
static void invert( const private_key_secret& in, private_key_secret& out )
@ -273,281 +306,280 @@ namespace fc { namespace ecc {
// static void print(public_key_data key) {
// print((unsigned char*) key.begin() + 1);
// }
static void canonicalize( unsigned char *int256 )
static void canonicalize(unsigned char* int256)
{
fc::sha256 biggi( (char*) int256, 32 );
if ( detail::get_half_curve_order() >= biggi )
{
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 );
fc::sha256 biggi((char*)int256, 32);
if (detail::get_half_curve_order() >= biggi)
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_k( const private_key_secret& a, const private_key_secret& c,
const public_key& p )
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 );
public_key_data P = p.serialize();
secp256k1_pubkey pubkey;
FC_ASSERT(secp256k1_ec_pubkey_parse(detail::_get_context(), &pubkey, (const unsigned char*)P.begin(), P.size()));
private_key_secret prod = a;
FC_ASSERT(secp256k1_ec_privkey_tweak_mul(detail::_get_context(), (unsigned char*)prod.data(), (unsigned char*)c.data()));
invert(prod, prod);
FC_ASSERT(secp256k1_ec_pubkey_tweak_mul(detail::_get_context(), &pubkey, (const unsigned char*)prod.data()));
size_t pk_len = P.size();
FC_ASSERT(secp256k1_ec_pubkey_serialize(detail::_get_context(), (unsigned char*)P.begin(), &pk_len, &pubkey, SECP256K1_EC_COMPRESSED));
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 )
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)
{
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 * d
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()));
// 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 * d * P
public_key_data accu = p;
secp256k1_pubkey accu_pubkey;
FC_ASSERT(secp256k1_ec_pubkey_parse(detail::_get_context(), &accu_pubkey, (const unsigned char*)accu.begin(), accu.size()));
FC_ASSERT(secp256k1_ec_pubkey_tweak_mul(detail::_get_context(), &accu_pubkey, (unsigned char*)prod.data()));
size_t accu_pk_len = accu.size();
FC_ASSERT(secp256k1_ec_pubkey_serialize(detail::_get_context(), (unsigned char*)accu.begin(), &accu_pk_len, &accu_pubkey, SECP256K1_EC_COMPRESSED));
// accu == prod * P == c^-1 * d * P
ec_point point_accu( EC_POINT_new( detail::get_curve() ) );
to_point( accu, point_accu );
ec_point point_q( EC_POINT_new( detail::get_curve() ) );
to_point( q, point_q );
bn_ctx ctx(BN_CTX_new());
FC_ASSERT( EC_POINT_add( detail::get_curve(), point_accu, point_accu, point_q, ctx ) > 0 );
from_point( point_accu, accu );
// accu == c^-1 * a * P + Q
ec_point point_accu(EC_POINT_new(detail::get_curve()));
to_point(accu, point_accu);
ec_point point_q(EC_POINT_new(detail::get_curve()));
to_point(q, point_q);
bn_ctx ctx(BN_CTX_new());
FC_ASSERT(EC_POINT_add(detail::get_curve(), point_accu, point_accu, point_q, ctx) > 0);
from_point(point_accu, accu);
// accu == c^-1 * a * P + Q
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) b.data() ) );
// accu == c^-1 * a * P + Q + b*G
FC_ASSERT(secp256k1_ec_pubkey_parse(detail::_get_context(), &accu_pubkey, (const unsigned char*)accu.begin(), accu.size()));
FC_ASSERT(secp256k1_ec_pubkey_tweak_add(detail::_get_context(), &accu_pubkey, (unsigned char*)b.data()));
// accu == c^-1 * a * P + Q + b*G
public_key_data k = compute_k( a, c, p ).serialize();
memcpy( prod.data(), k.begin() + 1, prod.data_size() );
// prod == Kx
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) a.data() ) > 0 );
// prod == Kx * a
invert( prod, prod );
// prod == (Kx * a)^-1
public_key_data k = compute_k(a, c, p).serialize();
memcpy(prod.data(), k.begin() + 1, prod.data_size());
// prod == Kx
FC_ASSERT(secp256k1_ec_privkey_tweak_mul(detail::_get_context(), (unsigned char*)prod.data(), (unsigned char*)a.data()));
// prod == Kx * a
invert(prod, prod);
// prod == (Kx * a)^-1
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
FC_ASSERT(secp256k1_ec_pubkey_tweak_mul(detail::_get_context(), &accu_pubkey, (unsigned char*)prod.data()));
accu_pk_len = accu.size();
FC_ASSERT(secp256k1_ec_pubkey_serialize(detail::_get_context(), (unsigned char*)accu.begin(), &accu_pk_len, &accu_pubkey, SECP256K1_EC_COMPRESSED));
// accu == (c^-1 * a * P + Q + b*G) * (Kx * a)^-1
// printf("T: "); print(accu); printf("\n");
return public_key( accu );
// printf("T: "); print(accu); printf("\n");
return public_key(accu);
}
extended_private_key::extended_private_key( const private_key& k, const sha256& c,
int child, int parent, uint8_t depth )
: private_key(k), c(c), child_num(child), parent_fp(parent), depth(depth) { }
int child, int parent, uint8_t depth ) :
private_key(k), c(c), child_num(child), parent_fp(parent), depth(depth)
{}
extended_private_key extended_private_key::private_derive_rest( const fc::sha512& hash,
int i) const
extended_private_key extended_private_key::private_derive_rest(const fc::sha512& hash, int i) const
{
fc::sha256 left = detail::_left(hash);
FC_ASSERT( left < detail::get_curve_order() );
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) left.data(), (unsigned char*) get_secret().data() ) > 0 );
extended_private_key result( private_key::regenerate( left ), detail::_right(hash),
i, fingerprint(), depth + 1 );
return result;
fc::sha256 left = detail::_left(hash);
FC_ASSERT(left < detail::get_curve_order());
FC_ASSERT(secp256k1_ec_privkey_tweak_add(detail::_get_context(), (unsigned char*)left.data(), (unsigned char*)get_secret().data()));
extended_private_key result(private_key::regenerate(left), detail::_right(hash), i, fingerprint(), depth + 1);
return result;
}
public_key extended_private_key::blind_public_key( const extended_public_key& bob, int i ) const
public_key extended_private_key::blind_public_key(const extended_public_key& bob, 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_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 );
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_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);
}
blinded_hash extended_private_key::blind_hash( const fc::sha256& hash, int i ) const
blinded_hash extended_private_key::blind_hash(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();
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;
private_key_secret a = generate_a(i).get_secret();
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()));
FC_ASSERT(secp256k1_ec_privkey_tweak_add(detail::_get_context(), (unsigned char*)a.data(), (unsigned char*)b.data()));
// printf("hash: "); print(hash); printf("\n");
// printf("blinded: "); print(a); printf("\n");
return a;
}
private_key_secret extended_private_key::compute_p( int i ) const
private_key_secret extended_private_key::compute_p(int i) const
{
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 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 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();
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;
private_key_secret q = derive_normal_child(2 * i + 1).get_secret();
FC_ASSERT(secp256k1_ec_privkey_tweak_mul(detail::_get_context(), (unsigned char*)q.data(), (unsigned char*)p.data()));
// printf("q: "); print(q); printf("\n");
return q;
}
blind_signature extended_private_key::blind_sign( const blinded_hash& hash, int i ) const
blind_signature extended_private_key::blind_sign(const blinded_hash& hash, int i) const
{
private_key_secret p = compute_p( i );
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;
private_key_secret p = compute_p(i);
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()));
FC_ASSERT(secp256k1_ec_privkey_tweak_add(detail::_get_context(), (unsigned char*)p.data(), (unsigned char*)q.data()));
// 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
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();
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 );
FC_ASSERT(secp256k1_ec_privkey_tweak_mul(detail::_get_context(), (unsigned char*)c.data(), (unsigned char*)sig.data()));
FC_ASSERT(secp256k1_ec_privkey_tweak_add(detail::_get_context(), (unsigned char*)c.data(), (unsigned char*)d.data()));
compact_signature result;
memcpy( result.begin() + 1, k.begin() + 1, 32 );
memcpy( result.begin() + 33, c.data(), 32 );
canonicalize( result.begin() + 33 );
// printf("unblinded: "); print(result.begin() + 33); printf("\n");
for ( int i = 0; i < 4; i++ )
compact_signature result;
memcpy(result.begin() + 1, k.begin() + 1, 32);
memcpy(result.begin() + 33, c.data(), 32);
canonicalize(result.begin() + 33);
// printf("unblinded: "); print(result.begin() + 33); printf("\n");
for (int i = 0; i < 4; i++)
{
secp256k1_ecdsa_recoverable_signature sig;
if (secp256k1_ecdsa_recoverable_signature_parse_compact(detail::_get_context(), &sig, (const unsigned char*)result.begin() + 1, i))
{
secp256k1_pubkey recovered_key;
if (secp256k1_ecdsa_recover(detail::_get_context(), &recovered_key, &sig, (unsigned char*)hash.data()))
{
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 ) )
size_t pk_len = 33;
FC_ASSERT(secp256k1_ec_pubkey_serialize(detail::_get_context(), (unsigned char*)pubkey, &pk_len, &recovered_key, SECP256K1_EC_COMPRESSED));
if (!memcmp(t.begin(), pubkey, sizeof(pubkey)))
{
if ( !memcmp( t.begin(), pubkey, sizeof(pubkey) ) )
{
*result.begin() = 27 + 4 + i;
return result;
// } else {
// printf("Candidate: "); print( pubkey ); printf("\n");
}
*result.begin() = 27 + 4 + i;
return result;
// } else {
// printf("Candidate: "); print( pubkey ); printf("\n");
}
}
}
FC_ASSERT( 0, "Failed to unblind - use different i" );
}
FC_ASSERT(0, "Failed to unblind - use different i");
}
commitment_type blind( const blind_factor_type& blind, uint64_t value )
{
commitment_type result;
FC_ASSERT( secp256k1_pedersen_commit( detail::_get_context(), (unsigned char*)&result, (unsigned char*)&blind, value ) );
return result;
}
commitment_type blind(const blind_factor_type& blind, uint64_t value)
{
secp256k1_pedersen_commitment commit;
FC_ASSERT(secp256k1_pedersen_commit(detail::_get_context(), &commit, (unsigned char*)&blind, value, secp256k1_generator_h));
blind_factor_type blind_sum( const std::vector<blind_factor_type>& blinds_in, uint32_t non_neg )
{
blind_factor_type result;
std::vector<const unsigned char*> blinds(blinds_in.size());
for( uint32_t i = 0; i < blinds_in.size(); ++i ) blinds[i] = (const unsigned char*)&blinds_in[i];
FC_ASSERT( secp256k1_pedersen_blind_sum( detail::_get_context(), (unsigned char*)&result, blinds.data(), blinds_in.size(), non_neg ) );
return result;
}
commitment_type result;
FC_ASSERT(secp256k1_pedersen_commitment_serialize(detail::_get_context(), (unsigned char*)result.begin(), &commit));
return result;
}
/** verifies taht commnits + neg_commits + excess == 0 */
bool verify_sum( const std::vector<commitment_type>& commits_in, const std::vector<commitment_type>& neg_commits_in, int64_t excess )
{
std::vector<const unsigned char*> commits(commits_in.size());
for( uint32_t i = 0; i < commits_in.size(); ++i ) commits[i] = (const unsigned char*)&commits_in[i];
std::vector<const unsigned char*> neg_commits(neg_commits_in.size());
for( uint32_t i = 0; i < neg_commits_in.size(); ++i ) neg_commits[i] = (const unsigned char*)&neg_commits_in[i];
blind_factor_type blind_sum(const std::vector<blind_factor_type>& blinds_in, uint32_t non_neg)
{
blind_factor_type result;
std::vector<const unsigned char*> blinds(blinds_in.size());
for (uint32_t i = 0; i < blinds_in.size(); ++i)
blinds[i] = (const unsigned char*)&blinds_in[i];
FC_ASSERT(secp256k1_pedersen_blind_sum(detail::_get_context(), (unsigned char*)&result, blinds.data(), blinds_in.size(), non_neg));
return result;
}
return secp256k1_pedersen_verify_tally( detail::_get_context(), commits.data(), commits.size(), neg_commits.data(), neg_commits.size(), excess );
}
/** verifies that commnits + neg_commits == 0 */
bool verify_sum(const std::vector<commitment_type>& commits_in, const std::vector<commitment_type>& neg_commits_in)
{
std::vector<secp256k1_pedersen_commitment> commits(commits_in.size());
for (unsigned i = 0; i < commits_in.size(); ++i)
FC_ASSERT(secp256k1_pedersen_commitment_parse(detail::_get_context(), &commits[i], (const unsigned char *)commits_in[i].begin()));
bool verify_range( uint64_t& min_val, uint64_t& max_val, const commitment_type& commit, const std::vector<char>& proof )
{
return secp256k1_rangeproof_verify( detail::_get_context(), &min_val, &max_val, (const unsigned char*)&commit, (const unsigned char*)proof.data(), proof.size() );
}
std::vector<secp256k1_pedersen_commitment> neg_commits(neg_commits_in.size());
for (unsigned i = 0; i < neg_commits_in.size(); ++i)
FC_ASSERT(secp256k1_pedersen_commitment_parse(detail::_get_context(), &neg_commits[i], (const unsigned char *)neg_commits_in[i].begin()));
std::vector<char> range_proof_sign( uint64_t min_value,
const commitment_type& commit,
const blind_factor_type& commit_blind,
const blind_factor_type& nonce,
int8_t base10_exp,
uint8_t min_bits,
uint64_t actual_value
)
{
int proof_len = 5134;
std::vector<char> proof(proof_len);
std::vector<secp256k1_pedersen_commitment*> commits_ptrs(commits_in.size());
for (unsigned i = 0; i < commits.size(); ++i)
commits_ptrs[i] = &commits[i];
FC_ASSERT( secp256k1_rangeproof_sign( detail::_get_context(),
(unsigned char*)proof.data(),
&proof_len, min_value,
(const unsigned char*)&commit,
(const unsigned char*)&commit_blind,
(const unsigned char*)&nonce,
base10_exp, min_bits, actual_value ) );
proof.resize(proof_len);
return proof;
}
std::vector<secp256k1_pedersen_commitment*> neg_commits_ptrs(neg_commits_in.size());
for (unsigned i = 0; i < neg_commits.size(); ++i)
neg_commits_ptrs[i] = &neg_commits[i];
return secp256k1_pedersen_verify_tally(detail::_get_context(), commits_ptrs.data(), commits_ptrs.size(), neg_commits_ptrs.data(), neg_commits_ptrs.size());
}
bool verify_range_proof_rewind( blind_factor_type& blind_out,
uint64_t& value_out,
string& message_out,
const blind_factor_type& nonce,
uint64_t& min_val,
uint64_t& max_val,
commitment_type commit,
const std::vector<char>& proof )
{
char msg[4096];
int mlen = 0;
FC_ASSERT( secp256k1_rangeproof_rewind( detail::_get_context(),
(unsigned char*)&blind_out,
&value_out,
(unsigned char*)msg,
&mlen,
(const unsigned char*)&nonce,
&min_val,
&max_val,
(const unsigned char*)&commit,
(const unsigned char*)proof.data(),
proof.size() ) );
bool verify_range(uint64_t& min_val, uint64_t& max_val, const commitment_type& commit, const std::vector<char>& proof)
{
secp256k1_pedersen_commitment commitment;
FC_ASSERT(secp256k1_pedersen_commitment_parse(detail::_get_context(), &commitment, (const unsigned char *)commit.begin()));
return secp256k1_rangeproof_verify(detail::_get_context(), &min_val, &max_val, &commitment, (const unsigned char*)proof.data(), proof.size(),
NULL, 0, secp256k1_generator_h);
}
message_out = std::string( msg, mlen );
return true;
}
std::vector<char> range_proof_sign(uint64_t min_value, const commitment_type& commit, const blind_factor_type& commit_blind,
const blind_factor_type& nonce, int8_t base10_exp, uint8_t min_bits, uint64_t actual_value)
{
size_t proof_len = 5134;
std::vector<char> proof(proof_len);
range_proof_info range_get_info( const std::vector<char>& proof )
{
range_proof_info result;
FC_ASSERT( secp256k1_rangeproof_info( detail::_get_context(),
(int*)&result.exp,
(int*)&result.mantissa,
(uint64_t*)&result.min_value,
(uint64_t*)&result.max_value,
(const unsigned char*)proof.data(),
(int)proof.size() ) );
secp256k1_pedersen_commitment commitment;
FC_ASSERT(secp256k1_pedersen_commitment_parse(detail::_get_context(), &commitment, (const unsigned char *)commit.begin()));
FC_ASSERT(secp256k1_rangeproof_sign(detail::_get_context(), (unsigned char*)proof.data(), &proof_len, min_value, &commitment,
(const unsigned char*)&commit_blind, (const unsigned char*)&nonce, base10_exp, min_bits, actual_value,
NULL /*?*/, 0, NULL, 0, secp256k1_generator_h));
proof.resize(proof_len);
return proof;
}
return result;
}
bool verify_range_proof_rewind(blind_factor_type& blind_out, uint64_t& value_out, string& message_out, const blind_factor_type& nonce,
uint64_t& min_val, uint64_t& max_val, commitment_type commit, const std::vector<char>& proof)
{
char msg[4096];
size_t mlen = 0;
secp256k1_pedersen_commitment commitment;
FC_ASSERT(secp256k1_pedersen_commitment_parse(detail::_get_context(), &commitment, (const unsigned char *)commit.begin()));
FC_ASSERT(secp256k1_rangeproof_rewind(detail::_get_context(), (unsigned char*)&blind_out, &value_out, (unsigned char*)msg, &mlen, (const unsigned char*)&nonce, &min_val,
&max_val, &commitment, (const unsigned char*)proof.data(), proof.size(),
NULL /*?*/, 0, secp256k1_generator_h));
message_out = std::string(msg, mlen);
return true;
}
range_proof_info range_get_info(const std::vector<char>& proof)
{
range_proof_info result;
FC_ASSERT(secp256k1_rangeproof_info(detail::_get_context(), (int*)&result.exp, (int*)&result.mantissa, (uint64_t*)&result.min_value,
(uint64_t*)&result.max_value, (const unsigned char*)proof.data(), (int)proof.size()));
return result;
}
} }

View File

@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(blind_test)
//FC_ASSERT( fc::ecc::verify_sum( {InC1,InC2}, {OutC1}, -60 ) );
BOOST_CHECK( fc::ecc::verify_sum( {InC1,InC2}, {OutC1,OutC2}, 0 ) );
BOOST_CHECK( fc::ecc::verify_sum( {InC1,InC2}, {OutC1,OutC2} ) );
auto nonce = fc::sha256::hash("nonce");
auto proof = fc::ecc::range_proof_sign( 0, OutC1, OutB1, nonce, 0, 0, 40 );
@ -60,10 +60,10 @@ BOOST_AUTO_TEST_CASE(blind_test)
auto B2m1 = fc::ecc::blind_sum( {B2,B1}, 1 );
/*auto C2m1 = */fc::ecc::blind( B2m1, 1 );
BOOST_CHECK( fc::ecc::verify_sum( {C1,C2}, {C3}, 0 ) );
BOOST_CHECK( fc::ecc::verify_sum( {C1,C2}, {C3}, 0 ) );
BOOST_CHECK( fc::ecc::verify_sum( {C3}, {C1,C2}, 0 ) );
BOOST_CHECK( fc::ecc::verify_sum( {C3}, {C1,C2}, 0 ) );
BOOST_CHECK( fc::ecc::verify_sum( {C1,C2}, {C3} ) );
BOOST_CHECK( fc::ecc::verify_sum( {C1,C2}, {C3} ) );
BOOST_CHECK( fc::ecc::verify_sum( {C3}, {C1,C2} ) );
BOOST_CHECK( fc::ecc::verify_sum( {C3}, {C1,C2} ) );
{
@ -80,13 +80,13 @@ BOOST_AUTO_TEST_CASE(blind_test)
auto C3 = fc::ecc::blind( B1, 1 );
/*auto C4 = */fc::ecc::blind( B1, 2 );
BOOST_CHECK( fc::ecc::verify_sum( {C2}, {C3}, -1 ) );
BOOST_CHECK( fc::ecc::verify_sum( {C1}, {C1}, 0 ) );
BOOST_CHECK( fc::ecc::verify_sum( {C2}, {C2}, 0 ) );
BOOST_CHECK( fc::ecc::verify_sum( {C3}, {C2}, 1 ) );
BOOST_CHECK( fc::ecc::verify_sum( {C1}, {C2}, INT64_MAX ) );
BOOST_CHECK( fc::ecc::verify_sum( {C1}, {C2}, INT64_MAX ) );
BOOST_CHECK( fc::ecc::verify_sum( {C2}, {C1}, -INT64_MAX ) );
BOOST_CHECK( !fc::ecc::verify_sum( {C2}, {C3} ) ); // -1
BOOST_CHECK( fc::ecc::verify_sum( {C1}, {C1} ) );
BOOST_CHECK( fc::ecc::verify_sum( {C2}, {C2} ) );
BOOST_CHECK( !fc::ecc::verify_sum( {C3}, {C2} ) ); // 1
BOOST_CHECK( !fc::ecc::verify_sum( {C1}, {C2} ) ); // INT64_MAX
BOOST_CHECK( !fc::ecc::verify_sum( {C1}, {C2} ) ); // INT64_MAX
BOOST_CHECK( !fc::ecc::verify_sum( {C2}, {C1} ) ); // -INT64_MAX
}
@ -99,8 +99,8 @@ BOOST_AUTO_TEST_CASE(blind_test)
auto InC = fc::ecc::blind( InBlind, 1000 );
auto In0 = fc::ecc::blind( InBlind, 0 );
BOOST_CHECK( fc::ecc::verify_sum( {InC}, {OutC1,OutC2}, 0 ) );
BOOST_CHECK( fc::ecc::verify_sum( {InC}, {In0}, 1000 ) );
BOOST_CHECK( fc::ecc::verify_sum( {InC}, {OutC1,OutC2} ) );
BOOST_CHECK( !fc::ecc::verify_sum( {InC}, {In0} ) ); // 1000
}
}

@ -1 +1 @@
Subproject commit bd067945ead3b514fba884abd0de95fc4b5db9ae
Subproject commit d22774e248c703a191049b78f8d04f37d6fcfa05

View File

@ -61,9 +61,6 @@ namespace hive {
using fc::flat_map;
using fc::flat_set;
using fc::static_variant;
using fc::ecc::range_proof_type;
using fc::ecc::range_proof_info;
using fc::ecc::commitment_type;
struct void_t{};
namespace protocol {