BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
elliptic_common.cpp
Go to the documentation of this file.
1 #include <fc/crypto/base58.hpp>
2 #include <fc/crypto/elliptic.hpp>
3 #include <fc/io/raw.hpp>
4 #include <fc/crypto/hmac.hpp>
5 #include <fc/crypto/openssl.hpp>
7 
8 #ifdef _WIN32
9 # include <malloc.h>
10 #endif
11 
12 /* stuff common to all ecc implementations */
13 
14 #define BTC_EXT_PUB_MAGIC (0x0488B21E)
15 #define BTC_EXT_PRIV_MAGIC (0x0488ADE4)
16 
17 namespace fc { namespace ecc {
18 
19  namespace detail {
21 
23  {
24  fc::sha256 result;
25  memcpy( result.data(), v.data(), 32 );
26  return result;
27  }
28 
30  {
31  fc::sha256 result;
32  memcpy( result.data(), v.data() + 32, 32 );
33  return result;
34  }
35 
36  static void _put( unsigned char** dest, unsigned int i)
37  {
38  *(*dest)++ = (i >> 24) & 0xff;
39  *(*dest)++ = (i >> 16) & 0xff;
40  *(*dest)++ = (i >> 8) & 0xff;
41  *(*dest)++ = i & 0xff;
42  }
43 
44  static unsigned int _get( unsigned char** src )
45  {
46  unsigned int result = *(*src)++ << 24;
47  result |= *(*src)++ << 16;
48  result |= *(*src)++ << 8;
49  result |= *(*src)++;
50  return result;
51  }
52 
53  static chr37 _derive_message( unsigned char first, const unsigned char* key32, int i )
54  {
55  chr37 result;
56  unsigned char* dest = result.data();
57  *dest++ = first;
58  memcpy( dest, key32, 32 ); dest += 32;
59  _put( &dest, i );
60  return result;
61  }
62 
63  chr37 _derive_message( const public_key_data& key, int i )
64  {
65  return _derive_message( *key.data(), key.data() + 1, i );
66  }
67 
68  static chr37 _derive_message( const private_key_secret& key, int i )
69  {
70  return _derive_message( 0, (unsigned char*) key.data(), i );
71  }
72 
73  const ec_group& get_curve()
74  {
75  static const ec_group secp256k1( EC_GROUP_new_by_curve_name( NID_secp256k1 ) );
76  return secp256k1;
77  }
78 
79  static private_key_secret _get_curve_order()
80  {
81  const ec_group& group = get_curve();
82  bn_ctx ctx(BN_CTX_new());
83  ssl_bignum order;
84  FC_ASSERT( EC_GROUP_get_order( group, order, ctx ) );
86  FC_ASSERT( (size_t) BN_num_bytes( order ) == bin.data_size() );
87  FC_ASSERT( (size_t) BN_bn2bin( order, (unsigned char*) bin.data() ) == bin.data_size() );
88  return bin;
89  }
90 
92  {
93  static private_key_secret order = _get_curve_order();
94  return order;
95  }
96 
97  static private_key_secret _get_half_curve_order()
98  {
99  const ec_group& group = get_curve();
100  bn_ctx ctx(BN_CTX_new());
101  ssl_bignum order;
102  FC_ASSERT( EC_GROUP_get_order( group, order, ctx ) );
103  BN_rshift1( order, order );
104  private_key_secret bin;
105  FC_ASSERT( (size_t) BN_num_bytes( order ) == bin.data_size() );
106  FC_ASSERT( (size_t) BN_bn2bin( order, (unsigned char*) bin.data() ) == bin.data_size() );
107  return bin;
108  }
109 
111  {
112  static private_key_secret half_order = _get_half_curve_order();
113  return half_order;
114  }
115  }
116 
117  public_key public_key::from_key_data( const public_key_data &data ) {
118  return public_key(data);
119  }
120 
122  {
124  fc::raw::pack( enc, *this );
125  fc::raw::pack( enc, offset );
126 
127  return add( enc.result() );
128  }
129 
131  {
133  fc::raw::pack( enc, get_public_key() );
134  fc::raw::pack( enc, offset );
135  return generate_from_seed( get_secret(), enc.result() );
136  }
137 
138  std::string public_key::to_base58( const public_key_data &key )
139  {
140  sha256 check = sha256::hash((char*) key.data(), sizeof(key));
141  static_assert(sizeof(key) + 4 == 37, "Elliptic public key size (or its hash) is incorrect");
142  detail::chr37 data;
143  memcpy(data.data(), key.data(), key.size());
144  memcpy(data.data() + key.size(), (const char*)check._hash, 4);
145  return fc::to_base58((char*) data.data(), data.size());
146  }
147 
148  public_key public_key::from_base58( const std::string& b58 )
149  {
150  detail::chr37 data;
151  size_t s = fc::from_base58(b58, (char*)&data, sizeof(data) );
152  FC_ASSERT( s == sizeof(data) );
153 
154  public_key_data key;
155  sha256 check = sha256::hash((char*) data.data(), sizeof(key));
156  FC_ASSERT( memcmp( (char*)check._hash, data.data() + key.size(), 4 ) == 0 );
157  memcpy( (char*)key.data(), data.data(), key.size() );
158  return from_key_data(key);
159  }
160 
161  unsigned int public_key::fingerprint() const
162  {
163  public_key_data key = serialize();
164  ripemd160 hash = ripemd160::hash( sha256::hash( (char*) key.data(), key.size() ) );
165  unsigned char* fp = (unsigned char*) hash._hash;
166  return (fp[0] << 24) | (fp[1] << 16) | (fp[2] << 8) | fp[3];
167  }
168 
169  bool public_key::is_canonical( const compact_signature& c ) {
170  return !(c[1] & 0x80)
171  && !(c[1] == 0 && !(c[2] & 0x80))
172  && !(c[33] & 0x80)
173  && !(c[33] == 0 && !(c[34] & 0x80));
174  }
175 
177  {
178  ssl_bignum z;
179  BN_bin2bn((unsigned char*)&offset, sizeof(offset), z);
180 
181  ec_group group(EC_GROUP_new_by_curve_name(NID_secp256k1));
182  bn_ctx ctx(BN_CTX_new());
183  ssl_bignum order;
184  EC_GROUP_get_order(group, order, ctx);
185 
186  // secexp = (seed + z) % order
187  ssl_bignum secexp;
188  BN_bin2bn((unsigned char*)&seed, sizeof(seed), secexp);
189  BN_add(secexp, secexp, z);
190  BN_mod(secexp, secexp, order, ctx);
191 
192  fc::sha256 secret;
193  FC_ASSERT(BN_num_bytes(secexp) <= int64_t(sizeof(secret)));
194  auto shift = sizeof(secret) - BN_num_bytes(secexp);
195  BN_bn2bin(secexp, ((unsigned char*)&secret)+shift);
196  return regenerate( secret );
197  }
198 
199  fc::sha256 private_key::get_secret( const EC_KEY * const k )
200  {
201  if( !k )
202  {
203  return fc::sha256();
204  }
205 
206  fc::sha256 sec;
207  const BIGNUM* bn = EC_KEY_get0_private_key(k);
208  if( bn == NULL )
209  {
210  FC_THROW_EXCEPTION( exception, "get private key failed" );
211  }
212  int nbytes = BN_num_bytes(bn);
213  BN_bn2bin(bn, &((unsigned char*)&sec)[32-nbytes] );
214  return sec;
215  }
216 
218  {
219  EC_KEY* k = EC_KEY_new_by_curve_name( NID_secp256k1 );
220  if( !k ) FC_THROW_EXCEPTION( exception, "Unable to generate EC key" );
221  if( !EC_KEY_generate_key( k ) )
222  {
223  FC_THROW_EXCEPTION( exception, "ecc key generation error" );
224 
225  }
226 
227  return private_key( k );
228  }
229 
230  static std::string _to_base58( const extended_key_data& key )
231  {
232  char buffer[std::tuple_size<extended_key_data>::value + 4]; // it's a small static array => allocate on stack
233  memcpy( buffer, key.data(), key.size() );
234  fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( (char*)key.data(), key.size() ));
235  memcpy( buffer + key.size(), double_hash.data(), 4 );
236  return fc::to_base58( buffer, sizeof(buffer) );
237  }
238 
239  static void _parse_extended_data( unsigned char* buffer, std::string base58 )
240  {
241  memset( buffer, 0, 78 );
242  std::vector<char> decoded = fc::from_base58( base58 );
243  unsigned int i = 0;
244  for ( char c : decoded )
245  {
246  if ( i >= 78 || i > decoded.size() - 4 ) { break; }
247  buffer[i++] = c;
248  }
249  }
250 
252  {
253  FC_ASSERT( !(i&0x80000000), "Can't derive hardened public key!" );
254  return derive_normal_child(i);
255  }
256 
258  {
259  extended_key_data result;
260  unsigned char* dest = (unsigned char*) result.data();
261  detail::_put( &dest, BTC_EXT_PUB_MAGIC );
262  *dest++ = depth;
263  detail::_put( &dest, parent_fp );
264  detail::_put( &dest, child_num );
265  memcpy( dest, c.data(), c.data_size() ); dest += 32;
266  public_key_data key = serialize();
267  memcpy( dest, key.data(), key.size() );
268  return result;
269  }
270 
272  {
273  return from_base58( _to_base58( data ) );
274  }
275 
276  std::string extended_public_key::str() const
277  {
278  return _to_base58( serialize_extended() );
279  }
280 
282  {
283  unsigned char buffer[78];
284  unsigned char* ptr = buffer;
285  _parse_extended_data( buffer, base58 );
286  FC_ASSERT( detail::_get( &ptr ) == BTC_EXT_PUB_MAGIC, "Invalid extended private key" );
287  uint8_t d = *ptr++;
288  int fp = detail::_get( &ptr );
289  int cn = detail::_get( &ptr );
290  fc::sha256 chain;
291  memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
292  public_key_data key;
293  memcpy( key.data(), ptr, key.size() );
294  return extended_public_key( key, chain, cn, fp, d );
295  }
296 
298  {
299  return extended_public_key( get_public_key(), c, child_num, parent_fp, depth );
300  }
301 
303  {
304  return i < 0 ? derive_hardened_child(i) : derive_normal_child(i);
305  }
306 
308  {
309  const detail::chr37 data = detail::_derive_message( get_public_key().serialize(), i );
310  hmac_sha512 mac;
311  fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.data(), data.size() );
312  return private_derive_rest( l, i );
313  }
314 
316  {
317  hmac_sha512 mac;
319  const detail::chr37 data = detail::_derive_message( key, i );
320  fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.data(), data.size() );
321  return private_derive_rest( l, i );
322  }
323 
325  {
326  extended_key_data result;
327  unsigned char* dest = (unsigned char*) result.data();
328  detail::_put( &dest, BTC_EXT_PRIV_MAGIC );
329  *dest++ = depth;
330  detail::_put( &dest, parent_fp );
331  detail::_put( &dest, child_num );
332  memcpy( dest, c.data(), c.data_size() ); dest += 32;
333  *dest++ = 0;
335  memcpy( dest, key.data(), key.data_size() );
336  return result;
337  }
338 
340  {
341  return from_base58( _to_base58( data ) );
342  }
343 
344  std::string extended_private_key::str() const
345  {
346  return _to_base58( serialize_extended() );
347  }
348 
350  {
351  unsigned char buffer[78];
352  unsigned char* ptr = buffer;
353  _parse_extended_data( buffer, base58 );
354  FC_ASSERT( detail::_get( &ptr ) == BTC_EXT_PRIV_MAGIC, "Invalid extended private key" );
355  uint8_t d = *ptr++;
356  int fp = detail::_get( &ptr );
357  int cn = detail::_get( &ptr );
358  fc::sha256 chain;
359  memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
360  ptr++;
361  private_key_secret key;
362  memcpy( key.data(), ptr, key.data_size() );
363  return extended_private_key( private_key::regenerate(key), chain, cn, fp, d );
364  }
365 
367  {
368  return generate_master( seed.c_str(), seed.size() );
369  }
370 
371  extended_private_key extended_private_key::generate_master( const char* seed, uint32_t seed_len )
372  {
373  hmac_sha512 mac;
374  fc::sha512 hash = mac.digest( "Bitcoin seed", 12, seed, seed_len );
376  detail::_right(hash) );
377  return result;
378  }
379 }
380 
381 void to_variant( const ecc::private_key& var, variant& vo, uint32_t max_depth )
382 {
383  to_variant( var.get_secret(), vo, max_depth );
384 }
385 
386 void from_variant( const variant& var, ecc::private_key& vo, uint32_t max_depth )
387 {
388  fc::sha256 sec;
389  from_variant( var, sec, max_depth );
391 }
392 
393 void to_variant( const ecc::public_key& var, variant& vo, uint32_t max_depth )
394 {
395  to_variant( var.serialize(), vo, max_depth );
396 }
397 
398 void from_variant( const variant& var, ecc::public_key& vo, uint32_t max_depth )
399 {
401  from_variant( var, dat, max_depth );
402  vo = ecc::public_key(dat);
403 }
404 
405 }
fc::hmac::digest
H digest(const char *c, uint32_t c_len, const char *d, uint32_t d_len)
Definition: hmac.hpp:23
fc::ecc::extended_public_key::derive_child
extended_public_key derive_child(int i) const
Definition: elliptic_common.cpp:251
fc::ecc::extended_public_key::derive_normal_child
extended_public_key derive_normal_child(int i) const
Definition: elliptic_secp256k1.cpp:178
fc::to_base58
std::string to_base58(const char *d, size_t s)
Definition: base58.cpp:612
fc::exception
Used to generate a useful error report when an exception is thrown.
Definition: exception.hpp:56
fc::ecc::extended_public_key::serialize_extended
extended_key_data serialize_extended() const
Definition: elliptic_common.cpp:257
fc::ecc::extended_public_key
Definition: elliptic.hpp:147
fc::typelist::first
at< List, 0 > first
Get the type at the beginning of the list.
Definition: typelist.hpp:190
fc::ecc::detail::get_curve
const ec_group & get_curve()
Definition: elliptic_common.cpp:73
fc::ecc::public_key::fingerprint
unsigned int fingerprint() const
Definition: elliptic_common.cpp:161
fc::ecc::extended_private_key::derive_child
extended_private_key derive_child(int i) const
Definition: elliptic_common.cpp:302
openssl.hpp
fc
Definition: api.hpp:15
fc::ecc::private_key::get_secret
private_key_secret get_secret() const
Definition: elliptic_impl_priv.cpp:59
fc::ecc::detail::get_half_curve_order
const private_key_secret & get_half_curve_order()
Definition: elliptic_common.cpp:110
fc::from_base58
std::vector< char > from_base58(const std::string &base58_str)
Definition: base58.cpp:622
fc::ecc::private_key::generate_from_seed
static private_key generate_from_seed(const fc::sha256 &seed, const fc::sha256 &offset=fc::sha256())
Definition: elliptic_common.cpp:176
fc::sha256
Definition: sha256.hpp:10
fc::sha256::data_size
static constexpr size_t data_size()
Definition: sha256.hpp:21
fc::ecc::public_key::to_base58
std::string to_base58() const
Allows to convert current public key object into base58 number.
Definition: elliptic_secp256k1.cpp:112
fc::zero_initialized_array
Definition: zeroed_array.hpp:30
fc::ecc::public_key
contains only the public point of an elliptic curve key.
Definition: elliptic.hpp:35
fc::from_variant
void from_variant(const variant &var, flat_set< T, A... > &vo, uint32_t _max_depth)
Definition: flat.hpp:116
BTC_EXT_PUB_MAGIC
#define BTC_EXT_PUB_MAGIC
Definition: elliptic_common.cpp:14
fc::ecc::extended_public_key::deserialize
static extended_public_key deserialize(const extended_key_data &data)
Definition: elliptic_common.cpp:271
fc::ecc::extended_public_key::from_base58
static extended_public_key from_base58(const std::string &base58)
Definition: elliptic_common.cpp:281
fc::ripemd160::_hash
boost::endian::little_uint32_buf_t _hash[5]
Definition: ripemd160.hpp:71
fc::ecc::private_key
an elliptic curve private key.
Definition: elliptic.hpp:89
fc::ecc::private_key::generate
static private_key generate()
Definition: elliptic_common.cpp:217
fc::sha512
Definition: sha512.hpp:9
fc::ecc::public_key::add
public_key add(const fc::sha256 &offset) const
Definition: elliptic_secp256k1.cpp:102
fc::hmac
Definition: hmac.hpp:18
fc::sha256::encoder::result
sha256 result()
Definition: sha256.cpp:59
fc::ecc::detail::_left
fc::sha256 _left(const fc::sha512 &v)
Definition: elliptic_common.cpp:22
fc::ecc::public_key_data
zero_initialized_array< unsigned char, 33 > public_key_data
Definition: elliptic.hpp:23
BTC_EXT_PRIV_MAGIC
#define BTC_EXT_PRIV_MAGIC
Definition: elliptic_common.cpp:15
fc::ecc::public_key::child
public_key child(const fc::sha256 &offset) const
Definition: elliptic_common.cpp:121
fc::sha512::data
char * data() const
Definition: sha512.cpp:22
fc::sha256::data
char * data() const
Definition: sha256.cpp:29
fc::ripemd160
Definition: ripemd160.hpp:11
fc::ecc::private_key::private_key
private_key()
Definition: elliptic_impl_priv.cpp:32
fc::ssl_bignum
Definition: openssl.hpp:53
fc::ecc::extended_public_key::extended_public_key
extended_public_key(const public_key &k, const sha256 &c, int child=0, int parent_fp=0, uint8_t depth=0)
Definition: elliptic_secp256k1.cpp:174
fc::sha256::_hash
boost::endian::little_uint64_buf_t _hash[4]
Definition: sha256.hpp:71
fc::to_variant
void to_variant(const flat_set< T, A... > &var, variant &vo, uint32_t _max_depth)
Definition: flat.hpp:105
fc::ecc::extended_private_key::deserialize
static extended_private_key deserialize(const extended_key_data &data)
Definition: elliptic_common.cpp:339
fc::ecc::private_key::child
private_key child(const fc::sha256 &offset) const
Definition: elliptic_common.cpp:130
fc::ecc::extended_private_key::derive_normal_child
extended_private_key derive_normal_child(int i) const
Definition: elliptic_common.cpp:307
fc::ecc::detail::_right
fc::sha256 _right(const fc::sha512 &v)
Definition: elliptic_common.cpp:29
fc::ecc::private_key::get_public_key
public_key get_public_key() const
Definition: elliptic_impl_priv.cpp:70
fc::ecc::extended_private_key::get_extended_public_key
extended_public_key get_extended_public_key() const
Definition: elliptic_common.cpp:297
fc::ecc::extended_private_key::str
std::string str() const
Definition: elliptic_common.cpp:344
fc::ecc::extended_public_key::str
std::string str() const
Definition: elliptic_common.cpp:276
ripemd160.hpp
FC_ASSERT
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
base58.hpp
fc::ecc::extended_private_key::serialize_extended
extended_key_data serialize_extended() const
Definition: elliptic_common.cpp:324
fc::sha256::encoder
Definition: sha256.hpp:35
fc::variant
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition: variant.hpp:198
hmac.hpp
fc::ripemd160::hash
static ripemd160 hash(const fc::sha512 &h)
Definition: ripemd160.cpp:43
fc::ecc::extended_private_key::extended_private_key
extended_private_key(const private_key &k, const sha256 &c, int child=0, int parent_fp=0, uint8_t depth=0)
Definition: elliptic_secp256k1.cpp:193
fc::ecc::extended_private_key::derive_hardened_child
extended_private_key derive_hardened_child(int i) const
Definition: elliptic_common.cpp:315
fc::ecc::public_key::from_base58
static public_key from_base58(const std::string &b58)
Definition: elliptic_common.cpp:148
fc::ecc::detail::chr37
zero_initialized_array< unsigned char, 37 > chr37
Definition: elliptic_common.cpp:20
fc::ecc::public_key::public_key
public_key()
Definition: elliptic_secp256k1.cpp:77
elliptic.hpp
fc::ecc::detail::get_curve_order
const private_key_secret & get_curve_order()
Definition: elliptic_common.cpp:91
fc::ecc::extended_private_key::from_base58
static extended_private_key from_base58(const std::string &base58)
Definition: elliptic_common.cpp:349
FC_THROW_EXCEPTION
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
Definition: exception.hpp:379
fc::ecc::extended_private_key::generate_master
static extended_private_key generate_master(const std::string &seed)
Definition: elliptic_common.cpp:366
fc::ecc::private_key::regenerate
static private_key regenerate(const fc::sha256 &secret)
Definition: elliptic_impl_priv.cpp:52
fc::ecc::extended_private_key
Definition: elliptic.hpp:168
fc::sha256::hash
static sha256 hash(const char *d, uint32_t dlen)
Definition: sha256.cpp:41
fc::ecc::public_key::serialize
public_key_data serialize() const
Definition: elliptic_secp256k1.cpp:118
fc::raw::pack
void pack(Stream &s, const flat_set< T, A... > &value, uint32_t _max_depth)
Definition: flat.hpp:11
BIGNUM
bignum_st BIGNUM
Definition: bigint.hpp:6
raw.hpp