Some refactoring
This commit is contained in:
parent
0f67ca751e
commit
5ecdcba4b6
6 changed files with 222 additions and 210 deletions
|
|
@ -54,14 +54,9 @@ namespace fc {
|
|||
typename H::encoder encoder;
|
||||
};
|
||||
|
||||
template<>
|
||||
unsigned int hmac<sha224>::internal_block_size() const { return 64; }
|
||||
|
||||
template<>
|
||||
unsigned int hmac<sha256>::internal_block_size() const { return 64; }
|
||||
|
||||
template<>
|
||||
unsigned int hmac<sha512>::internal_block_size() const { return 128; }
|
||||
typedef hmac<fc::sha224> hmac_sha224;
|
||||
typedef hmac<fc::sha256> hmac_sha256;
|
||||
typedef hmac<fc::sha512> hmac_sha512;
|
||||
}
|
||||
|
||||
#endif /* HMAC_HPP */
|
||||
|
|
|
|||
|
|
@ -1,12 +1,71 @@
|
|||
#include <fc/crypto/base58.hpp>
|
||||
#include <fc/crypto/elliptic.hpp>
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/crypto/ripemd160.hpp>
|
||||
|
||||
/* stuff common to all ecc implementations */
|
||||
|
||||
#define BTC_EXT_PUB_MAGIC (0x0488B21E)
|
||||
#define BTC_EXT_PRIV_MAGIC (0x0488ADE4)
|
||||
|
||||
namespace fc { namespace ecc {
|
||||
|
||||
namespace detail {
|
||||
typedef fc::array<char,37> chr37;
|
||||
|
||||
fc::sha256 _left( const fc::sha512& v )
|
||||
{
|
||||
fc::sha256 result;
|
||||
memcpy( result.data(), v.data(), 32 );
|
||||
return result;
|
||||
}
|
||||
|
||||
fc::sha256 _right( const fc::sha512& v )
|
||||
{
|
||||
fc::sha256 result;
|
||||
memcpy( result.data(), v.data() + 32, 32 );
|
||||
return result;
|
||||
}
|
||||
|
||||
static void _put( unsigned char** dest, unsigned int i)
|
||||
{
|
||||
*(*dest)++ = (i >> 24) & 0xff;
|
||||
*(*dest)++ = (i >> 16) & 0xff;
|
||||
*(*dest)++ = (i >> 8) & 0xff;
|
||||
*(*dest)++ = i & 0xff;
|
||||
}
|
||||
|
||||
static unsigned int _get( unsigned char** src )
|
||||
{
|
||||
unsigned int result = *(*src)++ << 24;
|
||||
result |= *(*src)++ << 16;
|
||||
result |= *(*src)++ << 8;
|
||||
result |= *(*src)++;
|
||||
return result;
|
||||
}
|
||||
|
||||
static chr37 _derive_message( char first, const char* key32, int i )
|
||||
{
|
||||
chr37 result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
*dest++ = first;
|
||||
memcpy( dest, key32, 32 ); dest += 32;
|
||||
_put( &dest, i );
|
||||
return result;
|
||||
}
|
||||
|
||||
chr37 _derive_message( const public_key_data& key, int i )
|
||||
{
|
||||
return _derive_message( *key.begin(), key.begin() + 1, i );
|
||||
}
|
||||
|
||||
static chr37 _derive_message( const private_key_secret& key, int i )
|
||||
{
|
||||
return _derive_message( 0, key.data(), i );
|
||||
}
|
||||
}
|
||||
|
||||
public_key public_key::from_key_data( const public_key_data &data ) {
|
||||
return public_key(data);
|
||||
}
|
||||
|
|
@ -120,6 +179,145 @@ namespace fc { namespace ecc {
|
|||
return private_key( k );
|
||||
}
|
||||
|
||||
static fc::string _to_base58( const extended_key_data& key )
|
||||
{
|
||||
char buffer[key.size() + 4];
|
||||
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) );
|
||||
}
|
||||
|
||||
static void _parse_extended_data( unsigned char* buffer, fc::string base58 )
|
||||
{
|
||||
memset( buffer, 0, 78 );
|
||||
std::vector<char> decoded = fc::from_base58( base58 );
|
||||
unsigned int i = 0;
|
||||
for ( char c : decoded )
|
||||
{
|
||||
if ( i >= 78 || i > decoded.size() - 4 ) { break; }
|
||||
buffer[i++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
extended_public_key extended_public_key::derive_child(int i) const
|
||||
{
|
||||
FC_ASSERT( !(i&0x80000000), "Can't derive hardened public key!" );
|
||||
return derive_normal_child(i);
|
||||
}
|
||||
|
||||
extended_key_data extended_public_key::serialize_extended() const
|
||||
{
|
||||
extended_key_data result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
detail::_put( &dest, BTC_EXT_PUB_MAGIC );
|
||||
*dest++ = depth;
|
||||
detail::_put( &dest, parent_fp );
|
||||
detail::_put( &dest, child_num );
|
||||
memcpy( dest, c.data(), c.data_size() ); dest += 32;
|
||||
public_key_data key = serialize();
|
||||
memcpy( dest, key.begin(), key.size() );
|
||||
return result;
|
||||
}
|
||||
|
||||
fc::string extended_public_key::str() const
|
||||
{
|
||||
return _to_base58( serialize_extended() );
|
||||
}
|
||||
|
||||
extended_public_key extended_public_key::from_base58( const fc::string& base58 )
|
||||
{
|
||||
unsigned char buffer[78];
|
||||
unsigned char* ptr = buffer;
|
||||
_parse_extended_data( buffer, base58 );
|
||||
FC_ASSERT( detail::_get( &ptr ) == BTC_EXT_PUB_MAGIC, "Invalid extended private key" );
|
||||
uint8_t d = *ptr++;
|
||||
int fp = detail::_get( &ptr );
|
||||
int cn = detail::_get( &ptr );
|
||||
fc::sha256 chain;
|
||||
memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
|
||||
public_key_data key;
|
||||
memcpy( key.begin(), ptr, key.size() );
|
||||
return extended_public_key( key, chain, cn, fp, d );
|
||||
}
|
||||
|
||||
extended_public_key extended_private_key::get_extended_public_key() const
|
||||
{
|
||||
return extended_public_key( get_public_key(), c, child_num, parent_fp, depth );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::derive_child(int i) const
|
||||
{
|
||||
return i < 0 ? derive_hardened_child(i) : derive_normal_child(i);
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::derive_normal_child(int i) const
|
||||
{
|
||||
const detail::chr37 data = detail::_derive_message( get_public_key().serialize(), i );
|
||||
hmac_sha512 mac;
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
|
||||
return private_derive_rest( l, i );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::derive_hardened_child(int i) const
|
||||
{
|
||||
hmac_sha512 mac;
|
||||
private_key_secret key = get_secret();
|
||||
const detail::chr37 data = detail::_derive_message( key, i );
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
|
||||
return private_derive_rest( l, i );
|
||||
}
|
||||
|
||||
extended_key_data extended_private_key::serialize_extended() const
|
||||
{
|
||||
extended_key_data result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
detail::_put( &dest, BTC_EXT_PRIV_MAGIC );
|
||||
*dest++ = depth;
|
||||
detail::_put( &dest, parent_fp );
|
||||
detail::_put( &dest, child_num );
|
||||
memcpy( dest, c.data(), c.data_size() ); dest += 32;
|
||||
*dest++ = 0;
|
||||
private_key_secret key = get_secret();
|
||||
memcpy( dest, key.data(), key.data_size() );
|
||||
return result;
|
||||
}
|
||||
|
||||
fc::string extended_private_key::str() const
|
||||
{
|
||||
return _to_base58( serialize_extended() );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::from_base58( const fc::string& base58 )
|
||||
{
|
||||
unsigned char buffer[78];
|
||||
unsigned char* ptr = buffer;
|
||||
_parse_extended_data( buffer, base58 );
|
||||
FC_ASSERT( detail::_get( &ptr ) == BTC_EXT_PRIV_MAGIC, "Invalid extended private key" );
|
||||
uint8_t d = *ptr++;
|
||||
int fp = detail::_get( &ptr );
|
||||
int cn = detail::_get( &ptr );
|
||||
fc::sha256 chain;
|
||||
memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
|
||||
ptr++;
|
||||
private_key_secret key;
|
||||
memcpy( key.data(), ptr, key.data_size() );
|
||||
return extended_private_key( private_key::regenerate(key), chain, cn, fp, d );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::generate_master( const fc::string& seed )
|
||||
{
|
||||
return generate_master( seed.c_str(), seed.size() );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::generate_master( const char* seed, uint32_t seed_len )
|
||||
{
|
||||
hmac_sha512 mac;
|
||||
fc::sha512 hash = mac.digest( "Bitcoin seed", 12, seed, seed_len );
|
||||
extended_private_key result( private_key::regenerate( detail::_left(hash) ),
|
||||
detail::_right(hash) );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void to_variant( const ecc::private_key& var, variant& vo )
|
||||
|
|
|
|||
|
|
@ -14,9 +14,6 @@
|
|||
|
||||
#include "_elliptic_impl_priv.hpp"
|
||||
|
||||
#define BTC_EXT_PUB_MAGIC (0x0488B21E)
|
||||
#define BTC_EXT_PRIV_MAGIC (0x0488ADE4)
|
||||
|
||||
namespace fc { namespace ecc {
|
||||
namespace detail
|
||||
{
|
||||
|
|
@ -47,6 +44,11 @@ namespace fc { namespace ecc {
|
|||
|
||||
public_key_data _key;
|
||||
};
|
||||
|
||||
typedef fc::array<char,37> chr37;
|
||||
chr37 _derive_message( const public_key_data& key, int i );
|
||||
fc::sha256 _left( const fc::sha512& v );
|
||||
fc::sha256 _right( const fc::sha512& v );
|
||||
}
|
||||
|
||||
static const public_key_data empty_pub;
|
||||
|
|
@ -156,230 +158,36 @@ namespace fc { namespace ecc {
|
|||
FC_ASSERT( pk_len == my->_key.size() );
|
||||
}
|
||||
|
||||
static fc::sha256 _left( const fc::sha512& v )
|
||||
{
|
||||
fc::sha256 result;
|
||||
memcpy( result.data(), v.data(), 32 );
|
||||
return result;
|
||||
}
|
||||
|
||||
static fc::sha256 _right( const fc::sha512& v )
|
||||
{
|
||||
fc::sha256 result;
|
||||
memcpy( result.data(), v.data() + 32, 32 );
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef fc::array<char,37> chr37;
|
||||
|
||||
static void _put( unsigned char** dest, unsigned int i)
|
||||
{
|
||||
*(*dest)++ = (i >> 24) & 0xff;
|
||||
*(*dest)++ = (i >> 16) & 0xff;
|
||||
*(*dest)++ = (i >> 8) & 0xff;
|
||||
*(*dest)++ = i & 0xff;
|
||||
}
|
||||
|
||||
static unsigned int _get( unsigned char** src )
|
||||
{
|
||||
unsigned int result = *(*src)++ << 24;
|
||||
result |= *(*src)++ << 16;
|
||||
result |= *(*src)++ << 8;
|
||||
result |= *(*src)++;
|
||||
return result;
|
||||
}
|
||||
|
||||
static chr37 _derive_message( char first, const char* key32, int i )
|
||||
{
|
||||
chr37 result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
*dest++ = first;
|
||||
memcpy( dest, key32, 32 ); dest += 32;
|
||||
_put( &dest, i );
|
||||
return result;
|
||||
}
|
||||
|
||||
static chr37 _derive_message( const public_key_data& key, int i )
|
||||
{
|
||||
return _derive_message( *key.begin(), key.begin() + 1, i );
|
||||
}
|
||||
|
||||
static chr37 _derive_message( const private_key_secret& key, int i )
|
||||
{
|
||||
return _derive_message( 0, key.data(), i );
|
||||
}
|
||||
|
||||
static fc::string _to_base58( const extended_key_data& key )
|
||||
{
|
||||
char buffer[key.size() + 4];
|
||||
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) );
|
||||
}
|
||||
|
||||
static void _parse_extended_data( unsigned char* buffer, fc::string base58 )
|
||||
{
|
||||
memset( buffer, 0, 78 );
|
||||
std::vector<char> decoded = fc::from_base58( base58 );
|
||||
unsigned int i = 0;
|
||||
for ( char c : decoded )
|
||||
{
|
||||
if ( i >= 78 || i > decoded.size() - 4 ) { break; }
|
||||
buffer[i++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
typedef hmac<fc::sha512> hmac_sha512;
|
||||
|
||||
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_child(int i) const
|
||||
{
|
||||
FC_ASSERT( !(i&0x80000000), "Can't derive hardened public key!" );
|
||||
return derive_normal_child(i);
|
||||
}
|
||||
|
||||
extended_public_key extended_public_key::derive_normal_child(int i) const
|
||||
{
|
||||
hmac_sha512 mac;
|
||||
public_key_data key = serialize();
|
||||
const chr37 data = _derive_message( key, i );
|
||||
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 = _left(l);
|
||||
fc::sha256 left = detail::_left(l);
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) key.begin(), key.size(), (unsigned char*) left.data() ) > 0 );
|
||||
extended_public_key result( key, _right(l), i, fingerprint(), depth + 1 );
|
||||
extended_public_key result( key, detail::_right(l), i, fingerprint(), depth + 1 );
|
||||
return result;
|
||||
}
|
||||
|
||||
extended_key_data extended_public_key::serialize_extended() const
|
||||
{
|
||||
extended_key_data result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
_put( &dest, BTC_EXT_PUB_MAGIC );
|
||||
*dest++ = depth;
|
||||
_put( &dest, parent_fp );
|
||||
_put( &dest, child_num );
|
||||
memcpy( dest, c.data(), c.data_size() ); dest += 32;
|
||||
public_key_data key = serialize();
|
||||
memcpy( dest, key.begin(), key.size() );
|
||||
return result;
|
||||
}
|
||||
|
||||
fc::string extended_public_key::str() const
|
||||
{
|
||||
return _to_base58( serialize_extended() );
|
||||
}
|
||||
|
||||
extended_public_key extended_public_key::from_base58( const fc::string& base58 )
|
||||
{
|
||||
unsigned char buffer[78];
|
||||
unsigned char* ptr = buffer;
|
||||
_parse_extended_data( buffer, base58 );
|
||||
FC_ASSERT( _get( &ptr ) == BTC_EXT_PUB_MAGIC, "Invalid extended private key" );
|
||||
uint8_t d = *ptr++;
|
||||
int fp = _get( &ptr );
|
||||
int cn = _get( &ptr );
|
||||
fc::sha256 chain;
|
||||
memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
|
||||
public_key_data key;
|
||||
memcpy( key.begin(), ptr, key.size() );
|
||||
return extended_public_key( key, chain, cn, fp, d );
|
||||
}
|
||||
|
||||
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) { }
|
||||
|
||||
extended_public_key extended_private_key::get_extended_public_key() const
|
||||
{
|
||||
return extended_public_key( get_public_key(), c, child_num, parent_fp, depth );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::derive_child(int i) const
|
||||
{
|
||||
return i < 0 ? derive_hardened_child(i) : derive_normal_child(i);
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::derive_normal_child(int i) const
|
||||
{
|
||||
const chr37 data = _derive_message( get_public_key().serialize(), i );
|
||||
hmac_sha512 mac;
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
|
||||
return private_derive_rest( l, i );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::derive_hardened_child(int i) const
|
||||
{
|
||||
hmac_sha512 mac;
|
||||
private_key_secret key = get_secret();
|
||||
const chr37 data = _derive_message( key, i );
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
|
||||
return private_derive_rest( l, i );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::private_derive_rest( const fc::sha512& hash,
|
||||
int i) const
|
||||
{
|
||||
fc::sha256 left = _left(hash);
|
||||
fc::sha256 left = detail::_left(hash);
|
||||
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 ), _right(hash),
|
||||
extended_private_key result( private_key::regenerate( left ), detail::_right(hash),
|
||||
i, fingerprint(), depth + 1 );
|
||||
return result;
|
||||
}
|
||||
|
||||
extended_key_data extended_private_key::serialize_extended() const
|
||||
{
|
||||
extended_key_data result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
_put( &dest, BTC_EXT_PRIV_MAGIC );
|
||||
*dest++ = depth;
|
||||
_put( &dest, parent_fp );
|
||||
_put( &dest, child_num );
|
||||
memcpy( dest, c.data(), c.data_size() ); dest += 32;
|
||||
*dest++ = 0;
|
||||
private_key_secret key = get_secret();
|
||||
memcpy( dest, key.data(), key.data_size() );
|
||||
return result;
|
||||
}
|
||||
|
||||
fc::string extended_private_key::str() const
|
||||
{
|
||||
return _to_base58( serialize_extended() );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::from_base58( const fc::string& base58 )
|
||||
{
|
||||
unsigned char buffer[78];
|
||||
unsigned char* ptr = buffer;
|
||||
_parse_extended_data( buffer, base58 );
|
||||
FC_ASSERT( _get( &ptr ) == BTC_EXT_PRIV_MAGIC, "Invalid extended private key" );
|
||||
uint8_t d = *ptr++;
|
||||
int fp = _get( &ptr );
|
||||
int cn = _get( &ptr );
|
||||
fc::sha256 chain;
|
||||
memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
|
||||
ptr++;
|
||||
private_key_secret key;
|
||||
memcpy( key.data(), ptr, key.data_size() );
|
||||
return extended_private_key( private_key::regenerate(key), chain, cn, fp, d );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::generate_master( const fc::string& seed )
|
||||
{
|
||||
return generate_master( seed.c_str(), seed.size() );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::generate_master( const char* seed, uint32_t seed_len )
|
||||
{
|
||||
hmac_sha512 mac;
|
||||
fc::sha512 hash = mac.digest( "Bitcoin seed", 12, seed, seed_len );
|
||||
extended_private_key result( private_key::regenerate( _left(hash) ), _right(hash) );
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
commitment_type blind( const blind_factor_type& blind, uint64_t value )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/fwd_impl.hpp>
|
||||
#include <openssl/sha.h>
|
||||
#include <string.h>
|
||||
|
|
@ -95,4 +96,7 @@ namespace fc {
|
|||
else
|
||||
memset( &bi, char(0), sizeof(bi) );
|
||||
}
|
||||
|
||||
template<>
|
||||
unsigned int hmac<sha224>::internal_block_size() const { return 64; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/fwd_impl.hpp>
|
||||
#include <openssl/sha.h>
|
||||
#include <string.h>
|
||||
|
|
@ -116,4 +117,6 @@ namespace fc {
|
|||
return sha_value._hash[0];
|
||||
}
|
||||
|
||||
template<>
|
||||
unsigned int hmac<sha256>::internal_block_size() const { return 64; }
|
||||
} //end namespace fc
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/fwd_impl.hpp>
|
||||
#include <openssl/sha.h>
|
||||
#include <string.h>
|
||||
|
|
@ -101,4 +102,7 @@ namespace fc {
|
|||
else
|
||||
memset( &bi, char(0), sizeof(bi) );
|
||||
}
|
||||
|
||||
template<>
|
||||
unsigned int hmac<sha512>::internal_block_size() const { return 128; }
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue