Make NewcoinAddress use new crypto primatives and add unit test.

This commit is contained in:
Arthur Britto
2012-06-12 23:01:19 -07:00
parent eb6898f5ce
commit d4a057cfcd
3 changed files with 159 additions and 34 deletions

View File

@@ -36,7 +36,7 @@ bool NewcoinAddress::isValid() const
break; break;
case VER_ACCOUNT_PRIVATE: case VER_ACCOUNT_PRIVATE:
bValid = key.SetPrivKey(getAccountPrivate()); bValid = key.SetPrivateKeyU(getAccountPrivate());
break; break;
default: default:
@@ -58,6 +58,17 @@ void NewcoinAddress::clear()
// NodePublic // NodePublic
// //
NewcoinAddress NewcoinAddress::createNodePublic(NewcoinAddress& naSeed)
{
CKey ckSeed(naSeed.getFamilySeed());
NewcoinAddress naNew;
// YYY Should there be a GetPubKey() equiv that returns a uint256?
naNew.setNodePublic(ckSeed.GetPubKey());
return naNew;
}
const std::vector<unsigned char>& NewcoinAddress::getNodePublic() const const std::vector<unsigned char>& NewcoinAddress::getNodePublic() const
{ {
switch (nVersion) { switch (nVersion) {
@@ -125,6 +136,19 @@ bool NewcoinAddress::verifyNodePublic(const uint256& hash, const std::string& st
// NodePrivate // NodePrivate
// //
NewcoinAddress NewcoinAddress::createNodePrivate(NewcoinAddress& naSeed)
{
uint256 uPrivKey;
NewcoinAddress naNew;
CKey ckSeed(naSeed.getFamilySeed());
ckSeed.GetPrivateKeyU(uPrivKey);
naNew.setNodePrivate(uPrivKey);
return naNew;
}
const std::vector<unsigned char>& NewcoinAddress::getNodePrivateData() const const std::vector<unsigned char>& NewcoinAddress::getNodePrivateData() const
{ {
switch (nVersion) { switch (nVersion) {
@@ -251,6 +275,16 @@ void NewcoinAddress::setAccountID(const uint160& hash160)
// AccountPublic // AccountPublic
// //
NewcoinAddress NewcoinAddress::createAccountPublic(const NewcoinAddress& naGenerator, int iSeq)
{
CKey ckPub(naGenerator, iSeq);
NewcoinAddress naNew;
naNew.setAccountPublic(ckPub.GetPubKey());
return naNew;
}
const std::vector<unsigned char>& NewcoinAddress::getAccountPublic() const const std::vector<unsigned char>& NewcoinAddress::getAccountPublic() const
{ {
switch (nVersion) { switch (nVersion) {
@@ -335,14 +369,23 @@ NewcoinAddress NewcoinAddress::createAccountID(const uint160& uiAccountID)
// AccountPrivate // AccountPrivate
// //
const std::vector<unsigned char>& NewcoinAddress::getAccountPrivate() const NewcoinAddress NewcoinAddress::createAccountPrivate(const NewcoinAddress& naGenerator, const NewcoinAddress& naSeed, int iSeq)
{
NewcoinAddress naNew;
naNew.setAccountPrivate(naGenerator, naSeed, iSeq);
return naNew;
}
uint256 NewcoinAddress::getAccountPrivate() const
{ {
switch (nVersion) { switch (nVersion) {
case VER_NONE: case VER_NONE:
throw std::runtime_error("unset source"); throw std::runtime_error("unset source");
case VER_ACCOUNT_PRIVATE: case VER_ACCOUNT_PRIVATE:
return vchData; return uint256(vchData);
default: default:
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion))); throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
@@ -380,9 +423,12 @@ void NewcoinAddress::setAccountPrivate(uint256 hash256)
void NewcoinAddress::setAccountPrivate(const NewcoinAddress& generator, const NewcoinAddress& seed, int seq) void NewcoinAddress::setAccountPrivate(const NewcoinAddress& generator, const NewcoinAddress& seed, int seq)
{ {
CKey privkey = CKey(generator, seed.getFamilyPrivateKey(), seq); CKey ckPrivkey = CKey(generator, seed.getFamilyPrivateKey(), seq);
uint256 uPrivKey;
setAccountPrivate(privkey.GetPrivKey()); ckPrivkey.GetPrivateKeyU(uPrivKey);
setAccountPrivate(uPrivKey);
} }
bool NewcoinAddress::accountPrivateSign(const uint256& uHash, std::vector<unsigned char>& vucSig) const bool NewcoinAddress::accountPrivateSign(const uint256& uHash, std::vector<unsigned char>& vucSig) const
@@ -390,7 +436,7 @@ bool NewcoinAddress::accountPrivateSign(const uint256& uHash, std::vector<unsign
CKey ckPrivate; CKey ckPrivate;
bool bResult; bool bResult;
if (!ckPrivate.SetPrivKey(getAccountPrivate())) if (!ckPrivate.SetPrivateKeyU(getAccountPrivate()))
{ {
// Bad private key. // Bad private key.
std::cerr << "accountPrivateSign: Bad private key." << std::endl; std::cerr << "accountPrivateSign: Bad private key." << std::endl;
@@ -406,12 +452,13 @@ bool NewcoinAddress::accountPrivateSign(const uint256& uHash, std::vector<unsign
return bResult; return bResult;
} }
#if 0
bool NewcoinAddress::accountPrivateVerify(const uint256& uHash, const std::vector<unsigned char>& vucSig) const bool NewcoinAddress::accountPrivateVerify(const uint256& uHash, const std::vector<unsigned char>& vucSig) const
{ {
CKey ckPrivate; CKey ckPrivate;
bool bVerified; bool bVerified;
if (!ckPrivate.SetPrivKey(getAccountPrivate())) if (!ckPrivate.SetPrivateKeyU(getAccountPrivate()))
{ {
// Bad private key. // Bad private key.
std::cerr << "accountPrivateVerify: Bad private key." << std::endl; std::cerr << "accountPrivateVerify: Bad private key." << std::endl;
@@ -424,6 +471,7 @@ bool NewcoinAddress::accountPrivateVerify(const uint256& uHash, const std::vecto
return bVerified; return bVerified;
} }
#endif
std::vector<unsigned char> NewcoinAddress::accountPrivateEncrypt(const NewcoinAddress& naPublicTo, const std::vector<unsigned char>& vucPlainText) const std::vector<unsigned char> NewcoinAddress::accountPrivateEncrypt(const NewcoinAddress& naPublicTo, const std::vector<unsigned char>& vucPlainText) const
{ {
@@ -436,7 +484,7 @@ std::vector<unsigned char> NewcoinAddress::accountPrivateEncrypt(const NewcoinAd
// Bad public key. // Bad public key.
std::cerr << "accountPrivateEncrypt: Bad public key." << std::endl; std::cerr << "accountPrivateEncrypt: Bad public key." << std::endl;
} }
else if (!ckPrivate.SetPrivKey(getAccountPrivate())) else if (!ckPrivate.SetPrivateKeyU(getAccountPrivate()))
{ {
// Bad private key. // Bad private key.
std::cerr << "accountPrivateEncrypt: Bad private key." << std::endl; std::cerr << "accountPrivateEncrypt: Bad private key." << std::endl;
@@ -466,7 +514,7 @@ std::vector<unsigned char> NewcoinAddress::accountPrivateDecrypt(const NewcoinAd
// Bad public key. // Bad public key.
std::cerr << "accountPrivateDecrypt: Bad public key." << std::endl; std::cerr << "accountPrivateDecrypt: Bad public key." << std::endl;
} }
else if (!ckPrivate.SetPrivKey(getAccountPrivate())) else if (!ckPrivate.SetPrivateKeyU(getAccountPrivate()))
{ {
// Bad private key. // Bad private key.
std::cerr << "accountPrivateDecrypt: Bad private key." << std::endl; std::cerr << "accountPrivateDecrypt: Bad private key." << std::endl;
@@ -552,6 +600,16 @@ void NewcoinAddress::setFamilyGenerator(const NewcoinAddress& seed)
seed.seedInfo(this, 0); seed.seedInfo(this, 0);
} }
NewcoinAddress NewcoinAddress::createGeneratorPublic(const NewcoinAddress& naSeed)
{
CKey ckSeed(naSeed.getFamilySeed());
NewcoinAddress naNew;
naNew.setFamilyGenerator(ckSeed.GetPubKey());
return naNew;
}
// //
// Family Seed // Family Seed
// //
@@ -702,7 +760,55 @@ BOOST_AUTO_TEST_SUITE(newcoin_address)
BOOST_AUTO_TEST_CASE( my_test ) BOOST_AUTO_TEST_CASE( my_test )
{ {
// BOOST_CHECK( false ); NewcoinAddress naSeed;
BOOST_CHECK(naSeed.setFamilySeedGeneric("masterpassphrase"));
BOOST_CHECK_MESSAGE(naSeed.humanFamilySeed() == "snoPBiXtMeMyMHUVTgbuqAfg1SUTb", naSeed.humanFamilySeed());
NewcoinAddress naNodePublic = NewcoinAddress::createNodePublic(naSeed);
NewcoinAddress naNodePrivate = NewcoinAddress::createNodePrivate(naSeed);
BOOST_CHECK_MESSAGE(naNodePublic.humanNodePublic() == "n94a1u4jAz288pZLtw6yFWVbr89YamrC6JBXPVUj5zmExe5fTVg9", naNodePublic.humanNodePublic());
BOOST_CHECK_MESSAGE(naNodePrivate.humanNodePrivate() == "pnen77YEeUd4fFKG7rycBWcwKpTaeFRkW2WFostaATy1DSupwXe", naNodePrivate.humanNodePrivate());
NewcoinAddress naGenerator;
naGenerator.setFamilyGenerator(naSeed);
BOOST_CHECK_MESSAGE(naGenerator.humanFamilyGenerator() == "fhuJKihSDzV2SkjLn9qbwm5AaRmixDPfFsHDCP6yfDZWcxDFz4mt", naGenerator.humanFamilyGenerator());
NewcoinAddress naAccountPublic0 = NewcoinAddress::createAccountPublic(naGenerator, 0);
NewcoinAddress naAccountPrivate0 = NewcoinAddress::createAccountPrivate(naGenerator, naSeed, 0);
BOOST_CHECK_MESSAGE(naAccountPublic0.humanAccountID() == "iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh", naAccountPublic0.humanAccountID());
BOOST_CHECK_MESSAGE(naAccountPublic0.humanAccountPublic() == "aBQG8RQAzjs1eTKFEAQXi2gS4utcDrEC9wmr7pfUPTr27VCahwgw", naAccountPublic0.humanAccountPublic());
BOOST_CHECK_MESSAGE(naAccountPrivate0.humanAccountPrivate() == "p9JfM6HHr64m6mvB6v5k7G2b1cXzGmYrCNJf6GHPKvFTWdeRVjh", naAccountPrivate0.humanAccountPrivate());
NewcoinAddress naAccountPublic1 = NewcoinAddress::createAccountPublic(naGenerator, 1);
NewcoinAddress naAccountPrivate1 = NewcoinAddress::createAccountPrivate(naGenerator, naSeed, 1);
BOOST_CHECK_MESSAGE(naAccountPublic1.humanAccountID() == "i4bYF7SLUMD7QgSLLpgJx38WJSY12VrRjP", naAccountPublic1.humanAccountID());
BOOST_CHECK_MESSAGE(naAccountPublic1.humanAccountPublic() == "aBPXpTfuLy1Bhk3HnGTTAqnovpKWQ23NpFMNkAF6F1Atg5vDyPiw", naAccountPublic1.humanAccountPublic());
BOOST_CHECK_MESSAGE(naAccountPrivate1.humanAccountPrivate() == "p9JEm822LMizJrr1k7TvdphfENTp6G5ji253Xa5ikzUWVi8ogQt", naAccountPrivate1.humanAccountPrivate());
std::vector<unsigned char> vucTextSrc = strCopy("Hello, nurse!");
uint256 uHash = Serializer::getSHA512Half(vucTextSrc);
std::vector<unsigned char> vucTextSig;
BOOST_CHECK_MESSAGE(naAccountPrivate0.accountPrivateSign(uHash, vucTextSig), "Signing failed.");
BOOST_CHECK_MESSAGE(naAccountPublic0.accountPublicVerify(uHash, vucTextSig), "Verify failed.");
BOOST_CHECK_MESSAGE(!naAccountPublic1.accountPublicVerify(uHash, vucTextSig), "Anti-verify failed.");
BOOST_CHECK_MESSAGE(naAccountPrivate1.accountPrivateSign(uHash, vucTextSig), "Signing failed.");
BOOST_CHECK_MESSAGE(naAccountPublic1.accountPublicVerify(uHash, vucTextSig), "Verify failed.");
BOOST_CHECK_MESSAGE(!naAccountPublic0.accountPublicVerify(uHash, vucTextSig), "Anti-verify failed.");
std::vector<unsigned char> vucTextCipher
= naAccountPrivate0.accountPrivateEncrypt(naAccountPublic1, vucTextSrc);
std::vector<unsigned char> vucTextRecovered
= naAccountPrivate1.accountPrivateDecrypt(naAccountPublic0, vucTextCipher);
BOOST_CHECK_MESSAGE(vucTextSrc == vucTextRecovered, "Encrypt-decrypt failed.");
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@@ -42,6 +42,8 @@ public:
bool verifyNodePublic(const uint256& hash, const std::vector<unsigned char>& vchSig) const; bool verifyNodePublic(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
bool verifyNodePublic(const uint256& hash, const std::string& strSig) const; bool verifyNodePublic(const uint256& hash, const std::string& strSig) const;
static NewcoinAddress createNodePublic(NewcoinAddress& naSeed);
// //
// Node Private // Node Private
// //
@@ -55,6 +57,8 @@ public:
void setNodePrivate(uint256 hash256); void setNodePrivate(uint256 hash256);
void signNodePrivate(const uint256& hash, std::vector<unsigned char>& vchSig) const; void signNodePrivate(const uint256& hash, std::vector<unsigned char>& vchSig) const;
static NewcoinAddress createNodePrivate(NewcoinAddress& naSeed);
// //
// Accounts IDs // Accounts IDs
// //
@@ -67,9 +71,8 @@ public:
static NewcoinAddress createAccountID(const uint160& uiAccountID); static NewcoinAddress createAccountID(const uint160& uiAccountID);
static std::string createHumanAccountID(const std::vector<unsigned char>& vPrivate) { static std::string createHumanAccountID(const std::vector<unsigned char>& vPrivate)
return createAccountPrivate(vPrivate).humanAccountID(); { return createAccountPrivate(vPrivate).humanAccountID(); }
}
// //
// Accounts Public // Accounts Public
@@ -85,22 +88,25 @@ public:
bool accountPublicVerify(const uint256& uHash, const std::vector<unsigned char>& vucSig) const; bool accountPublicVerify(const uint256& uHash, const std::vector<unsigned char>& vucSig) const;
static NewcoinAddress createAccountPublic(const std::vector<unsigned char>& vPublic) static NewcoinAddress createAccountPublic(const std::vector<unsigned char>& vPublic)
{ {
NewcoinAddress naNew; NewcoinAddress naNew;
naNew.setAccountPublic(vPublic); naNew.setAccountPublic(vPublic);
return naNew; return naNew;
} }
static std::string createHumanAccountPublic(const std::vector<unsigned char>& vPublic) { static std::string createHumanAccountPublic(const std::vector<unsigned char>& vPublic) {
return createAccountPublic(vPublic).humanAccountPublic(); return createAccountPublic(vPublic).humanAccountPublic();
} }
// Create a deterministic public key from a public generator.
static NewcoinAddress createAccountPublic(const NewcoinAddress& naGenerator, int iSeq);
// //
// Accounts Private // Accounts Private
// //
const std::vector<unsigned char>& getAccountPrivate() const; uint256 getAccountPrivate() const;
std::string humanAccountPrivate() const; std::string humanAccountPrivate() const;
@@ -110,7 +116,7 @@ public:
void setAccountPrivate(const NewcoinAddress& generator, const NewcoinAddress& seed, int seq); void setAccountPrivate(const NewcoinAddress& generator, const NewcoinAddress& seed, int seq);
bool accountPrivateSign(const uint256& uHash, std::vector<unsigned char>& vucSig) const; bool accountPrivateSign(const uint256& uHash, std::vector<unsigned char>& vucSig) const;
bool accountPrivateVerify(const uint256& uHash, const std::vector<unsigned char>& vucSig) const; // bool accountPrivateVerify(const uint256& uHash, const std::vector<unsigned char>& vucSig) const;
// Encrypt a message. // Encrypt a message.
std::vector<unsigned char> accountPrivateEncrypt(const NewcoinAddress& naPublicTo, const std::vector<unsigned char>& vucPlainText) const; std::vector<unsigned char> accountPrivateEncrypt(const NewcoinAddress& naPublicTo, const std::vector<unsigned char>& vucPlainText) const;
@@ -118,14 +124,16 @@ public:
// Decrypt a message. // Decrypt a message.
std::vector<unsigned char> accountPrivateDecrypt(const NewcoinAddress& naPublicFrom, const std::vector<unsigned char>& vucCipherText) const; std::vector<unsigned char> accountPrivateDecrypt(const NewcoinAddress& naPublicFrom, const std::vector<unsigned char>& vucCipherText) const;
static NewcoinAddress createAccountPrivate(const NewcoinAddress& naGenerator, const NewcoinAddress& naSeed, int iSeq);
static NewcoinAddress createAccountPrivate(const std::vector<unsigned char>& vPrivate) static NewcoinAddress createAccountPrivate(const std::vector<unsigned char>& vPrivate)
{ {
NewcoinAddress naNew; NewcoinAddress naNew;
naNew.setAccountPrivate(vPrivate); naNew.setAccountPrivate(vPrivate);
return naNew; return naNew;
} }
static std::string createHumanAccountPrivate(const std::vector<unsigned char>& vPrivate) { static std::string createHumanAccountPrivate(const std::vector<unsigned char>& vPrivate) {
return createAccountPrivate(vPrivate).humanAccountPrivate(); return createAccountPrivate(vPrivate).humanAccountPrivate();
@@ -144,6 +152,9 @@ public:
void setFamilyGenerator(const std::vector<unsigned char>& vPublic); void setFamilyGenerator(const std::vector<unsigned char>& vPublic);
void setFamilyGenerator(const NewcoinAddress& seed); void setFamilyGenerator(const NewcoinAddress& seed);
// Create generator for making public deterministic keys.
static NewcoinAddress createGeneratorPublic(const NewcoinAddress& naSeed);
// //
// Family Seeds // Family Seeds
// Clients must disallow reconizable entries from being seeds. // Clients must disallow reconizable entries from being seeds.

View File

@@ -179,7 +179,7 @@ public:
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED); EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
fSet = true; fSet = true;
} }
#if 0
bool SetPrivKey(const CPrivKey& vchPrivKey) bool SetPrivKey(const CPrivKey& vchPrivKey)
{ // DEPRECATED { // DEPRECATED
const unsigned char* pbegin = &vchPrivKey[0]; const unsigned char* pbegin = &vchPrivKey[0];
@@ -189,7 +189,8 @@ public:
fSet = true; fSet = true;
return true; return true;
} }
#endif
#if 1
bool SetSecret(const CSecret& vchSecret) bool SetSecret(const CSecret& vchSecret)
{ // DEPRECATED { // DEPRECATED
EC_KEY_free(pkey); EC_KEY_free(pkey);
@@ -207,7 +208,7 @@ public:
fSet = true; fSet = true;
return true; return true;
} }
#endif
CSecret GetSecret() CSecret GetSecret()
{ // DEPRECATED { // DEPRECATED
CSecret vchRet; CSecret vchRet;
@@ -236,16 +237,23 @@ public:
BN_bn2bin(bn, privKey.begin() + (privKey.size() - BN_num_bytes(bn))); BN_bn2bin(bn, privKey.begin() + (privKey.size() - BN_num_bytes(bn)));
} }
void SetPrivateKeyU(const uint256& key) bool SetPrivateKeyU(const uint256& key, bool bThrow=false)
{ {
BIGNUM* bn = BN_bin2bn(key.begin(), key.size(), NULL); BIGNUM* bn = BN_bin2bn(key.begin(), key.size(), NULL);
if (!EC_KEY_set_private_key(pkey, bn)) bool bSuccess = !!EC_KEY_set_private_key(pkey, bn);
BN_clear_free(bn);
if (bSuccess)
{
fSet = true;
}
else if (bThrow)
{ {
BN_clear_free(bn);
throw key_error("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed"); throw key_error("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
} }
fSet = true;
BN_clear_free(bn); return bSuccess;
} }
void SetPubSeq(const NewcoinAddress& masterKey, int keyNum) void SetPubSeq(const NewcoinAddress& masterKey, int keyNum)