update elliptic curve crypto for deterministic key generation
This commit is contained in:
parent
7b18403310
commit
314eabb293
3 changed files with 44 additions and 14 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
#include <fc/string.hpp>
|
#include <fc/string.hpp>
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
fc::string to_base58( const char* d, size_t s );
|
std::string to_base58( const char* d, size_t s );
|
||||||
fc::vector<char> from_base58( const fc::string& base58_str );
|
std::vector<char> from_base58( const std::string& base58_str );
|
||||||
size_t from_base58( const fc::string& base58_str, char* out_data, size_t out_data_len );
|
size_t from_base58( const std::string& base58_str, char* out_data, size_t out_data_len );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@ namespace fc {
|
||||||
typedef fc::array<char,72> signature;
|
typedef fc::array<char,72> signature;
|
||||||
typedef fc::array<unsigned char,65> compact_signature;
|
typedef fc::array<unsigned char,65> compact_signature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class public_key
|
||||||
|
* @brief contains only the public point of an elliptic curve key.
|
||||||
|
*/
|
||||||
class public_key
|
class public_key
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -31,7 +35,7 @@ namespace fc {
|
||||||
public_key( const compact_signature& c, const fc::sha256& digest );
|
public_key( const compact_signature& c, const fc::sha256& digest );
|
||||||
|
|
||||||
bool valid()const;
|
bool valid()const;
|
||||||
public_key mult( const fc::sha256& digest );
|
public_key mult( const fc::sha256& offset );
|
||||||
|
|
||||||
public_key( public_key&& pk );
|
public_key( public_key&& pk );
|
||||||
public_key& operator=( public_key&& pk );
|
public_key& operator=( public_key&& pk );
|
||||||
|
|
@ -41,7 +45,10 @@ namespace fc {
|
||||||
fc::fwd<detail::public_key_impl,8> my;
|
fc::fwd<detail::public_key_impl,8> my;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class private_key
|
||||||
|
* @brief an elliptic curve private key.
|
||||||
|
*/
|
||||||
class private_key
|
class private_key
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -57,6 +64,13 @@ namespace fc {
|
||||||
static private_key generate();
|
static private_key generate();
|
||||||
static private_key regenerate( const fc::sha256& secret );
|
static private_key regenerate( const fc::sha256& secret );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method of generation enables creating a new private key in a deterministic manner relative to
|
||||||
|
* an initial seed. A public_key created from the seed can be multiplied by the offset to calculate
|
||||||
|
* the new public key without having to know the private key.
|
||||||
|
*/
|
||||||
|
static private_key generate_from_seed( const fc::sha256& seed, const fc::sha256& offset = fc::sha256() );
|
||||||
|
|
||||||
fc::sha256 get_secret()const; // get the private key secret
|
fc::sha256 get_secret()const; // get the private key secret
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -243,8 +243,8 @@ struct ssl_bignum
|
||||||
|
|
||||||
// multiply by digest
|
// multiply by digest
|
||||||
ssl_bignum one;
|
ssl_bignum one;
|
||||||
bn_ctx ctx(BN_CTX_new());
|
|
||||||
BN_one(one);
|
BN_one(one);
|
||||||
|
bn_ctx ctx(BN_CTX_new());
|
||||||
|
|
||||||
ec_point result(EC_POINT_new(group));
|
ec_point result(EC_POINT_new(group));
|
||||||
EC_POINT_mul(group, result, z, master_pub, one, ctx);
|
EC_POINT_mul(group, result, z, master_pub, one, ctx);
|
||||||
|
|
@ -259,25 +259,41 @@ struct ssl_bignum
|
||||||
private_key::private_key()
|
private_key::private_key()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
private_key private_key::generate_from_seed( const fc::sha256& seed, const fc::sha256& offset )
|
||||||
|
{
|
||||||
|
ssl_bignum z;
|
||||||
|
BN_bin2bn((unsigned char*)&offset, sizeof(offset), z);
|
||||||
|
|
||||||
|
ec_group group(EC_GROUP_new_by_curve_name(NID_secp256k1));
|
||||||
|
ssl_bignum order;
|
||||||
|
bn_ctx ctx(BN_CTX_new());
|
||||||
|
EC_GROUP_get_order(group, order, ctx);
|
||||||
|
|
||||||
|
// secexp = (seed + z) % order
|
||||||
|
ssl_bignum secexp;
|
||||||
|
BN_bin2bn((unsigned char*)&seed, sizeof(seed), secexp);
|
||||||
|
BN_add(secexp, secexp, z);
|
||||||
|
BN_mod(secexp, secexp, order, ctx);
|
||||||
|
|
||||||
|
fc::sha256 secret;
|
||||||
|
assert(BN_num_bytes(secexp) == sizeof(secret));
|
||||||
|
BN_bn2bin(secexp, (unsigned char*)&secret);
|
||||||
|
return regenerate( secret );
|
||||||
|
}
|
||||||
|
|
||||||
private_key private_key::regenerate( const fc::sha256& secret )
|
private_key private_key::regenerate( const fc::sha256& secret )
|
||||||
{
|
{
|
||||||
private_key self;
|
private_key self;
|
||||||
self.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
|
self.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
|
||||||
if( !self.my->_key ) FC_THROW_EXCEPTION( exception, "Unable to generate EC key" );
|
if( !self.my->_key ) FC_THROW_EXCEPTION( exception, "Unable to generate EC key" );
|
||||||
|
|
||||||
BIGNUM* bn = BN_bin2bn( (const unsigned char*)&secret, 32, BN_new() );
|
ssl_bignum bn;
|
||||||
if( bn == NULL )
|
BN_bin2bn( (const unsigned char*)&secret, 32, bn );
|
||||||
{
|
|
||||||
FC_THROW_EXCEPTION( exception, "unable to create bignum from secret" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !EC_KEY_regenerate_key(self.my->_key,bn) )
|
if( !EC_KEY_regenerate_key(self.my->_key,bn) )
|
||||||
{
|
{
|
||||||
BN_clear_free(bn);
|
|
||||||
FC_THROW_EXCEPTION( exception, "unable to regenerate key" );
|
FC_THROW_EXCEPTION( exception, "unable to regenerate key" );
|
||||||
}
|
}
|
||||||
|
|
||||||
BN_clear_free(bn);
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue