diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp index f3b92ff3bf..6cd072db80 100644 --- a/src/NewcoinAddress.cpp +++ b/src/NewcoinAddress.cpp @@ -36,7 +36,7 @@ bool NewcoinAddress::isValid() const break; case VER_ACCOUNT_PRIVATE: - bValid = key.SetPrivKey(getAccountPrivate()); + bValid = key.SetPrivateKeyU(getAccountPrivate()); break; default: @@ -58,6 +58,17 @@ void NewcoinAddress::clear() // 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& NewcoinAddress::getNodePublic() const { switch (nVersion) { @@ -125,6 +136,19 @@ bool NewcoinAddress::verifyNodePublic(const uint256& hash, const std::string& st // 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& NewcoinAddress::getNodePrivateData() const { switch (nVersion) { @@ -251,6 +275,16 @@ void NewcoinAddress::setAccountID(const uint160& hash160) // AccountPublic // +NewcoinAddress NewcoinAddress::createAccountPublic(const NewcoinAddress& naGenerator, int iSeq) +{ + CKey ckPub(naGenerator, iSeq); + NewcoinAddress naNew; + + naNew.setAccountPublic(ckPub.GetPubKey()); + + return naNew; +} + const std::vector& NewcoinAddress::getAccountPublic() const { switch (nVersion) { @@ -335,14 +369,23 @@ NewcoinAddress NewcoinAddress::createAccountID(const uint160& uiAccountID) // AccountPrivate // -const std::vector& 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) { case VER_NONE: throw std::runtime_error("unset source"); case VER_ACCOUNT_PRIVATE: - return vchData; + return uint256(vchData); default: 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) { - 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& vucSig) const @@ -390,7 +436,7 @@ bool NewcoinAddress::accountPrivateSign(const uint256& uHash, std::vector& vucSig) const { CKey ckPrivate; bool bVerified; - if (!ckPrivate.SetPrivKey(getAccountPrivate())) + if (!ckPrivate.SetPrivateKeyU(getAccountPrivate())) { // Bad private key. std::cerr << "accountPrivateVerify: Bad private key." << std::endl; @@ -424,6 +471,7 @@ bool NewcoinAddress::accountPrivateVerify(const uint256& uHash, const std::vecto return bVerified; } +#endif std::vector NewcoinAddress::accountPrivateEncrypt(const NewcoinAddress& naPublicTo, const std::vector& vucPlainText) const { @@ -436,7 +484,7 @@ std::vector NewcoinAddress::accountPrivateEncrypt(const NewcoinAd // Bad public key. std::cerr << "accountPrivateEncrypt: Bad public key." << std::endl; } - else if (!ckPrivate.SetPrivKey(getAccountPrivate())) + else if (!ckPrivate.SetPrivateKeyU(getAccountPrivate())) { // Bad private key. std::cerr << "accountPrivateEncrypt: Bad private key." << std::endl; @@ -466,7 +514,7 @@ std::vector NewcoinAddress::accountPrivateDecrypt(const NewcoinAd // Bad public key. std::cerr << "accountPrivateDecrypt: Bad public key." << std::endl; } - else if (!ckPrivate.SetPrivKey(getAccountPrivate())) + else if (!ckPrivate.SetPrivateKeyU(getAccountPrivate())) { // Bad private key. std::cerr << "accountPrivateDecrypt: Bad private key." << std::endl; @@ -552,6 +600,16 @@ void NewcoinAddress::setFamilyGenerator(const NewcoinAddress& seed) seed.seedInfo(this, 0); } +NewcoinAddress NewcoinAddress::createGeneratorPublic(const NewcoinAddress& naSeed) +{ + CKey ckSeed(naSeed.getFamilySeed()); + NewcoinAddress naNew; + + naNew.setFamilyGenerator(ckSeed.GetPubKey()); + + return naNew; +} + // // Family Seed // @@ -702,7 +760,55 @@ BOOST_AUTO_TEST_SUITE(newcoin_address) 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 vucTextSrc = strCopy("Hello, nurse!"); + uint256 uHash = Serializer::getSHA512Half(vucTextSrc); + std::vector 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 vucTextCipher + = naAccountPrivate0.accountPrivateEncrypt(naAccountPublic1, vucTextSrc); + std::vector vucTextRecovered + = naAccountPrivate1.accountPrivateDecrypt(naAccountPublic0, vucTextCipher); + + BOOST_CHECK_MESSAGE(vucTextSrc == vucTextRecovered, "Encrypt-decrypt failed."); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/NewcoinAddress.h b/src/NewcoinAddress.h index 3418669152..4125fcf272 100644 --- a/src/NewcoinAddress.h +++ b/src/NewcoinAddress.h @@ -42,6 +42,8 @@ public: bool verifyNodePublic(const uint256& hash, const std::vector& vchSig) const; bool verifyNodePublic(const uint256& hash, const std::string& strSig) const; + static NewcoinAddress createNodePublic(NewcoinAddress& naSeed); + // // Node Private // @@ -55,6 +57,8 @@ public: void setNodePrivate(uint256 hash256); void signNodePrivate(const uint256& hash, std::vector& vchSig) const; + static NewcoinAddress createNodePrivate(NewcoinAddress& naSeed); + // // Accounts IDs // @@ -67,9 +71,8 @@ public: static NewcoinAddress createAccountID(const uint160& uiAccountID); - static std::string createHumanAccountID(const std::vector& vPrivate) { - return createAccountPrivate(vPrivate).humanAccountID(); - } + static std::string createHumanAccountID(const std::vector& vPrivate) + { return createAccountPrivate(vPrivate).humanAccountID(); } // // Accounts Public @@ -85,22 +88,25 @@ public: bool accountPublicVerify(const uint256& uHash, const std::vector& vucSig) const; static NewcoinAddress createAccountPublic(const std::vector& vPublic) - { - NewcoinAddress naNew; + { + NewcoinAddress naNew; - naNew.setAccountPublic(vPublic); + naNew.setAccountPublic(vPublic); - return naNew; - } + return naNew; + } static std::string createHumanAccountPublic(const std::vector& vPublic) { return createAccountPublic(vPublic).humanAccountPublic(); } + // Create a deterministic public key from a public generator. + static NewcoinAddress createAccountPublic(const NewcoinAddress& naGenerator, int iSeq); + // // Accounts Private // - const std::vector& getAccountPrivate() const; + uint256 getAccountPrivate() const; std::string humanAccountPrivate() const; @@ -110,7 +116,7 @@ public: void setAccountPrivate(const NewcoinAddress& generator, const NewcoinAddress& seed, int seq); bool accountPrivateSign(const uint256& uHash, std::vector& vucSig) const; - bool accountPrivateVerify(const uint256& uHash, const std::vector& vucSig) const; + // bool accountPrivateVerify(const uint256& uHash, const std::vector& vucSig) const; // Encrypt a message. std::vector accountPrivateEncrypt(const NewcoinAddress& naPublicTo, const std::vector& vucPlainText) const; @@ -118,14 +124,16 @@ public: // Decrypt a message. std::vector accountPrivateDecrypt(const NewcoinAddress& naPublicFrom, const std::vector& vucCipherText) const; + static NewcoinAddress createAccountPrivate(const NewcoinAddress& naGenerator, const NewcoinAddress& naSeed, int iSeq); + static NewcoinAddress createAccountPrivate(const std::vector& vPrivate) - { - NewcoinAddress naNew; + { + NewcoinAddress naNew; - naNew.setAccountPrivate(vPrivate); + naNew.setAccountPrivate(vPrivate); - return naNew; - } + return naNew; + } static std::string createHumanAccountPrivate(const std::vector& vPrivate) { return createAccountPrivate(vPrivate).humanAccountPrivate(); @@ -144,6 +152,9 @@ public: void setFamilyGenerator(const std::vector& vPublic); void setFamilyGenerator(const NewcoinAddress& seed); + // Create generator for making public deterministic keys. + static NewcoinAddress createGeneratorPublic(const NewcoinAddress& naSeed); + // // Family Seeds // Clients must disallow reconizable entries from being seeds. diff --git a/src/key.h b/src/key.h index 213bae4ddc..0a82b2759a 100644 --- a/src/key.h +++ b/src/key.h @@ -179,7 +179,7 @@ public: EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED); fSet = true; } - +#if 0 bool SetPrivKey(const CPrivKey& vchPrivKey) { // DEPRECATED const unsigned char* pbegin = &vchPrivKey[0]; @@ -189,7 +189,8 @@ public: fSet = true; return true; } - +#endif +#if 1 bool SetSecret(const CSecret& vchSecret) { // DEPRECATED EC_KEY_free(pkey); @@ -207,7 +208,7 @@ public: fSet = true; return true; } - +#endif CSecret GetSecret() { // DEPRECATED CSecret vchRet; @@ -236,16 +237,23 @@ public: 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); - if (!EC_KEY_set_private_key(pkey, bn)) + BIGNUM* bn = BN_bin2bn(key.begin(), key.size(), NULL); + 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"); } - fSet = true; - BN_clear_free(bn); + + return bSuccess; } void SetPubSeq(const NewcoinAddress& masterKey, int keyNum)