From 846545947cd3b993c40362b9d0afcd7b4f5f05bd Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sun, 1 Dec 2024 01:38:20 +0100 Subject: [PATCH] wallet: refactor: dedup master key encryption / derivation rounds setting --- src/wallet/wallet.cpp | 69 ++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 1f34bea441..7794034d0c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -576,6 +576,35 @@ void CWallet::UpgradeDescriptorCache() SetWalletFlag(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED); } +/* Given a wallet passphrase string and an unencrypted master key, determine the proper key + * derivation parameters (should take at least 100ms) and encrypt the master key. */ +static bool EncryptMasterKey(const SecureString& wallet_passphrase, const CKeyingMaterial& plain_master_key, CMasterKey& master_key) +{ + constexpr MillisecondsDouble target{100}; + auto start{SteadyClock::now()}; + CCrypter crypter; + + crypter.SetKeyFromPassphrase(wallet_passphrase, master_key.vchSalt, master_key.nDeriveIterations, master_key.nDerivationMethod); + master_key.nDeriveIterations = static_cast(master_key.nDeriveIterations * target / (SteadyClock::now() - start)); + + start = SteadyClock::now(); + crypter.SetKeyFromPassphrase(wallet_passphrase, master_key.vchSalt, master_key.nDeriveIterations, master_key.nDerivationMethod); + master_key.nDeriveIterations = (master_key.nDeriveIterations + static_cast(master_key.nDeriveIterations * target / (SteadyClock::now() - start))) / 2; + + if (master_key.nDeriveIterations < CMasterKey::DEFAULT_DERIVE_ITERATIONS) { + master_key.nDeriveIterations = CMasterKey::DEFAULT_DERIVE_ITERATIONS; + } + + if (!crypter.SetKeyFromPassphrase(wallet_passphrase, master_key.vchSalt, master_key.nDeriveIterations, master_key.nDerivationMethod)) { + return false; + } + if (!crypter.Encrypt(plain_master_key, master_key.vchCryptedKey)) { + return false; + } + + return true; +} + bool CWallet::Unlock(const SecureString& strWalletPassphrase) { CCrypter crypter; @@ -619,24 +648,11 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, return false; if (Unlock(_vMasterKey)) { - constexpr MillisecondsDouble target{100}; - auto start{SteadyClock::now()}; - crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod); - pMasterKey.second.nDeriveIterations = static_cast(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start)); - - start = SteadyClock::now(); - crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod); - pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2; - - if (pMasterKey.second.nDeriveIterations < CMasterKey::DEFAULT_DERIVE_ITERATIONS) - pMasterKey.second.nDeriveIterations = CMasterKey::DEFAULT_DERIVE_ITERATIONS; - + if (!EncryptMasterKey(strNewWalletPassphrase, _vMasterKey, pMasterKey.second)) { + return false; + } WalletLogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations); - if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) - return false; - if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey)) - return false; WalletBatch(GetDatabase()).WriteMasterKey(pMasterKey.first, pMasterKey.second); if (fWasLocked) Lock(); @@ -822,26 +838,11 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE); GetStrongRandBytes(kMasterKey.vchSalt); - CCrypter crypter; - constexpr MillisecondsDouble target{100}; - auto start{SteadyClock::now()}; - crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, CMasterKey::DEFAULT_DERIVE_ITERATIONS, kMasterKey.nDerivationMethod); - kMasterKey.nDeriveIterations = static_cast(CMasterKey::DEFAULT_DERIVE_ITERATIONS * target / (SteadyClock::now() - start)); - - start = SteadyClock::now(); - crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod); - kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast(kMasterKey.nDeriveIterations * target / (SteadyClock::now() - start))) / 2; - - if (kMasterKey.nDeriveIterations < CMasterKey::DEFAULT_DERIVE_ITERATIONS) - kMasterKey.nDeriveIterations = CMasterKey::DEFAULT_DERIVE_ITERATIONS; - + if (!EncryptMasterKey(strWalletPassphrase, _vMasterKey, kMasterKey)) { + return false; + } WalletLogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations); - if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod)) - return false; - if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey)) - return false; - { LOCK2(m_relock_mutex, cs_wallet); mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;