// CMalleableKeyView
+CMalleableKeyView::CMalleableKeyView(const std::string &strMalleableKey)
+{
+ SetString(strMalleableKey);
+}
+
CMalleableKeyView::CMalleableKeyView(const CMalleableKey &b)
{
if (b.vchSecretL.size() != 32)
public:
CMalleableKeyView() { nVersion = 0; };
CMalleableKeyView(const CMalleableKey &b);
+ CMalleableKeyView(const std::string &strMalleableKey);
CMalleableKeyView(const CMalleableKeyView &b);
CMalleableKeyView& operator=(const CMalleableKey &b);
return true;
}
-bool CBasicKeyStore::AddMalleableKey(const CMalleableKey& mKey)
+bool CBasicKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret& vchSecretH)
{
{
LOCK(cs_KeyStore);
- mapMalleableKeys[CMalleableKeyView(mKey)] = mKey.GetSecretH();
+ mapMalleableKeys[CMalleableKeyView(keyView)] = vchSecretH;
}
return true;
}
return true;
}
+bool CCryptoKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret &vchSecretH)
+{
+ {
+ LOCK(cs_KeyStore);
+ if (!SetCrypted())
+ return CBasicKeyStore::AddMalleableKey(keyView, vchSecretH);
+
+ if (IsLocked())
+ return false;
+
+ CKey keyH;
+ keyH.SetSecret(vchSecretH, true);
+
+ std::vector<unsigned char> vchCryptedSecretH;
+ if (!EncryptSecret(vMasterKey, vchSecretH, keyH.GetPubKey().GetHash(), vchCryptedSecretH))
+ return false;
+
+ if (!AddCryptedMalleableKey(keyView, vchCryptedSecretH))
+ return false;
+ }
+ return true;
+}
bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{
return true;
}
+bool CCryptoKeyStore::AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char> &vchCryptedSecretH)
+{
+ {
+ LOCK(cs_KeyStore);
+ if (!SetCrypted())
+ return false;
+
+ mapCryptedMalleableKeys[CMalleableKeyView(keyView)] = vchCryptedSecretH;
+ }
+ return true;
+}
+
+bool CCryptoKeyStore::CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const
+{
+ {
+ LOCK(cs_KeyStore);
+ if (!IsCrypted())
+ return CBasicKeyStore::CreatePrivKey(pubKeyVariant, R, privKey);
+
+ for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
+ {
+ if (mi->first.CheckKeyVariant(R, pubKeyVariant))
+ {
+ const CPubKey H = mi->first.GetMalleablePubKey().GetH();
+
+ CSecret vchSecretH;
+ if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
+ return false;
+ if (vchSecretH.size() != 32)
+ return false;
+
+ CMalleableKey mKey = mi->first.GetMalleableKey(vchSecretH);
+ return mKey.CheckKeyVariant(R, pubKeyVariant, privKey);;
+ }
+ }
+
+ }
+ return true;
+}
+
+bool CCryptoKeyStore::GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const
+{
+ {
+ LOCK(cs_KeyStore);
+ if (!IsCrypted())
+ return CBasicKeyStore::GetMalleableKey(keyView, mKey);
+ CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.find(keyView);
+ if (mi != mapCryptedMalleableKeys.end())
+ {
+ const CPubKey H = keyView.GetMalleablePubKey().GetH();
+
+ CSecret vchSecretH;
+ if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
+ return false;
+
+ if (vchSecretH.size() != 32)
+ return false;
+ mKey = mi->first.GetMalleableKey(vchSecretH);
+
+ return true;
+ }
+ }
+ return false;
+}
+
bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
{
{
return false;
}
mapKeys.clear();
+
+ BOOST_FOREACH(MalleableKeyMap::value_type& mKey, mapMalleableKeys)
+ {
+ const CPubKey vchPubKeyH = mKey.first.GetMalleablePubKey().GetH();
+ std::vector<unsigned char> vchCryptedSecretH;
+ if (!EncryptSecret(vMasterKeyIn, mKey.second, vchPubKeyH.GetHash(), vchCryptedSecretH))
+ return false;
+ if (!AddCryptedMalleableKey(mKey.first, vchCryptedSecretH))
+ return false;
+ }
+ mapMalleableKeys.clear();
}
return true;
}
}
mapCryptedKeys.clear();
+
+ CryptedMalleableKeyMap::const_iterator mi2 = mapCryptedMalleableKeys.begin();
+ for(; mi2 != mapCryptedMalleableKeys.end(); ++mi2)
+ {
+ const CPubKey vchPubKeyH = mi2->first.GetMalleablePubKey().GetH();
+
+ CSecret vchSecretH;
+ if(!DecryptSecret(vMasterKeyIn, mi2->second, vchPubKeyH.GetHash(), vchSecretH))
+ return false;
+ if (vchSecretH.size() != 32)
+ return false;
+
+ if (!CBasicKeyStore::AddMalleableKey(mi2->first, vchSecretH))
+ return false;
+ }
+ mapCryptedMalleableKeys.clear();
}
return true;
virtual bool AddKey(const CKey& key) =0;
// Add a malleable key to store.
- virtual bool AddMalleableKey(const CMalleableKey& mKey) =0;
+ virtual bool AddMalleableKey(const CMalleableKeyView &keyView, const CSecret &vchSecretH) =0;
virtual bool GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const =0;
// Check whether a key corresponding to a given address is present in the store.
public:
bool AddKey(const CKey& key);
- bool AddMalleableKey(const CMalleableKey& mKey);
+ bool AddMalleableKey(const CMalleableKeyView& keyView, const CSecret &vchSecretH);
bool GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const
{
{
void ListMalleableViews(std::list<CMalleableKeyView> &malleableViewList) const
{
malleableViewList.clear();
-
{
LOCK(cs_KeyStore);
for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
};
typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap;
+typedef std::map<CMalleableKeyView, std::vector<unsigned char> > CryptedMalleableKeyMap;
/** Keystore which keeps the private keys encrypted.
* It derives from the basic key store, which is used if no encryption is active.
{
private:
CryptedKeyMap mapCryptedKeys;
+ CryptedMalleableKeyMap mapCryptedMalleableKeys;
CKeyingMaterial vMasterKey;
bool Lock();
virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
+ virtual bool AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char> &vchCryptedSecretH);
+
bool AddKey(const CKey& key);
+ bool AddMalleableKey(const CMalleableKeyView& keyView, const CSecret &vchSecretH);
bool HaveKey(const CKeyID &address) const
{
{
}
}
+ bool GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const;
+
+ bool CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const
+ {
+ {
+ LOCK(cs_KeyStore);
+ if (!IsCrypted())
+ return CBasicKeyStore::CheckOwnership(pubKeyVariant, R);
+ for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
+ {
+ if (mi->first.CheckKeyVariant(R, pubKeyVariant))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R, CMalleableKeyView &view) const
+ {
+ {
+ LOCK(cs_KeyStore);
+ if (!IsCrypted())
+ return CBasicKeyStore::CheckOwnership(pubKeyVariant, R, view);
+ for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
+ {
+ if (mi->first.CheckKeyVariant(R, pubKeyVariant))
+ {
+ view = mi->first;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ bool CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const;
+
+ void ListMalleableViews(std::list<CMalleableKeyView> &malleableViewList) const
+ {
+ malleableViewList.clear();
+ {
+ LOCK(cs_KeyStore);
+ if (!IsCrypted())
+ return CBasicKeyStore::ListMalleableViews(malleableViewList);
+ for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
+ malleableViewList.push_back(CMalleableKeyView(mi->first));
+ }
+ }
+
+ bool GetMalleableView(const CMalleablePubKey &mpk, CMalleableKeyView &view)
+ {
+ const CKeyID &mpkID = mpk.GetID();
+ {
+ LOCK(cs_KeyStore);
+ if (!IsCrypted())
+ return CBasicKeyStore::GetMalleableView(mpk, view);
+ for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
+ if (mi->first.GetID() == mpkID)
+ {
+ view = CMalleableKeyView(mi->first);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/* Wallet status (encrypted, locked) changed.
* Note: Called without locks held.
*/
"importprivkey <novacoinprivkey> [label] [rescan=true]\n"
"Adds a private key (as returned by dumpprivkey) to your wallet.");
+ EnsureWalletIsUnlocked();
+
string strSecret = params[0].get_str();
string strLabel = "";
if (params.size() > 1)
"dumpmalleablekey <Key view>\n"
"Dump the private and public key pairs, which correspond to provided key view.\n");
+ EnsureWalletIsUnlocked();
+
CMalleableKey mKey;
CMalleableKeyView keyView;
keyView.SetString(params[0].get_str());
"importmalleablekey <Key data>\n"
"Imports the private key pair into your wallet.\n");
+
+ EnsureWalletIsUnlocked();
+
CMalleableKey mKey;
bool fSuccess = mKey.SetString(params[0].get_str());
bool CWallet::AddMalleableKey(const CMalleableKey& mKey)
{
CMalleableKeyView keyView = CMalleableKeyView(mKey);
- if (!CCryptoKeyStore::AddMalleableKey(mKey))
+ CSecret vchSecretH = mKey.GetSecretH();
+ if (!CCryptoKeyStore::AddMalleableKey(keyView, vchSecretH))
return false;
if (!fFileBacked)
return true;
if (!IsCrypted())
- return CWalletDB(strWalletFile).WriteMalleableKey(keyView, mKey, mapMalleableKeyMetadata[keyView]);
+ return CWalletDB(strWalletFile).WriteMalleableKey(keyView, vchSecretH, mapMalleableKeyMetadata[keyView]);
+ return true;
+}
+
+bool CWallet::AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char> &vchCryptedSecretH)
+{
+ if (!CCryptoKeyStore::AddCryptedMalleableKey(keyView, vchCryptedSecretH))
+ return false;
+
+ if (!fFileBacked)
+ return true;
+
+ {
+ LOCK(cs_wallet);
+ if (pwalletdbEncryption)
+ return pwalletdbEncryption->WriteCryptedMalleableKey(keyView, vchCryptedSecretH, mapMalleableKeyMetadata[keyView]);
+ else
+ return CWalletDB(strWalletFile).WriteCryptedMalleableKey(keyView, vchCryptedSecretH, mapMalleableKeyMetadata[keyView]);
+ }
+
return true;
}
mi++;
}
+ MalleableKeyMap::const_iterator mi2 = mapMalleableKeys.begin();
+ while (mi2 != mapMalleableKeys.end())
+ {
+ const CSecret &vchSecretH = mi2->second;
+ const CMalleableKeyView &keyView = mi2->first;
+ pwalletdbDecryption->EraseCryptedMalleableKey(keyView);
+ pwalletdbDecryption->WriteMalleableKey(keyView, vchSecretH, mapMalleableKeyMetadata[keyView]);
+ mi2++;
+ }
+
// Erase master keys
MasterKeyMap::const_iterator mk = mapMasterKeys.begin();
while (mk != mapMasterKeys.end())
bool LoadMalleableKeyMetadata(const CMalleableKeyView &keyView, const CKeyMetadata &metadata);
// Load malleable key without saving it to disk (used by LoadWallet)
- bool LoadMalleableKey(const CMalleableKey &mKey) { return CCryptoKeyStore::AddMalleableKey(mKey); }
+ bool LoadMalleableKey(const CMalleableKeyView &keyView, const CSecret &vchSecretH) { return CCryptoKeyStore::AddMalleableKey(keyView, vchSecretH); }
+ bool LoadCryptedMalleableKey(const CMalleableKeyView &keyView, const std::vector<unsigned char> &vchCryptedSecretH) { return CCryptoKeyStore::AddCryptedMalleableKey(keyView, vchCryptedSecretH); }
bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
// Adds an encrypted key to the store, and saves it to disk.
bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
+ bool AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char> &vchCryptedSecretH);
// Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { SetMinVersion(FEATURE_WALLETCRYPT); return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
bool AddCScript(const CScript& redeemScript);
}
else if (strType == "malpair")
{
- string strKey, strKeyView;
+ string strKeyView;
CSecret vchSecret;
- CMalleableKeyView keyView;
-
ssKey >> strKeyView;
- keyView.SetString(strKeyView);
ssValue >> vchSecret;
- CMalleableKey mKey = keyView.GetMalleableKey(vchSecret);
-
- if (mKey.IsNull())
- {
- strErr = "Error reading wallet database: CMalleableKey is corrupt";
- return false;
- }
- if (mKey.GetID() != keyView.GetID())
+ CMalleableKeyView keyView(strKeyView);
+ if (!pwallet->LoadMalleableKey(keyView, vchSecret))
{
- strErr = "Error reading wallet database: CMalleableKey view inconsistency";
+ strErr = "Error reading wallet database: LoadMalleableKey failed";
return false;
}
+ }
+ else if (strType == "malcpair")
+ {
+ string strKeyView;
- if (!pwallet->LoadMalleableKey(mKey))
+ std::vector<unsigned char> vchCryptedSecret;
+ ssKey >> strKeyView;
+ ssValue >> vchCryptedSecret;
+
+ CMalleableKeyView keyView(strKeyView);
+ if (!pwallet->LoadCryptedMalleableKey(keyView, vchCryptedSecret))
{
- strErr = "Error reading wallet database: LoadMalleableKey failed";
+ strErr = "Error reading wallet database: LoadCryptedMalleableKey failed";
return false;
}
}
static bool IsKeyType(string strType)
{
return (strType== "key" || strType == "wkey" ||
- strType == "mkey" || strType == "ckey" || strType == "malpair");
+ strType == "mkey" || strType == "ckey" || strType == "malpair" || strType == "malcpair");
}
DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
return true;
}
- bool WriteMalleableKey(const CMalleableKeyView& keyView, const CMalleableKey& malleableKey, const CKeyMetadata &keyMeta)
+ bool WriteMalleableKey(const CMalleableKeyView& keyView, const CSecret& vchSecretH, const CKeyMetadata &keyMeta)
{
nWalletDBUpdated++;
if(!Write(std::make_pair(std::string("malmeta"), keyView.ToString()), keyMeta))
return false;
- if(!Write(std::make_pair(std::string("malpair"), keyView.ToString()), malleableKey.GetSecretH(), false))
+ if(!Write(std::make_pair(std::string("malpair"), keyView.ToString()), vchSecretH, false))
return false;
return true;
}
+ bool WriteCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char>& vchCryptedSecretH, const CKeyMetadata &keyMeta)
+ {
+ nWalletDBUpdated++;
+ if(!Write(std::make_pair(std::string("malmeta"), keyView.ToString()), keyMeta))
+ return false;
+
+ if(!Write(std::make_pair(std::string("malcpair"), keyView.ToString()), vchCryptedSecretH, false))
+ return false;
+
+ Erase(std::make_pair(std::string("malpair"), keyView.ToString()));
+
+ return true;
+ }
+
bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, const CKeyMetadata &keyMeta)
{
return Erase(std::make_pair(std::string("ckey"), vchPubKey.Raw()));
}
+ bool EraseCryptedMalleableKey(const CMalleableKeyView& keyView)
+ {
+ return Erase(std::make_pair(std::string("malcpair"), keyView.ToString()));
+ }
+
bool WriteCScript(const uint160& hash, const CScript& redeemScript)
{
nWalletDBUpdated++;