From 314eabb2933f513451dc5fa41cf344134a51255d Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Tue, 2 Jul 2013 17:09:15 -0400 Subject: [PATCH] update elliptic curve crypto for deterministic key generation --- include/fc/crypto/base58.hpp | 6 +++--- include/fc/crypto/elliptic.hpp | 18 ++++++++++++++++-- src/crypto/elliptic.cpp | 34 +++++++++++++++++++++++++--------- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/include/fc/crypto/base58.hpp b/include/fc/crypto/base58.hpp index 71beb15..63974d7 100644 --- a/include/fc/crypto/base58.hpp +++ b/include/fc/crypto/base58.hpp @@ -2,7 +2,7 @@ #include namespace fc { - fc::string to_base58( const char* d, size_t s ); - fc::vector from_base58( const fc::string& base58_str ); - size_t from_base58( const fc::string& base58_str, char* out_data, size_t out_data_len ); + std::string to_base58( const char* d, size_t s ); + std::vector from_base58( const std::string& base58_str ); + size_t from_base58( const std::string& base58_str, char* out_data, size_t out_data_len ); } diff --git a/include/fc/crypto/elliptic.hpp b/include/fc/crypto/elliptic.hpp index 7aac348..b75ef5d 100644 --- a/include/fc/crypto/elliptic.hpp +++ b/include/fc/crypto/elliptic.hpp @@ -19,6 +19,10 @@ namespace fc { typedef fc::array signature; typedef fc::array compact_signature; + /** + * @class public_key + * @brief contains only the public point of an elliptic curve key. + */ class public_key { public: @@ -31,7 +35,7 @@ namespace fc { public_key( const compact_signature& c, const fc::sha256& digest ); bool valid()const; - public_key mult( const fc::sha256& digest ); + public_key mult( const fc::sha256& offset ); public_key( public_key&& pk ); public_key& operator=( public_key&& pk ); @@ -41,7 +45,10 @@ namespace fc { fc::fwd my; }; - + /** + * @class private_key + * @brief an elliptic curve private key. + */ class private_key { public: @@ -57,6 +64,13 @@ namespace fc { static private_key generate(); 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 /** diff --git a/src/crypto/elliptic.cpp b/src/crypto/elliptic.cpp index 6443674..4351b05 100644 --- a/src/crypto/elliptic.cpp +++ b/src/crypto/elliptic.cpp @@ -243,8 +243,8 @@ struct ssl_bignum // multiply by digest ssl_bignum one; - bn_ctx ctx(BN_CTX_new()); BN_one(one); + bn_ctx ctx(BN_CTX_new()); ec_point result(EC_POINT_new(group)); 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::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 self; self.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 ); if( !self.my->_key ) FC_THROW_EXCEPTION( exception, "Unable to generate EC key" ); - BIGNUM* bn = BN_bin2bn( (const unsigned char*)&secret, 32, BN_new() ); - if( bn == NULL ) - { - FC_THROW_EXCEPTION( exception, "unable to create bignum from secret" ); - } + ssl_bignum bn; + BN_bin2bn( (const unsigned char*)&secret, 32, bn ); if( !EC_KEY_regenerate_key(self.my->_key,bn) ) { - BN_clear_free(bn); FC_THROW_EXCEPTION( exception, "unable to regenerate key" ); } - - BN_clear_free(bn); return self; }