New wallet system. Still missing unit tests, ledger synchronization,

and SQL code. This uses some of the 'magic' properties of elliptic
curves to create related families of public and private keys.
Wallet encryption is not needed because the private keys do not
need to be stored.
This commit is contained in:
JoelKatz
2011-12-26 18:42:50 -08:00
parent 780f94798e
commit 5cec2e9a11
11 changed files with 477 additions and 242 deletions

View File

@@ -8,16 +8,16 @@
#include "Serializer.h"
uint256 CKey::GetBaseFromString(const std::string& phrase)
uint256 CKey::PassPhraseToKey(const std::string& passPhrase)
{
Serializer s;
s.addRaw((const void *) phrase.c_str(), phrase.length());
uint256 base(s.getSHA512Half());
s.addRaw(passPhrase.c_str(), passPhrase.size());
uint256 ret(s.getSHA512Half());
s.secureErase();
return base;
return ret;
}
EC_KEY* CKey::GenerateDeterministicKey(const uint256& base, uint32 n, bool private_key)
EC_KEY* CKey::GenerateRootDeterministicKey(const uint256& key)
{
BN_CTX* ctx=BN_CTX_new();
if(!ctx) return NULL;
@@ -44,9 +44,8 @@ EC_KEY* CKey::GenerateDeterministicKey(const uint256& base, uint32 n, bool priva
int seq=0;
do
{ // private key must be non-zero and less than the curve's order
Serializer s;
s.add32(n);
s.add256(base);
Serializer s(72);
s.add256(key);
s.add32(seq++);
uint256 root=s.getSHA512Half();
s.secureErase();
@@ -62,7 +61,7 @@ EC_KEY* CKey::GenerateDeterministicKey(const uint256& base, uint32 n, bool priva
BN_free(order);
if(private_key && !EC_KEY_set_private_key(pkey, privKey))
if(!EC_KEY_set_private_key(pkey, privKey))
{ // set the random point as the private key
assert(false);
EC_KEY_free(pkey);
@@ -98,8 +97,91 @@ EC_KEY* CKey::GenerateDeterministicKey(const uint256& base, uint32 n, bool priva
return pkey;
}
uint256 CKey::GetRandomBase(void)
static BIGNUM* makeHash(const uint160& family, int seq)
{
uint256 r;
return (RAND_bytes((unsigned char *) &r, sizeof(uint256)) == 1) ? r : 0;
Serializer s;
s.add160(family);
s.add32(seq);
uint256 root=s.getSHA512Half();
s.secureErase();
return BN_bin2bn((const unsigned char *) &root, sizeof(root), NULL);
}
EC_KEY* CKey::GeneratePublicDeterministicKey(const uint160& family, EC_POINT* rootPubKey, int seq)
{ // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
BN_CTX* ctx=BN_CTX_new();
if(ctx==NULL) return NULL;
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
if(pkey==NULL)
{
BN_CTX_free(ctx);
return NULL;
}
EC_POINT *newPoint=EC_POINT_new(EC_KEY_get0_group(pkey));
if(newPoint==NULL)
{
EC_KEY_free(pkey);
BN_CTX_free(ctx);
return NULL;
}
BIGNUM* hash=makeHash(family, seq);
if(hash==NULL)
{
EC_POINT_free(newPoint);
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
}
EC_POINT_mul(EC_KEY_get0_group(pkey), newPoint, hash, NULL, NULL, ctx);
BN_free(hash);
EC_POINT_add(EC_KEY_get0_group(pkey), newPoint, newPoint, rootPubKey, ctx);
EC_KEY_set_public_key(pkey, newPoint);
EC_POINT_free(newPoint);
BN_CTX_free(ctx);
return pkey;
}
EC_KEY* CKey::GeneratePrivateDeterministicKey(const uint160& family, BIGNUM* rootPrivKey, int seq)
{ // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
BN_CTX* ctx=BN_CTX_new();
if(ctx==NULL) return NULL;
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
if(pkey==NULL)
{
BN_CTX_free(ctx);
return NULL;
}
BIGNUM* order=BN_new();
if(order==NULL)
{
BN_CTX_free(ctx);
EC_KEY_free(pkey);
}
EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx);
BIGNUM* privKey=makeHash(family, seq);
BN_mod_add(privKey, privKey, rootPrivKey, order, ctx);
BN_free(order);
EC_KEY_set_private_key(pkey, privKey);
EC_POINT* pubKey=EC_POINT_new(EC_KEY_get0_group(pkey));
EC_POINT_mul(EC_KEY_get0_group(pkey), pubKey, privKey, NULL, NULL, ctx);
BN_free(privKey);
EC_KEY_set_public_key(pkey, pubKey);
EC_POINT_free(pubKey);
BN_CTX_free(ctx);
return pkey;
}