update elliptic curve crypto for deterministic key generation

This commit is contained in:
Daniel Larimer 2013-07-02 17:09:15 -04:00
parent 7b18403310
commit 314eabb293
3 changed files with 44 additions and 14 deletions

View file

@ -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 );
} }

View file

@ -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
/** /**

View file

@ -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;
} }