bitcoin/src/wallet/test/fuzz/crypter.cpp
Ava Chow 14b8dfb2bd
Merge bitcoin/bitcoin#31398: wallet: refactor: various master key encryption cleanups
a8333fc9ff9adaa97a1f9024f5783cc071777150 scripted-diff: wallet: rename plain and encrypted master key variables (Sebastian Falbesoner)
5a92077fd5317f936da2fa0aa45e0173248f765b wallet: refactor: dedup master key decryption (Sebastian Falbesoner)
846545947cd3b993c40362b9d0afcd7b4f5f05bd wallet: refactor: dedup master key encryption / derivation rounds setting (Sebastian Falbesoner)
a6d9b415aa3afcfe463887d0fde00c3d2d32672a wallet: refactor: introduce `CMasterKey::DEFAULT_DERIVE_ITERATIONS` constant (Sebastian Falbesoner)
62c209f50d9c33fde5062ebca317b9a4233aff62 wallet: doc: remove mentions of unavailable scrypt derivation method (Sebastian Falbesoner)

Pull request description:

  This PR contains various cleanups around the wallet's master key encryption logic. The default/minimum key derivation rounds magic number of 25000 is hoisted into a constant (member of `CMasterKey`) and two new functions `EncryptMasterKey`/`DecryptMasterKey` are introduced in order to deduplicate code for the derivation round determination and master key en/decryption. Also, mentions of the never-implemented derivation method `scrypt` are removed from the wallet crypter header and both plain and encrypted master key instances are renamed to adapt to moderning coding style (hopefully improving readability).

ACKs for top commit:
  davidgumberg:
    ACK a8333fc9ff
  achow101:
    ACK a8333fc9ff9adaa97a1f9024f5783cc071777150

Tree-SHA512: 5a66d3b26f481347d0b5b4f742dd237803a35aad6e3480ed15fd38b7fa3700650bd5f67f4c30ed88f5fad45d6cd4c893fe4f1657e36e563b4294fd3596187724
2025-04-29 16:32:21 -07:00

89 lines
3.6 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <test/util/setup_common.h>
#include <wallet/crypter.h>
namespace wallet {
namespace {
const TestingSetup* g_setup;
void initialize_crypter()
{
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
g_setup = testing_setup.get();
}
FUZZ_TARGET(crypter, .init = initialize_crypter)
{
SeedRandomStateForTest(SeedRand::ZEROS);
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
bool good_data{true};
CCrypter crypt;
// These values are regularly updated within `CallOneOf`
std::vector<unsigned char> cipher_text_ed;
CKeyingMaterial plain_text_ed;
const std::vector<unsigned char> random_key = ConsumeFixedLengthByteVector(fuzzed_data_provider, WALLET_CRYPTO_KEY_SIZE);
if (fuzzed_data_provider.ConsumeBool()) {
const std::string random_string = fuzzed_data_provider.ConsumeRandomLengthString(100);
SecureString secure_string(random_string.begin(), random_string.end());
const unsigned int derivation_method = fuzzed_data_provider.ConsumeBool() ? 0 : fuzzed_data_provider.ConsumeIntegral<unsigned int>();
// Limiting the value of rounds since it is otherwise uselessly expensive and causes a timeout when fuzzing.
crypt.SetKeyFromPassphrase(/*key_data=*/secure_string,
/*salt=*/ConsumeFixedLengthByteVector(fuzzed_data_provider, WALLET_CRYPTO_SALT_SIZE),
/*rounds=*/fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, CMasterKey::DEFAULT_DERIVE_ITERATIONS),
/*derivation_method=*/derivation_method);
}
CKey random_ckey;
random_ckey.Set(random_key.begin(), random_key.end(), /*fCompressedIn=*/fuzzed_data_provider.ConsumeBool());
if (!random_ckey.IsValid()) return;
CPubKey pubkey{random_ckey.GetPubKey()};
LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 100)
{
CallOneOf(
fuzzed_data_provider,
[&] {
const std::vector<unsigned char> random_vector = ConsumeFixedLengthByteVector(fuzzed_data_provider, WALLET_CRYPTO_KEY_SIZE);
plain_text_ed = CKeyingMaterial(random_vector.begin(), random_vector.end());
},
[&] {
cipher_text_ed = ConsumeRandomLengthByteVector(fuzzed_data_provider, 64);
},
[&] {
(void)crypt.Encrypt(plain_text_ed, cipher_text_ed);
},
[&] {
(void)crypt.Decrypt(cipher_text_ed, plain_text_ed);
},
[&] {
const CKeyingMaterial master_key(random_key.begin(), random_key.end());;
(void)EncryptSecret(master_key, plain_text_ed, pubkey.GetHash(), cipher_text_ed);
},
[&] {
std::optional<CPubKey> random_pub_key{ConsumeDeserializable<CPubKey>(fuzzed_data_provider)};
if (!random_pub_key) {
good_data = false;
return;
}
pubkey = *random_pub_key;
},
[&] {
const CKeyingMaterial master_key(random_key.begin(), random_key.end());
CKey key;
(void)DecryptKey(master_key, cipher_text_ed, pubkey, key);
});
}
}
} // namespace
} // namespace wallet