Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge #11272: CKeystore/CCrypter: move relevant implementation out of… #3318

Merged
merged 2 commits into from Feb 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/keystore.cpp
Expand Up @@ -36,6 +36,33 @@ bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
return true;
}

bool CBasicKeyStore::HaveKey(const CKeyID &address) const
{
LOCK(cs_KeyStore);
return mapKeys.count(address) > 0;
}

std::set<CKeyID> CBasicKeyStore::GetKeys() const
{
LOCK(cs_KeyStore);
std::set<CKeyID> set_address;
for (const auto& mi : mapKeys) {
set_address.insert(mi.first);
}
return set_address;
}

bool CBasicKeyStore::GetKey(const CKeyID &address, CKey &keyOut) const
{
LOCK(cs_KeyStore);
KeyMap::const_iterator mi = mapKeys.find(address);
if (mi != mapKeys.end()) {
keyOut = mi->second;
return true;
}
return false;
}

bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
{
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
Expand Down
34 changes: 3 additions & 31 deletions src/keystore.h
Expand Up @@ -65,37 +65,9 @@ class CBasicKeyStore : public CKeyStore
public:
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
bool HaveKey(const CKeyID &address) const override
{
bool result;
{
LOCK(cs_KeyStore);
result = (mapKeys.count(address) > 0);
}
return result;
}
std::set<CKeyID> GetKeys() const override
{
LOCK(cs_KeyStore);
std::set<CKeyID> set_address;
for (const auto& mi : mapKeys) {
set_address.insert(mi.first);
}
return set_address;
}
bool GetKey(const CKeyID &address, CKey &keyOut) const override
{
{
LOCK(cs_KeyStore);
KeyMap::const_iterator mi = mapKeys.find(address);
if (mi != mapKeys.end())
{
keyOut = mi->second;
return true;
}
}
return false;
}
bool HaveKey(const CKeyID &address) const override;
std::set<CKeyID> GetKeys() const override;
bool GetKey(const CKeyID &address, CKey &keyOut) const override;
bool AddCScript(const CScript& redeemScript) override;
bool HaveCScript(const CScriptID &hash) const override;
bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override;
Expand Down
159 changes: 103 additions & 56 deletions src/wallet/crypter.cpp
Expand Up @@ -198,6 +198,35 @@ bool CCryptoKeyStore::SetCrypted()
return true;
}

// This function should be used in a different combinations to determine
// if CCryptoKeyStore is fully locked so that no operations requiring access
// to private keys are possible:
// IsLocked(true)
// or if CCryptoKeyStore's private keys are available for mixing only:
// !IsLocked(true) && IsLocked()
// or if they are available for everything:
// !IsLocked()
bool CCryptoKeyStore::IsLocked(bool fForMixing) const
{
if (!IsCrypted())
return false;
bool result;
{
LOCK(cs_KeyStore);
result = vMasterKey.empty();
}
// fForMixing fOnlyMixingAllowed return
// ---------------------------------------
// true true result
// true false result
// false true true
// false false result

if(!fForMixing && fOnlyMixingAllowed) return true;

return result;
}

bool CCryptoKeyStore::Lock(bool fAllowMixing)
{
if (!SetCrypted())
Expand Down Expand Up @@ -269,95 +298,113 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn, bool fForMixin

bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
{
{
LOCK(cs_KeyStore);
if (!IsCrypted())
return CBasicKeyStore::AddKeyPubKey(key, pubkey);
LOCK(cs_KeyStore);
if (!IsCrypted()) {
return CBasicKeyStore::AddKeyPubKey(key, pubkey);
}

if (IsLocked(true))
return false;
if (IsLocked(true)) {
return false;
}

std::vector<unsigned char> vchCryptedSecret;
CKeyingMaterial vchSecret(key.begin(), key.end());
if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret))
return false;
std::vector<unsigned char> vchCryptedSecret;
CKeyingMaterial vchSecret(key.begin(), key.end());
if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret)) {
return false;
}

if (!AddCryptedKey(pubkey, vchCryptedSecret))
return false;
if (!AddCryptedKey(pubkey, vchCryptedSecret)) {
return false;
}
return true;
}


bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{
{
LOCK(cs_KeyStore);
if (!SetCrypted())
return false;

mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
LOCK(cs_KeyStore);
if (!SetCrypted()) {
return false;
}

mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
return true;
}

bool CCryptoKeyStore::HaveKey(const CKeyID &address) const
{
LOCK(cs_KeyStore);
if (!IsCrypted()) {
return CBasicKeyStore::HaveKey(address);
}
return mapCryptedKeys.count(address) > 0;
}

bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
{
{
LOCK(cs_KeyStore);
if (!IsCrypted())
return CBasicKeyStore::GetKey(address, keyOut);
LOCK(cs_KeyStore);
if (!IsCrypted()) {
return CBasicKeyStore::GetKey(address, keyOut);
}

CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
if (mi != mapCryptedKeys.end())
{
const CPubKey &vchPubKey = (*mi).second.first;
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
return DecryptKey(vMasterKey, vchCryptedSecret, vchPubKey, keyOut);
}
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
if (mi != mapCryptedKeys.end())
{
const CPubKey &vchPubKey = (*mi).second.first;
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
return DecryptKey(vMasterKey, vchCryptedSecret, vchPubKey, keyOut);
}
return false;
}

bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
{
LOCK(cs_KeyStore);
if (!IsCrypted())
return CBasicKeyStore::GetPubKey(address, vchPubKeyOut);

CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
if (mi != mapCryptedKeys.end())
{
LOCK(cs_KeyStore);
if (!IsCrypted())
return CBasicKeyStore::GetPubKey(address, vchPubKeyOut);
vchPubKeyOut = (*mi).second.first;
return true;
}
// Check for watch-only pubkeys
return CBasicKeyStore::GetPubKey(address, vchPubKeyOut);
}

CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
if (mi != mapCryptedKeys.end())
{
vchPubKeyOut = (*mi).second.first;
return true;
}
// Check for watch-only pubkeys
return CBasicKeyStore::GetPubKey(address, vchPubKeyOut);
std::set<CKeyID> CCryptoKeyStore::GetKeys() const
{
LOCK(cs_KeyStore);
if (!IsCrypted()) {
return CBasicKeyStore::GetKeys();
}
std::set<CKeyID> set_address;
for (const auto& mi : mapCryptedKeys) {
set_address.insert(mi.first);
}
return set_address;
}

bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
{
LOCK(cs_KeyStore);
if (!mapCryptedKeys.empty() || IsCrypted())
return false;

fUseCrypto = true;
for (KeyMap::value_type& mKey : mapKeys)
{
LOCK(cs_KeyStore);
if (!mapCryptedKeys.empty() || IsCrypted())
const CKey &key = mKey.second;
CPubKey vchPubKey = key.GetPubKey();
CKeyingMaterial vchSecret(key.begin(), key.end());
std::vector<unsigned char> vchCryptedSecret;
if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
return false;
if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
return false;

fUseCrypto = true;
for (KeyMap::value_type& mKey : mapKeys)
{
const CKey &key = mKey.second;
CPubKey vchPubKey = key.GetPubKey();
CKeyingMaterial vchSecret(key.begin(), key.end());
std::vector<unsigned char> vchCryptedSecret;
if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
return false;
if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
return false;
}
mapKeys.clear();
}
mapKeys.clear();
return true;
}

Expand Down
63 changes: 5 additions & 58 deletions src/wallet/crypter.h
Expand Up @@ -152,69 +152,16 @@ class CCryptoKeyStore : public CBasicKeyStore
{
}

bool IsCrypted() const
{
return fUseCrypto;
}

// This function should be used in a different combinations to determine
// if CCryptoKeyStore is fully locked so that no operations requiring access
// to private keys are possible:
// IsLocked(true)
// or if CCryptoKeyStore's private keys are available for mixing only:
// !IsLocked(true) && IsLocked()
// or if they are available for everything:
// !IsLocked()
bool IsLocked(bool fForMixing = false) const
{
if (!IsCrypted())
return false;
bool result;
{
LOCK(cs_KeyStore);
result = vMasterKey.empty();
}
// fForMixing fOnlyMixingAllowed return
// ---------------------------------------
// true true result
// true false result
// false true true
// false false result

if(!fForMixing && fOnlyMixingAllowed) return true;

return result;
}

bool Lock(bool fAllowMixing = false);
bool IsCrypted() const { return fUseCrypto; }
bool IsLocked(bool fForMixing = false) const;
bool Lock(bool fForMixing = false);

virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
bool HaveKey(const CKeyID &address) const override
{
{
LOCK(cs_KeyStore);
if (!IsCrypted()) {
return CBasicKeyStore::HaveKey(address);
}
return mapCryptedKeys.count(address) > 0;
}
return false;
}
bool HaveKey(const CKeyID &address) const override;
bool GetKey(const CKeyID &address, CKey& keyOut) const override;
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
std::set<CKeyID> GetKeys() const override
{
LOCK(cs_KeyStore);
if (!IsCrypted()) {
return CBasicKeyStore::GetKeys();
}
std::set<CKeyID> set_address;
for (const auto& mi : mapCryptedKeys) {
set_address.insert(mi.first);
}
return set_address;
}
std::set<CKeyID> GetKeys() const override;

virtual bool GetHDChain(CHDChain& hdChainRet) const override;

Expand Down