1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
10 extern bool fWalletUnlockMintOnly;
12 bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
15 if (!GetKey(address, key))
17 vchPubKeyOut = key.GetPubKey();
21 bool CKeyStore::GetSecret(const CKeyID &address, CSecret& vchSecret, bool &fCompressed) const
24 if (!GetKey(address, key))
26 vchSecret = key.GetSecret(fCompressed);
30 bool CBasicKeyStore::AddKey(const CKey& key)
32 bool fCompressed = false;
33 auto secret = key.GetSecret(fCompressed);
36 mapKeys[key.GetPubKey().GetID()] = { secret, fCompressed };
41 bool CBasicKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret& vchSecretH)
45 mapMalleableKeys[CMalleableKeyView(keyView)] = vchSecretH;
50 bool CBasicKeyStore::GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const
54 MalleableKeyMap::const_iterator mi = mapMalleableKeys.find(keyView);
55 if (mi != mapMalleableKeys.end())
57 mKey = mi->first.GetMalleableKey(mi->second);
64 bool CBasicKeyStore::HaveKey(const CKeyID &address) const
69 result = (mapKeys.count(address) > 0);
74 void CBasicKeyStore::GetKeys(std::set<CKeyID> &setAddress) const
79 KeyMap::const_iterator mi;
80 for (mi = mapKeys.begin(); mi != mapKeys.end(); ++mi) setAddress.insert((*mi).first);
84 bool CBasicKeyStore::GetKey(const CKeyID &address, CKey &keyOut) const
88 KeyMap::const_iterator mi = mapKeys.find(address);
89 if (mi != mapKeys.end())
91 keyOut.SetSecret((*mi).second.first, (*mi).second.second);
98 bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
100 if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
101 return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE);
105 mapScripts[CScriptID(redeemScript)] = redeemScript;
110 bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const
115 result = (mapScripts.count(hash) > 0);
121 bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const
125 auto mi = mapScripts.find(hash);
126 if (mi != mapScripts.end())
128 redeemScriptOut = (*mi).second;
135 bool CBasicKeyStore::AddWatchOnly(const CScript &dest)
139 CTxDestination address;
140 if (ExtractDestination(dest, address)) {
142 CBitcoinAddress(address).GetKeyID(keyID);
147 setWatchOnly.insert(dest);
152 bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest)
155 setWatchOnly.erase(dest);
159 bool CBasicKeyStore::HaveWatchOnly(const CScript &dest) const
162 return setWatchOnly.count(dest) > 0;
165 bool CBasicKeyStore::HaveWatchOnly() const
168 return (!setWatchOnly.empty());
171 bool CBasicKeyStore::CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const
175 for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
177 if (mi->first.CheckKeyVariant(R, pubKeyVariant))
184 bool CBasicKeyStore::CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R, CMalleableKeyView &view) const
188 for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
190 if (mi->first.CheckKeyVariant(R, pubKeyVariant))
200 bool CBasicKeyStore::CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const
204 for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
206 if (mi->first.CheckKeyVariant(R, pubKeyVariant))
208 CMalleableKey mKey = mi->first.GetMalleableKey(mi->second);
209 return mKey.CheckKeyVariant(R, pubKeyVariant, privKey);
216 void CBasicKeyStore::ListMalleableViews(std::list<CMalleableKeyView> &malleableViewList) const
218 malleableViewList.clear();
221 for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
222 malleableViewList.push_back(CMalleableKeyView(mi->first));
226 bool CBasicKeyStore::GetMalleableView(const CMalleablePubKey &mpk, CMalleableKeyView &view)
228 const CKeyID &mpkID = mpk.GetID();
231 for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
232 if (mi->first.GetID() == mpkID)
234 view = CMalleableKeyView(mi->first);
242 bool CCryptoKeyStore::SetCrypted()
248 if (!mapKeys.empty())
255 CCryptoKeyStore::CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false)
259 bool CCryptoKeyStore::IsCrypted() const
264 bool CCryptoKeyStore::IsLocked() const
271 result = vMasterKey.empty();
276 bool CCryptoKeyStore::Lock()
284 fWalletUnlockMintOnly = false;
287 NotifyStatusChanged(this);
291 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
298 bool keyPass = false;
299 bool keyFail = false;
301 // Check regular key pairs
303 auto mi = mapCryptedKeys.begin();
304 for (; mi != mapCryptedKeys.end(); ++mi)
306 const auto &vchPubKey = (*mi).second.first;
307 const auto &vchCryptedSecret = (*mi).second.second;
309 if (!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
314 if (vchSecret.size() != 32)
320 if (fDecryptionThoroughlyChecked)
325 // Check malleable key pairs
327 if (keyPass && !keyFail)
329 auto mi = mapCryptedMalleableKeys.begin();
330 for(; mi != mapCryptedMalleableKeys.end(); ++mi)
332 const auto &H = mi->first.GetMalleablePubKey().GetH();
334 if (!DecryptSecret(vMasterKeyIn, mi->second, H.GetHash(), vchSecretH))
339 if (vchSecretH.size() != 32)
345 if (fDecryptionThoroughlyChecked)
351 if (keyPass && keyFail)
353 printf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
356 if (keyFail || !keyPass)
358 vMasterKey = vMasterKeyIn;
359 fDecryptionThoroughlyChecked = true;
361 NotifyStatusChanged(this);
366 bool CCryptoKeyStore::AddKey(const CKey& key)
372 script.SetDestination(key.GetPubKey().GetID());
374 if (HaveWatchOnly(script))
378 return CBasicKeyStore::AddKey(key);
383 std::vector<unsigned char> vchCryptedSecret;
384 auto vchPubKey = key.GetPubKey();
386 if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
389 if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
395 bool CCryptoKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret &vchSecretH)
400 return CBasicKeyStore::AddMalleableKey(keyView, vchSecretH);
406 keyH.SetSecret(vchSecretH, true);
408 std::vector<unsigned char> vchCryptedSecretH;
409 if (!EncryptSecret(vMasterKey, vchSecretH, keyH.GetPubKey().GetHash(), vchCryptedSecretH))
412 if (!AddCryptedMalleableKey(keyView, vchCryptedSecretH))
418 bool CCryptoKeyStore::HaveKey(const CKeyID &address) const
423 return CBasicKeyStore::HaveKey(address);
424 return mapCryptedKeys.count(address) > 0;
428 bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
435 mapCryptedKeys[vchPubKey.GetID()] = { vchPubKey, vchCryptedSecret };
440 bool CCryptoKeyStore::AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char> &vchCryptedSecretH)
447 mapCryptedMalleableKeys[CMalleableKeyView(keyView)] = vchCryptedSecretH;
452 bool CCryptoKeyStore::CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const
457 return CBasicKeyStore::CreatePrivKey(pubKeyVariant, R, privKey);
459 for (auto mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
461 if (mi->first.CheckKeyVariant(R, pubKeyVariant))
463 const CPubKey H = mi->first.GetMalleablePubKey().GetH();
466 if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
468 if (vchSecretH.size() != 32)
471 CMalleableKey mKey = mi->first.GetMalleableKey(vchSecretH);
472 return mKey.CheckKeyVariant(R, pubKeyVariant, privKey);;
480 bool CCryptoKeyStore::GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const
485 return CBasicKeyStore::GetMalleableKey(keyView, mKey);
486 auto mi = mapCryptedMalleableKeys.find(keyView);
487 if (mi != mapCryptedMalleableKeys.end())
489 const CPubKey H = keyView.GetMalleablePubKey().GetH();
492 if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
495 if (vchSecretH.size() != 32)
497 mKey = mi->first.GetMalleableKey(vchSecretH);
505 bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
510 return CBasicKeyStore::GetKey(address, keyOut);
512 auto mi = mapCryptedKeys.find(address);
513 if (mi != mapCryptedKeys.end())
515 const CPubKey &vchPubKey = (*mi).second.first;
516 const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
518 if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
520 if (vchSecret.size() != 32)
522 keyOut.SetSecret(vchSecret);
523 keyOut.SetCompressedPubKey(vchPubKey.IsCompressed());
530 bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
535 return CKeyStore::GetPubKey(address, vchPubKeyOut);
537 auto mi = mapCryptedKeys.find(address);
538 if (mi != mapCryptedKeys.end())
540 vchPubKeyOut = (*mi).second.first;
547 void CCryptoKeyStore::GetKeys(std::set<CKeyID> &setAddress) const
551 CBasicKeyStore::GetKeys(setAddress);
555 CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
556 while (mi != mapCryptedKeys.end())
558 setAddress.insert((*mi).first);
563 bool CCryptoKeyStore::CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const
568 return CBasicKeyStore::CheckOwnership(pubKeyVariant, R);
569 for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
571 if (mi->first.CheckKeyVariant(R, pubKeyVariant))
578 bool CCryptoKeyStore::CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R, CMalleableKeyView &view) const
583 return CBasicKeyStore::CheckOwnership(pubKeyVariant, R, view);
584 for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
586 if (mi->first.CheckKeyVariant(R, pubKeyVariant))
596 bool CCryptoKeyStore::CheckOwnership(const CMalleablePubKey &mpk)
598 CMalleableKeyView view;
599 return GetMalleableView(mpk, view);
602 void CCryptoKeyStore::ListMalleableViews(std::list<CMalleableKeyView> &malleableViewList) const
604 malleableViewList.clear();
608 return CBasicKeyStore::ListMalleableViews(malleableViewList);
609 for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
610 malleableViewList.push_back(CMalleableKeyView(mi->first));
614 bool CCryptoKeyStore::GetMalleableView(const CMalleablePubKey &mpk, CMalleableKeyView &view)
616 const CKeyID &mpkID = mpk.GetID();
620 return CBasicKeyStore::GetMalleableView(mpk, view);
621 for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
622 if (mi->first.GetID() == mpkID)
624 view = CMalleableKeyView(mi->first);
631 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
635 if (!mapCryptedKeys.empty() || IsCrypted())
639 for(auto& mKey : mapKeys)
642 if (!key.SetSecret(mKey.second.first, mKey.second.second))
644 const auto vchPubKey = key.GetPubKey();
645 std::vector<unsigned char> vchCryptedSecret;
647 if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
649 if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
654 for(auto& mKey : mapMalleableKeys)
656 const auto vchPubKeyH = mKey.first.GetMalleablePubKey().GetH();
657 std::vector<unsigned char> vchCryptedSecretH;
658 if (!EncryptSecret(vMasterKeyIn, mKey.second, vchPubKeyH.GetHash(), vchCryptedSecretH))
660 if (!AddCryptedMalleableKey(mKey.first, vchCryptedSecretH))
663 mapMalleableKeys.clear();
668 bool CCryptoKeyStore::DecryptKeys(const CKeyingMaterial& vMasterKeyIn)
675 auto mi = mapCryptedKeys.begin();
676 for (; mi != mapCryptedKeys.end(); ++mi)
678 const auto &vchPubKey = (*mi).second.first;
679 const auto &vchCryptedSecret = (*mi).second.second;
681 if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
683 if (vchSecret.size() != 32)
686 key.SetSecret(vchSecret);
687 key.SetCompressedPubKey(vchPubKey.IsCompressed());
688 if (!CBasicKeyStore::AddKey(key))
692 mapCryptedKeys.clear();
694 auto mi2 = mapCryptedMalleableKeys.begin();
695 for(; mi2 != mapCryptedMalleableKeys.end(); ++mi2)
697 const auto vchPubKeyH = mi2->first.GetMalleablePubKey().GetH();
700 if(!DecryptSecret(vMasterKeyIn, mi2->second, vchPubKeyH.GetHash(), vchSecretH))
702 if (vchSecretH.size() != 32)
705 if (!CBasicKeyStore::AddMalleableKey(mi2->first, vchSecretH))
708 mapCryptedMalleableKeys.clear();