void RunDeriveTest(std::vector<DeriveTestData> &vData) { int rv; CBitcoinExtKey extKey58; CExtKey evkeyM; CExtPubKey epkeyM; for (uint32_t k = 0; k < vData.size(); ++k) { DeriveTestData &dt = vData[k]; if (dt.nDerives == 0) { // - set master BOOST_CHECK(0 == (rv = extKey58.Set58(dt.vKey58.c_str()))); BOOST_CHECK(0 == (rv += abs(strcmp(extKey58.ToString().c_str(), dt.vKey58.c_str())))); evkeyM = extKey58.GetKey(); BOOST_CHECK(0 == (rv += abs(strcmp(CBitcoinExtKey(evkeyM).ToString().c_str(), dt.vKey58.c_str())))); epkeyM = evkeyM.Neutered(); BOOST_CHECK(0 == (rv += abs(strcmp(CBitcoinExtPubKey(epkeyM).ToString().c_str(), dt.pKey58.c_str())))); BOOST_CHECK(CBitcoinExtPubKey(epkeyM).ToString().c_str()); if (rv != 0) { BOOST_TEST_MESSAGE("Set master failed, aborting test."); break; } continue; }; CExtKey evkey[2], evkeyOut; CExtPubKey epkeyOut; evkey[0] = evkeyM; rv = 0; for (uint32_t d = 0; d < dt.nDerives; ++d) { rv += evkey[d % 2].Derive(evkey[(d+1) % 2], 1); } BOOST_CHECK(dt.nDerives == (uint32_t)rv); evkeyOut = evkey[dt.nDerives % 2]; BOOST_CHECK(CBitcoinExtKey(evkeyOut).ToString().c_str()); BOOST_TEST_MESSAGE("evkeyOut.nDepth " << (int)evkeyOut.nDepth); BOOST_CHECK(evkeyOut.nDepth == dt.nDerives % 256); BOOST_CHECK(0 == strcmp(CBitcoinExtKey(evkeyOut).ToString().c_str(), dt.vKey58.c_str())); epkeyOut = evkeyOut.Neutered(); BOOST_CHECK(0 == strcmp(CBitcoinExtPubKey(epkeyOut).ToString().c_str(), dt.pKey58.c_str())); }; }
void TestMnemonic(int nLanguage, const Array &va) { std::string sError; std::string sEntropy = va[0].get_str(); std::string sWords = va[1].get_str(); std::string sSeed; std::string sPassphrase; if (va.size() > 3) { sPassphrase = va[2].get_str(); sSeed = va[3].get_str(); } else { sPassphrase = "TREZOR"; sSeed = va[2].get_str(); }; //BOOST_MESSAGE("sEntropy " << sEntropy); //BOOST_MESSAGE("sWords " << sWords); //BOOST_MESSAGE("sSeed " << sSeed); //BOOST_MESSAGE("sPassphrase " << sPassphrase); std::vector<uint8_t> vEntropy = ParseHex(sEntropy); std::vector<uint8_t> vEntropyTest; std::string sWordsTest; BOOST_CHECK_MESSAGE(0 == MnemonicEncode(nLanguage, vEntropy, sWordsTest, sError), "MnemonicEncode: " << sError); BOOST_CHECK(sWords == sWordsTest); BOOST_CHECK_MESSAGE(0 == MnemonicDecode(-1, sWords, vEntropyTest, sError), "MnemonicDecode: " << sError); BOOST_CHECK(vEntropy == vEntropyTest); std::vector<uint8_t> vSeed = ParseHex(sSeed); std::vector<uint8_t> vSeedTest; BOOST_CHECK(0 == MnemonicToSeed(sWords, sPassphrase, vSeedTest)); BOOST_CHECK(vSeed == vSeedTest); //BOOST_MESSAGE("vSeedTest " << HexStr(vSeedTest)); if (va.size() > 4) { CExtKey58 eKey58; std::string sExtKey = va[4].get_str(); CExtKey ekTest; ekTest.SetMaster(&vSeed[0], vSeed.size()); eKey58.SetKey(ekTest, CChainParams::EXT_SECRET_KEY_BTC); BOOST_CHECK(eKey58.ToString() == sExtKey); //BOOST_MESSAGE("sExtKey " << sExtKey); //BOOST_MESSAGE("eKey58 " << eKey58.ToString()); }; };
CExtKey DecodeExtKey(const std::string& str) { CExtKey key; std::vector<unsigned char> data; if (DecodeBase58Check(str, data)) { const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY); if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) { key.Decode(data.data() + prefix.size()); } } return key; }
bool CHDKeyStore::DeriveKey(const CHDPubKey hdPubKey, CKey& keyOut) const { //this methode required no locking std::string chainPath = hdPubKey.chainPath; std::vector<std::string> pathFragments; boost::split(pathFragments, chainPath, boost::is_any_of("/")); CExtKey extKey; CExtKey parentKey; BOOST_FOREACH(std::string fragment, pathFragments) { bool harden = false; if (*fragment.rbegin() == '\'') { harden = true; fragment = fragment.substr(0,fragment.size()-1); } if (fragment == "m") { CExtKey bip32MasterKey; CKeyingMaterial masterSeed; // get master seed if (!GetMasterSeed(hdPubKey.chainHash, masterSeed)) return false; if (masterSeed.size() == BIP32_EXTKEY_SIZE) { //if the seed size matches the BIP32_EXTKEY_SIZE, we assume its a encoded ext priv key bip32MasterKey.Decode(&masterSeed[0]); } else bip32MasterKey.SetMaster(&masterSeed[0], masterSeed.size()); parentKey = bip32MasterKey; } else if (fragment == "c") { return false; } else { CExtKey childKey; int32_t nIndex; if (!ParseInt32(fragment,&nIndex)) return false; parentKey.Derive(childKey, (harden ? 0x80000000 : 0)+nIndex); parentKey = childKey; } }
std::string EncodeExtKey(const CExtKey& key) { std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY); size_t size = data.size(); data.resize(size + BIP32_EXTKEY_SIZE); key.Encode(data.data() + size); std::string ret = EncodeBase58Check(data); memory_cleanse(data.data(), data.size()); return ret; }
bool CAccountHD::GetKey(const CKeyID& keyID, CKey& key) const { assert(!m_readOnly); assert(IsHD()); // Witness keys are a special case. // They are stored instead of generated on demand (so that they work in encrypted wallets) if (IsPoW2Witness()) { if (internalKeyStore.GetKey(keyID, key)) { // But skip it if it is an empty key... (Which can happen by design) // Technical: Witness keystore is filled with "public/empty" pairs as the public keys are created and then populated on demand with "public/witness" keys only when they are needed/generated (first use) if (key.IsValid()) return true; } } if (IsLocked()) return false; int64_t nKeyIndex = -1; CExtKey privKey; if (externalKeyStore.GetKey(keyID, nKeyIndex)) { primaryChainKeyPriv.Derive(privKey, nKeyIndex); if(privKey.Neuter().pubkey.GetID() != keyID) assert(0); key = privKey.key; return true; } if (internalKeyStore.GetKey(keyID, nKeyIndex)) { changeChainKeyPriv.Derive(privKey, nKeyIndex); if(privKey.Neuter().pubkey.GetID() != keyID) assert(0); key = privKey.key; return true; } return false; }
bool CAccountHD::GetKey(const CKeyID& keyID, CKey& key) const { if (IsLocked()) return false; int64_t nKeyIndex = -1; CExtKey privKey; if (externalKeyStore.GetKey(keyID, nKeyIndex)) { primaryChainKeyPriv.Derive(privKey, nKeyIndex); if (privKey.Neuter().pubkey.GetID() != keyID) assert(0); key = privKey.key; return true; } if (internalKeyStore.GetKey(keyID, nKeyIndex)) { changeChainKeyPriv.Derive(privKey, nKeyIndex); if (privKey.Neuter().pubkey.GetID() != keyID) assert(0); key = privKey.key; return true; } return false; }