From f92d5b6cebf6bac303f4db68d96ee22c192f4c79 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 8 Jun 2012 20:47:05 -0700 Subject: [PATCH] Untie the dependencies between NewcoinAddress and BIGNUM. --- src/DeterministicKeys.cpp | 20 +++++++++++------ src/NewcoinAddress.cpp | 21 ++++++++++++++++++ src/NewcoinAddress.h | 3 ++- src/key.h | 45 ++++++++++++++++++++++++++++++++++----- 4 files changed, 76 insertions(+), 13 deletions(-) diff --git a/src/DeterministicKeys.cpp b/src/DeterministicKeys.cpp index e6717540bc..75e36bdc21 100644 --- a/src/DeterministicKeys.cpp +++ b/src/DeterministicKeys.cpp @@ -144,14 +144,14 @@ EC_KEY* CKey::GenerateRootPubKey(BIGNUM* pubGenerator) } // --> public generator -static BIGNUM* makeHash(const NewcoinAddress& generator, int seq, BIGNUM* order) +static BIGNUM* makeHash(const NewcoinAddress& pubGen, int seq, BIGNUM* order) { int subSeq=0; BIGNUM* ret=NULL; do { Serializer s((33*8+32+32)/8); - s.addRaw(generator.getFamilyGenerator()); + s.addRaw(pubGen.getFamilyGenerator()); s.add32(seq); s.add32(subSeq++); uint256 root=s.getSHA512Half(); @@ -164,9 +164,9 @@ static BIGNUM* makeHash(const NewcoinAddress& generator, int seq, BIGNUM* order) } // --> public generator -EC_KEY* CKey::GeneratePublicDeterministicKey(const NewcoinAddress& generator, int seq) +EC_KEY* CKey::GeneratePublicDeterministicKey(const NewcoinAddress& pubGen, int seq) { // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point - EC_KEY* rootKey = CKey::GenerateRootPubKey(generator.getFamilyGeneratorBN()); + EC_KEY* rootKey = CKey::GenerateRootPubKey(pubGen.getFamilyGeneratorBN()); const EC_POINT* rootPubKey = EC_KEY_get0_public_key(rootKey); BN_CTX* ctx = BN_CTX_new(); EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1); @@ -194,7 +194,7 @@ EC_KEY* CKey::GeneratePublicDeterministicKey(const NewcoinAddress& generator, in // Calculate the private additional key. if (success) { - hash = makeHash(generator, seq, order); + hash = makeHash(pubGen, seq, order); if(!hash) success = false; } @@ -217,8 +217,14 @@ EC_KEY* CKey::GeneratePublicDeterministicKey(const NewcoinAddress& generator, in return success ? pkey : NULL; } +EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& pubGen, const uint256& u, int seq) +{ + CBigNum bn(u); + return GeneratePrivateDeterministicKey(pubGen, static_cast(&bn), seq); +} + // --> root private key -EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& family, const BIGNUM* rootPrivKey, int seq) +EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& pubGen, const BIGNUM* rootPrivKey, int seq) { // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order BN_CTX* ctx=BN_CTX_new(); if(ctx==NULL) return NULL; @@ -248,7 +254,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& family, cons } // calculate the private additional key - BIGNUM* privKey=makeHash(family, seq, order); + BIGNUM* privKey=makeHash(pubGen, seq, order); if(privKey==NULL) { BN_free(order); diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp index 05179cfd06..715863c3e7 100644 --- a/src/NewcoinAddress.cpp +++ b/src/NewcoinAddress.cpp @@ -503,12 +503,33 @@ BIGNUM* NewcoinAddress::getFamilyGeneratorBN() const throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion))); } + assert(vchData.size() <= (256 / 8)); BIGNUM* ret = BN_bin2bn(&vchData[0], vchData.size(), NULL); assert(ret); return ret; } +uint256 NewcoinAddress::getFamilyGeneratorU() const +{ + switch (nVersion) { + case VER_NONE: + throw std::runtime_error("unset source"); + + case VER_FAMILY_GENERATOR: + // Do nothing. + break; + + default: + throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion))); + } + + assert(vchData.size() <= (256 / 8)); + uint256 ret; + memcpy(ret.begin() + (ret.size() - vchData.size()), &vchData[0], vchData.size()); + return ret; +} + const std::vector& NewcoinAddress::getFamilyGenerator() const { switch (nVersion) { diff --git a/src/NewcoinAddress.h b/src/NewcoinAddress.h index daf30cdb9c..8e3069d722 100644 --- a/src/NewcoinAddress.h +++ b/src/NewcoinAddress.h @@ -135,7 +135,8 @@ public: // Family Generators // Use to generate a master or regular family. // - BIGNUM* getFamilyGeneratorBN() const; + BIGNUM* getFamilyGeneratorBN() const; // DEPRECATED + uint256 getFamilyGeneratorU() const; const std::vector& getFamilyGenerator() const; std::string humanFamilyGenerator() const; diff --git a/src/key.h b/src/key.h index 10ab23a237..c287c51490 100644 --- a/src/key.h +++ b/src/key.h @@ -128,28 +128,41 @@ public: static EC_KEY* GenerateRootPubKey(BIGNUM* pubGenerator); static EC_KEY* GeneratePublicDeterministicKey(const NewcoinAddress& generator, int n); static EC_KEY* GeneratePrivateDeterministicKey(const NewcoinAddress& family, const BIGNUM* rootPriv, int n); + static EC_KEY* GeneratePrivateDeterministicKey(const NewcoinAddress& family, const uint256& rootPriv, int n); - CKey(const uint128& passPhrase) : fSet(true) + CKey(const uint128& passPhrase) : fSet(false) { pkey = GenerateRootDeterministicKey(passPhrase); + fSet = true; assert(pkey); } - CKey(const NewcoinAddress& generator, int n) : fSet(true) + CKey(const NewcoinAddress& generator, int n) : fSet(false) { // public deterministic key pkey = GeneratePublicDeterministicKey(generator, n); + fSet = true; assert(pkey); } - CKey(const NewcoinAddress& base, const BIGNUM* rootPrivKey, int n) : fSet(true) + CKey(const NewcoinAddress& base, const BIGNUM* rootPrivKey, int n) : fSet(false) { // private deterministic key pkey = GeneratePrivateDeterministicKey(base, rootPrivKey, n); + fSet = true; assert(pkey); } - CKey(const uint256& pKey) : fSet(false) + CKey(const uint256& privateKey) : pkey(NULL), fSet(false) { - SetPrivateKeyU(pKey); + SetPrivateKeyU(privateKey); + } + + CKey(const NewcoinAddress& masterKey, int keyNum, bool isPublic) : pkey(NULL), fSet(false) + { + if (isPublic) + SetPubSeq(masterKey, keyNum); + else + SetPrivSeq(masterKey, keyNum); + fSet = true; } bool IsNull() const @@ -233,6 +246,28 @@ public: BN_free(bn); } + void SetPubSeq(const NewcoinAddress& masterKey, int keyNum) + { + EC_KEY* key = GeneratePublicDeterministicKey(masterKey, keyNum); + if (key == NULL) + throw key_error("CKey::SetPubSeq: GenPubDetKey failed"); + if (pkey != NULL) + EC_KEY_free(pkey); + pkey = key; + fSet = true; + } + + void SetPrivSeq(const NewcoinAddress& masterKey, int keyNum) + { + uint256 privKey; + EC_KEY* key = GeneratePrivateDeterministicKey(masterKey, masterKey.getFamilyGeneratorU(), keyNum); + privKey.zero(); + if (pkey != NULL) + EC_KEY_free(pkey); + pkey = key; + fSet = true; + } + CPrivKey GetPrivKey() { unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);