Merge pull request #7 from bitshares/openssl-1.1-support

Openssl 1.1 support
This commit is contained in:
Alfredo Garcia 2018-05-31 17:32:21 -03:00 committed by GitHub
commit 0a90eff697
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 123 additions and 668 deletions

View file

@ -25,8 +25,6 @@ namespace fc {
typedef fc::array<unsigned char,65> compact_signature;
typedef std::vector<char> range_proof_type;
typedef fc::array<char,78> extended_key_data;
typedef fc::sha256 blinded_hash;
typedef fc::sha256 blind_signature;
/**
* @class public_key
@ -38,7 +36,6 @@ namespace fc {
public_key();
public_key(const public_key& k);
~public_key();
// bool verify( const fc::sha256& digest, const signature& sig );
public_key_data serialize()const;
public_key_point_data serialize_ecc_point()const;
@ -52,8 +49,6 @@ namespace fc {
public_key child( const fc::sha256& offset )const;
bool valid()const;
/** Computes new pubkey = generator * offset + old pubkey ?! */
// public_key mult( const fc::sha256& offset )const;
/** Computes new pubkey = regenerate(offset).pubkey + old pubkey
* = offset * G + 1 * old pubkey ?! */
public_key add( const fc::sha256& offset )const;
@ -122,9 +117,7 @@ namespace fc {
*/
fc::sha512 get_shared_secret( const public_key& pub )const;
// signature sign( const fc::sha256& digest )const;
compact_signature sign_compact( const fc::sha256& digest, bool require_canonical = true )const;
// bool verify( const fc::sha256& digest, const signature& sig );
public_key get_public_key()const;
@ -164,8 +157,6 @@ namespace fc {
fc::string to_base58() const { return str(); }
static extended_public_key from_base58( const fc::string& base58 );
public_key generate_p( int i ) const;
public_key generate_q( int i ) const;
private:
sha256 c;
int child_num, parent_fp;
@ -192,25 +183,9 @@ namespace fc {
static extended_private_key generate_master( const fc::string& seed );
static extended_private_key generate_master( const char* seed, uint32_t seed_len );
// Oleg Andreev's blind signature scheme,
// see http://blog.oleganza.com/post/77474860538/blind-signatures
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,
const fc::sha256& hash, int i ) const;
private:
private:
extended_private_key private_derive_rest( const fc::sha512& hash,
int num ) const;
private_key generate_a( int i ) const;
private_key generate_b( int i ) const;
private_key generate_c( int i ) const;
private_key generate_d( int i ) const;
private_key_secret compute_p( int i ) const;
private_key_secret compute_q( int i, const private_key_secret& p ) const;
sha256 c;
int child_num, parent_fp;
uint8_t depth;

View file

@ -66,74 +66,71 @@ public:
/** C++ wrapper for BIGNUM (OpenSSL bignum) */
class CBigNum : public BIGNUM
class CBigNum
{
BIGNUM* bn;
public:
CBigNum()
{
BN_init(this);
}
: bn(BN_new()) {}
CBigNum(const CBigNum& b)
: CBigNum()
{
BN_init(this);
if (!BN_copy(this, &b))
if (!BN_copy(bn, b.bn))
{
BN_clear_free(this);
BN_clear_free(bn);
throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
}
}
CBigNum& operator=(const CBigNum& b)
{
if (!BN_copy(this, &b))
if (!BN_copy(bn, b.bn))
throw bignum_error("CBigNum::operator= : BN_copy failed");
return (*this);
}
~CBigNum()
{
BN_clear_free(this);
BN_clear_free(bn);
}
//CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'.
CBigNum(signed char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
//CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
CBigNum(int64_t n) { BN_init(this); setint64(n); }
CBigNum(unsigned char n) { BN_init(this); setulong(n); }
CBigNum(unsigned short n) { BN_init(this); setulong(n); }
CBigNum(unsigned int n) { BN_init(this); setulong(n); }
//CBigNum(unsigned long n) { BN_init(this); setulong(n); }
CBigNum(uint64_t n) { BN_init(this); setuint64(n); }
CBigNum(signed char n) :CBigNum() { if (n >= 0) setulong(n); else setint64(n); }
CBigNum(short n) :CBigNum() { if (n >= 0) setulong(n); else setint64(n); }
CBigNum(int n) :CBigNum() { if (n >= 0) setulong(n); else setint64(n); }
CBigNum(int64_t n) :CBigNum() { setint64(n); }
CBigNum(unsigned char n) :CBigNum() { setulong(n); }
CBigNum(unsigned short n) :CBigNum() { setulong(n); }
CBigNum(unsigned int n) :CBigNum() { setulong(n); }
CBigNum(uint64_t n) :CBigNum() { setuint64(n); }
explicit CBigNum(const std::vector<unsigned char>& vch)
: CBigNum()
{
BN_init(this);
setvch(vch);
}
void setulong(unsigned long n)
{
if (!BN_set_word(this, n))
if (!BN_set_word(bn, n))
throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
}
unsigned long getulong() const
{
return BN_get_word(this);
return BN_get_word(bn);
}
unsigned int getuint() const
{
return BN_get_word(this);
return BN_get_word(bn);
}
int getint() const
{
unsigned long n = BN_get_word(this);
if (!BN_is_negative(this))
unsigned long n = BN_get_word(bn);
if (!BN_is_negative(bn))
return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n);
else
return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n);
@ -171,7 +168,7 @@ public:
pch[1] = (nSize >> 16) & 0xff;
pch[2] = (nSize >> 8) & 0xff;
pch[3] = (nSize) & 0xff;
BN_mpi2bn(pch, p - pch, this);
BN_mpi2bn(pch, p - pch, bn);
}
void setuint64(uint64_t n)
@ -198,7 +195,7 @@ public:
pch[1] = (nSize >> 16) & 0xff;
pch[2] = (nSize >> 8) & 0xff;
pch[3] = (nSize) & 0xff;
BN_mpi2bn(pch, p - pch, this);
BN_mpi2bn(pch, p - pch, bn);
}
@ -214,16 +211,16 @@ public:
vch2[3] = (nSize >> 0) & 0xff;
// swap data to big endian
reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
BN_mpi2bn(&vch2[0], vch2.size(), this);
BN_mpi2bn(&vch2[0], vch2.size(), bn);
}
std::vector<unsigned char> getvch() const
{
unsigned int nSize = BN_bn2mpi(this, NULL);
unsigned int nSize = BN_bn2mpi(bn, NULL);
if (nSize <= 4)
return std::vector<unsigned char>();
std::vector<unsigned char> vch(nSize);
BN_bn2mpi(this, &vch[0]);
BN_bn2mpi(bn, &vch[0]);
vch.erase(vch.begin(), vch.begin() + 4);
reverse(vch.begin(), vch.end());
return vch;
@ -237,16 +234,16 @@ public:
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
BN_mpi2bn(&vch[0], vch.size(), this);
BN_mpi2bn(&vch[0], vch.size(), bn);
return *this;
}
unsigned int GetCompact() const
{
unsigned int nSize = BN_bn2mpi(this, NULL);
unsigned int nSize = BN_bn2mpi(bn, NULL);
std::vector<unsigned char> vch(nSize);
nSize -= 4;
BN_bn2mpi(this, &vch[0]);
BN_bn2mpi(bn, &vch[0]);
unsigned int nCompact = nSize << 24;
if (nSize >= 1) nCompact |= (vch[4] << 16);
if (nSize >= 2) nCompact |= (vch[5] << 8);
@ -281,7 +278,7 @@ public:
*this += n;
}
if (fNegative)
*this = 0 - *this;
BN_set_negative(bn, 1);
}
std::string ToString(int nBase=10) const
@ -291,20 +288,20 @@ public:
CBigNum bn0 = 0;
std::string str;
CBigNum bn = *this;
BN_set_negative(&bn, false);
BN_set_negative(bn.bn, false);
CBigNum dv;
CBigNum rem;
if (BN_cmp(&bn, &bn0) == 0)
if (BN_cmp(bn.bn, bn0.bn) == 0)
return "0";
while (BN_cmp(&bn, &bn0) > 0)
while (BN_cmp(bn.bn, bn0.bn) > 0)
{
if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
if (!BN_div(dv.bn, rem.bn, bn.bn, bnBase.bn, pctx))
throw bignum_error("CBigNum::ToString() : BN_div failed");
bn = dv;
unsigned int c = rem.getulong();
str += "0123456789abcdef"[c];
}
if (BN_is_negative(this))
if (BN_is_negative(this->bn))
str += "-";
reverse(str.begin(), str.end());
return str;
@ -319,45 +316,50 @@ public:
bool operator!() const
{
return BN_is_zero(this);
return BN_is_zero(bn);
}
CBigNum& operator+=(const CBigNum& b)
{
if (!BN_add(this, this, &b))
if (!BN_add(bn, bn, b.bn))
throw bignum_error("CBigNum::operator+= : BN_add failed");
return *this;
}
CBigNum& operator-=(const CBigNum& b)
{
*this = *this - b;
if (!BN_sub(bn, bn, b.bn))
throw bignum_error("CBigNum::operator-= : BN_sub failed");
return *this;
}
CBigNum& operator*=(const CBigNum& b)
{
CAutoBN_CTX pctx;
if (!BN_mul(this, this, &b, pctx))
if (!BN_mul(bn, bn, b.bn, pctx))
throw bignum_error("CBigNum::operator*= : BN_mul failed");
return *this;
}
CBigNum& operator/=(const CBigNum& b)
{
*this = *this / b;
CAutoBN_CTX pctx;
if (!BN_div(bn, NULL, bn, b.bn, pctx))
throw bignum_error("CBigNum::operator/= : BN_div failed");
return *this;
}
CBigNum& operator%=(const CBigNum& b)
{
*this = *this % b;
CAutoBN_CTX pctx;
if (!BN_div(NULL, bn, bn, b.bn, pctx))
throw bignum_error("CBigNum::operator%= : BN_div failed");
return *this;
}
CBigNum& operator<<=(unsigned int shift)
{
if (!BN_lshift(this, this, shift))
if (!BN_lshift(bn, bn, shift))
throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
return *this;
}
@ -368,13 +370,13 @@ public:
// if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
CBigNum a = 1;
a <<= shift;
if (BN_cmp(&a, this) > 0)
if (BN_cmp(a.bn, bn) > 0)
{
*this = 0;
return *this;
}
if (!BN_rshift(this, this, shift))
if (!BN_rshift(bn, bn, shift))
throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
return *this;
}
@ -383,7 +385,7 @@ public:
CBigNum& operator++()
{
// prefix operator
if (!BN_add(this, this, BN_value_one()))
if (!BN_add(bn, bn, BN_value_one()))
throw bignum_error("CBigNum::operator++ : BN_add failed");
return *this;
}
@ -400,7 +402,7 @@ public:
{
// prefix operator
CBigNum r;
if (!BN_sub(&r, this, BN_value_one()))
if (!BN_sub(r.bn, bn, BN_value_one()))
throw bignum_error("CBigNum::operator-- : BN_sub failed");
*this = r;
return *this;
@ -414,10 +416,12 @@ public:
return ret;
}
friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
const BIGNUM* to_bignum() const {
return bn;
}
BIGNUM* to_bignum() {
return bn;
}
};
@ -425,7 +429,7 @@ public:
inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
{
CBigNum r;
if (!BN_add(&r, &a, &b))
if (!BN_add(r.to_bignum(), a.to_bignum(), b.to_bignum()))
throw bignum_error("CBigNum::operator+ : BN_add failed");
return r;
}
@ -433,7 +437,7 @@ inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
{
CBigNum r;
if (!BN_sub(&r, &a, &b))
if (!BN_sub(r.to_bignum(), a.to_bignum(), b.to_bignum()))
throw bignum_error("CBigNum::operator- : BN_sub failed");
return r;
}
@ -441,7 +445,7 @@ inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
inline const CBigNum operator-(const CBigNum& a)
{
CBigNum r(a);
BN_set_negative(&r, !BN_is_negative(&r));
BN_set_negative(r.to_bignum(), !BN_is_negative(r.to_bignum()));
return r;
}
@ -449,7 +453,7 @@ inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)
{
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_mul(&r, &a, &b, pctx))
if (!BN_mul(r.to_bignum(), a.to_bignum(), b.to_bignum(), pctx))
throw bignum_error("CBigNum::operator* : BN_mul failed");
return r;
}
@ -458,7 +462,7 @@ inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)
{
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_div(&r, NULL, &a, &b, pctx))
if (!BN_div(r.to_bignum(), NULL, a.to_bignum(), b.to_bignum(), pctx))
throw bignum_error("CBigNum::operator/ : BN_div failed");
return r;
}
@ -467,7 +471,7 @@ inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
{
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_mod(&r, &a, &b, pctx))
if (!BN_mod(r.to_bignum(), a.to_bignum(), b.to_bignum(), pctx))
throw bignum_error("CBigNum::operator% : BN_div failed");
return r;
}
@ -475,7 +479,7 @@ inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
{
CBigNum r;
if (!BN_lshift(&r, &a, shift))
if (!BN_lshift(r.to_bignum(), a.to_bignum(), shift))
throw bignum_error("CBigNum:operator<< : BN_lshift failed");
return r;
}
@ -487,12 +491,12 @@ inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
return r;
}
inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); }
inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); }
inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); }
inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); }
inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); }
inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); }
inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) == 0); }
inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) != 0); }
inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) <= 0); }
inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) >= 0); }
inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) < 0); }
inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) > 0); }
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
@ -522,7 +526,7 @@ inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char
CBigNum rem;
while (bn > bn0)
{
if (!BN_div(&dv, &rem, &bn, &bn58, pctx))
if (!BN_div(dv.to_bignum(), rem.to_bignum(), bn.to_bignum(), bn58.to_bignum(), pctx))
throw bignum_error("EncodeBase58 : BN_div failed");
bn = dv;
unsigned int c = rem.getulong();
@ -572,7 +576,7 @@ inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
break;
}
bnChar.setulong(p1 - pszBase58);
if (!BN_mul(&bn, &bn, &bn58, pctx))
if (!BN_mul(bn.to_bignum(), bn.to_bignum(), bn58.to_bignum(), pctx))
throw bignum_error("DecodeBase58 : BN_mul failed");
bn += bnChar;
}

View file

@ -1,6 +1,9 @@
#include <fc/crypto/dh.hpp>
#include <openssl/dh.h>
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
#endif
namespace fc {
SSL_TYPE(ssl_dh, DH, DH_free)
@ -12,10 +15,19 @@ namespace fc {
bool diffie_hellman::generate_params( int s, uint8_t g )
{
ssl_dh dh = DH_generate_parameters( s, g, NULL, NULL );
ssl_dh dh(DH_new());
DH_generate_parameters_ex(dh.obj, s, g, NULL);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
const BIGNUM* bn_p; // must not be free'd!
DH_get0_pqg(dh.obj, &bn_p, NULL, NULL);
p.resize( BN_num_bytes( bn_p ) );
if( p.size() )
BN_bn2bin( bn_p, (unsigned char*)&p.front() );
#else
p.resize( BN_num_bytes( dh->p ) );
if( p.size() )
BN_bn2bin( dh->p, (unsigned char*)&p.front() );
#endif
this->g = g;
return fc::validate( dh, valid );
}
@ -25,8 +37,14 @@ namespace fc {
if( !p.size() )
return valid = false;
ssl_dh dh = DH_new();
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
const auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
const auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
DH_set0_pqg(dh.obj, bn_p, NULL, bn_g);
#else
dh->p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
dh->g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
#endif
return fc::validate( dh, valid );
}
@ -35,8 +53,14 @@ namespace fc {
if( !p.size() )
return valid = false;
ssl_dh dh = DH_new();
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
const auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
const auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
DH_set0_pqg(dh.obj, bn_p, NULL, bn_g);
#else
dh->p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
dh->g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
#endif
if( !fc::validate( dh, valid ) )
{
@ -44,21 +68,42 @@ namespace fc {
}
DH_generate_key(dh);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
const BIGNUM* bn_pub_key; // must not be free'd!
const BIGNUM* bn_priv_key; // must not be free'd!
DH_get0_key(dh.obj, &bn_pub_key, &bn_priv_key);
pub_key.resize( BN_num_bytes( bn_pub_key ) );
priv_key.resize( BN_num_bytes( bn_priv_key ) );
if( pub_key.size() )
BN_bn2bin( bn_pub_key, (unsigned char*)&pub_key.front() );
if( priv_key.size() )
BN_bn2bin( bn_priv_key, (unsigned char*)&priv_key.front() );
#else
pub_key.resize( BN_num_bytes( dh->pub_key ) );
priv_key.resize( BN_num_bytes( dh->priv_key ) );
if( pub_key.size() )
BN_bn2bin( dh->pub_key, (unsigned char*)&pub_key.front() );
if( priv_key.size() )
BN_bn2bin( dh->priv_key, (unsigned char*)&priv_key.front() );
#endif
return true;
}
bool diffie_hellman::compute_shared_key( const char* buf, uint32_t s ) {
ssl_dh dh = DH_new();
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
auto bn_pub_key = BN_bin2bn( (unsigned char*)&pub_key.front(), pub_key.size(), NULL );
auto bn_priv_key = BN_bin2bn( (unsigned char*)&priv_key.front(), priv_key.size(), NULL );
auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
DH_set0_pqg(dh.obj, bn_p, NULL, bn_g);
DH_set0_key(dh.obj, bn_pub_key, bn_priv_key);
#else
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 );
dh->g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
#endif
int check;
DH_check(dh,&check);

View file

@ -231,11 +231,12 @@ namespace fc { namespace ecc {
static fc::string _to_base58( const extended_key_data& key )
{
char *buffer = (char*)alloca(key.size() + 4);
size_t buf_len = key.size() + 4;
char *buffer = (char*)alloca(buf_len);
memcpy( buffer, key.begin(), key.size() );
fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( key.begin(), key.size() ));
memcpy( buffer + key.size(), double_hash.data(), 4 );
return fc::to_base58( buffer, sizeof(buffer) );
return fc::to_base58( buffer, buf_len );
}
static void _parse_extended_data( unsigned char* buffer, fc::string base58 )
@ -301,9 +302,6 @@ namespace fc { namespace ecc {
return extended_public_key( get_public_key(), c, child_num, parent_fp, depth );
}
public_key extended_public_key::generate_p(int i) const { return derive_normal_child(2*i + 0); }
public_key extended_public_key::generate_q(int i) const { return derive_normal_child(2*i + 1); }
extended_private_key extended_private_key::derive_child(int i) const
{
return i < 0 ? derive_hardened_child(i) : derive_normal_child(i);
@ -346,11 +344,6 @@ namespace fc { namespace ecc {
return from_base58( _to_base58( data ) );
}
private_key extended_private_key::generate_a(int i) const { return derive_hardened_child(4*i + 0); }
private_key extended_private_key::generate_b(int i) const { return derive_hardened_child(4*i + 1); }
private_key extended_private_key::generate_c(int i) const { return derive_hardened_child(4*i + 2); }
private_key extended_private_key::generate_d(int i) const { return derive_hardened_child(4*i + 3); }
fc::string extended_private_key::str() const
{
return _to_base58( serialize_extended() );

View file

@ -186,164 +186,6 @@ namespace fc { namespace ecc {
return result;
}
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 );
}
}
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 = (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 invert( const private_key_secret& in, private_key_secret& out )
{
ssl_bignum bn_in;
to_bignum( in, bn_in );
ssl_bignum bn_n;
to_bignum( detail::get_curve_order(), bn_n );
ssl_bignum bn_inv;
bn_ctx ctx( BN_CTX_new() );
FC_ASSERT( BN_mod_inverse( bn_inv, bn_in, bn_n, ctx ) );
from_bignum( bn_inv, out );
}
static void to_point( const public_key_data& in, ec_point& out )
{
bn_ctx ctx( BN_CTX_new() );
const ec_group& curve = detail::get_curve();
private_key_secret x;
memcpy( x.data(), in.begin() + 1, x.data_size() );
ssl_bignum bn_x;
to_bignum( x, bn_x );
FC_ASSERT( EC_POINT_set_compressed_coordinates_GFp( curve, out, bn_x, *in.begin() & 1, ctx ) > 0 );
}
static void from_point( const ec_point& in, public_key_data& out )
{
bn_ctx ctx( BN_CTX_new() );
const ec_group& curve = detail::get_curve();
ssl_bignum bn_x;
ssl_bignum bn_y;
FC_ASSERT( EC_POINT_get_affine_coordinates_GFp( curve, in, bn_x, bn_y, ctx ) > 0 );
private_key_secret x;
from_bignum( bn_x, x );
memcpy( out.begin() + 1, x.data(), out.size() - 1 );
*out.begin() = BN_is_bit_set( bn_y, 0 ) ? 3 : 2;
}
// 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 )
{
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 )
{
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 )
{
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
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
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
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
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 );
}
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) { }
@ -359,102 +201,6 @@ namespace fc { namespace ecc {
return result;
}
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 );
}
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 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 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;
}
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;
}
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 );
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++ )
{
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 )
{
commitment_type result;

View file

@ -23,9 +23,6 @@ target_link_libraries( real128_test fc )
add_executable( hmac_test hmac_test.cpp )
target_link_libraries( hmac_test fc )
add_executable( blinding_test blinding_test.cpp )
target_link_libraries( blinding_test fc )
add_executable( ecc_test crypto/ecc_test.cpp )
target_link_libraries( ecc_test fc )

View file

@ -1,304 +0,0 @@
#define BOOST_TEST_MODULE BlindingTest
#include <boost/test/unit_test.hpp>
#include <fc/array.hpp>
#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
static fc::string TEST1_SEED = "000102030405060708090a0b0c0d0e0f";
static fc::string TEST1_M_PUB = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8";
static fc::string TEST1_M_PRIV = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi";
static fc::string TEST1_M_0H_PUB = "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw";
static fc::string TEST1_M_0H_PRIV = "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7";
static fc::string TEST1_M_0H_1_PUB = "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ";
static fc::string TEST1_M_0H_1_PRIV = "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs";
static fc::string TEST1_M_0H_1_2H_PUB = "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5";
static fc::string TEST1_M_0H_1_2H_PRIV = "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM";
static fc::string TEST1_M_0H_1_2H_2_PUB = "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV";
static fc::string TEST1_M_0H_1_2H_2_PRIV = "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334";
static fc::string TEST1_M_0H_1_2H_2_1g_PUB = "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy";
static fc::string TEST1_M_0H_1_2H_2_1g_PRIV = "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76";
static fc::string TEST2_SEED = "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542";
static fc::string TEST2_M_PUB = "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB";
static fc::string TEST2_M_PRIV = "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U";
static fc::string TEST2_M_0_PUB = "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH";
static fc::string TEST2_M_0_PRIV = "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt";
static fc::string TEST2_M_0_m1_PUB = "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a";
static fc::string TEST2_M_0_m1_PRIV = "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9";
static fc::string TEST2_M_0_m1_1_PUB = "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon";
static fc::string TEST2_M_0_m1_1_PRIV = "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef";
static fc::string TEST2_M_0_m1_1_m2_PUB = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
static fc::string TEST2_M_0_m1_1_m2_PRIV = "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc";
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];
fc::from_hex( TEST1_SEED, seed, sizeof(seed) );
fc::ecc::extended_private_key master = fc::ecc::extended_private_key::generate_master( seed, sizeof(seed) );
BOOST_CHECK_EQUAL( master.str(), TEST1_M_PRIV );
BOOST_CHECK_EQUAL( master.get_extended_public_key().str(), TEST1_M_PUB );
BOOST_CHECK_EQUAL( fc::ecc::extended_private_key::from_base58(TEST1_M_PRIV).str(), TEST1_M_PRIV );
BOOST_CHECK_EQUAL( fc::ecc::extended_public_key::from_base58(TEST1_M_PUB).str(), TEST1_M_PUB );
BOOST_CHECK_EQUAL( fc::ecc::extended_private_key::from_base58(TEST1_M_0H_PRIV).str(), TEST1_M_0H_PRIV );
BOOST_CHECK_EQUAL( fc::ecc::extended_public_key::from_base58(TEST1_M_0H_PUB).str(), TEST1_M_0H_PUB );
fc::ecc::extended_private_key m_0 = master.derive_child(0x80000000);
BOOST_CHECK_EQUAL( m_0.str(), TEST1_M_0H_PRIV );
BOOST_CHECK_EQUAL( m_0.get_extended_public_key().str(), TEST1_M_0H_PUB );
fc::ecc::extended_private_key m_0_1 = m_0.derive_child(1);
BOOST_CHECK_EQUAL( m_0_1.str(), TEST1_M_0H_1_PRIV );
BOOST_CHECK_EQUAL( m_0_1.get_extended_public_key().str(), TEST1_M_0H_1_PUB );
BOOST_CHECK_EQUAL( m_0.get_extended_public_key().derive_child(1).str(), TEST1_M_0H_1_PUB );
fc::ecc::extended_private_key m_0_1_2 = m_0_1.derive_child(0x80000002);
BOOST_CHECK_EQUAL( m_0_1_2.str(), TEST1_M_0H_1_2H_PRIV );
BOOST_CHECK_EQUAL( m_0_1_2.get_extended_public_key().str(), TEST1_M_0H_1_2H_PUB );
fc::ecc::extended_private_key m_0_1_2_2 = m_0_1_2.derive_child(2);
BOOST_CHECK_EQUAL( m_0_1_2_2.str(), TEST1_M_0H_1_2H_2_PRIV );
BOOST_CHECK_EQUAL( m_0_1_2_2.get_extended_public_key().str(), TEST1_M_0H_1_2H_2_PUB );
BOOST_CHECK_EQUAL( m_0_1_2.get_extended_public_key().derive_child(2).str(), TEST1_M_0H_1_2H_2_PUB );
fc::ecc::extended_private_key m_0_1_2_2_1g = m_0_1_2_2.derive_child(1000000000);
BOOST_CHECK_EQUAL( m_0_1_2_2_1g.str(), TEST1_M_0H_1_2H_2_1g_PRIV );
BOOST_CHECK_EQUAL( m_0_1_2_2_1g.get_extended_public_key().str(), TEST1_M_0H_1_2H_2_1g_PUB );
BOOST_CHECK_EQUAL( m_0_1_2_2.get_extended_public_key().derive_child(1000000000).str(), TEST1_M_0H_1_2H_2_1g_PUB );
}
BOOST_AUTO_TEST_CASE(test_extended_keys_2)
{
char seed[64];
fc::from_hex( TEST2_SEED, seed, sizeof(seed) );
fc::ecc::extended_private_key master = fc::ecc::extended_private_key::generate_master( seed, sizeof(seed) );
BOOST_CHECK_EQUAL( master.str(), TEST2_M_PRIV );
BOOST_CHECK_EQUAL( master.get_extended_public_key().str(), TEST2_M_PUB );
fc::ecc::extended_private_key m_0 = master.derive_child(0);
BOOST_CHECK_EQUAL( m_0.str(), TEST2_M_0_PRIV );
BOOST_CHECK_EQUAL( m_0.get_extended_public_key().str(), TEST2_M_0_PUB );
BOOST_CHECK_EQUAL( master.get_extended_public_key().derive_child(0).str(), TEST2_M_0_PUB );
fc::ecc::extended_private_key m_0_m1 = m_0.derive_child(-1);
BOOST_CHECK_EQUAL( m_0_m1.str(), TEST2_M_0_m1_PRIV );
BOOST_CHECK_EQUAL( m_0_m1.get_extended_public_key().str(), TEST2_M_0_m1_PUB );
fc::ecc::extended_private_key m_0_m1_1 = m_0_m1.derive_child(1);
BOOST_CHECK_EQUAL( m_0_m1_1.str(), TEST2_M_0_m1_1_PRIV );
BOOST_CHECK_EQUAL( m_0_m1_1.get_extended_public_key().str(), TEST2_M_0_m1_1_PUB );
BOOST_CHECK_EQUAL( m_0_m1.get_extended_public_key().derive_child(1).str(), TEST2_M_0_m1_1_PUB );
fc::ecc::extended_private_key m_0_m1_1_m2 = m_0_m1_1.derive_child(-2);
BOOST_CHECK_EQUAL( m_0_m1_1_m2.str(), TEST2_M_0_m1_1_m2_PRIV );
BOOST_CHECK_EQUAL( m_0_m1_1_m2.get_extended_public_key().str(), TEST2_M_0_m1_1_m2_PUB );
fc::ecc::extended_private_key m_0_m1_1_m2_2 = m_0_m1_1_m2.derive_child(2);
BOOST_CHECK_EQUAL( m_0_m1_1_m2_2.str(), TEST2_M_0_m1_1_m2_2_PRIV );
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 );
}
//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 < 30; 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 );
try {
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");
}

@ -1 +0,0 @@
Subproject commit 7f95b37e554453262e2bcda830724fc362614103