Coverage Report

Created: 2025-04-14 16:24

/Users/mcomp/contrib/bitcoin/src/wallet/crypter.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2009-2021 The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#ifndef BITCOIN_WALLET_CRYPTER_H
6
#define BITCOIN_WALLET_CRYPTER_H
7
8
#include <serialize.h>
9
#include <support/allocators/secure.h>
10
#include <script/signingprovider.h>
11
12
13
namespace wallet {
14
const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
15
const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
16
const unsigned int WALLET_CRYPTO_IV_SIZE = 16;
17
18
/**
19
 * Private key encryption is done based on a CMasterKey,
20
 * which holds a salt and random encryption key.
21
 *
22
 * CMasterKeys are encrypted using AES-256-CBC using a key
23
 * derived using derivation method nDerivationMethod
24
 * (0 == EVP_sha512()) and derivation iterations nDeriveIterations.
25
 * vchOtherDerivationParameters is provided for alternative algorithms
26
 * which may require more parameters (such as scrypt).
27
 *
28
 * Wallet Private Keys are then encrypted using AES-256-CBC
29
 * with the double-sha256 of the public key as the IV, and the
30
 * master key's key as the encryption key (see keystore.[ch]).
31
 */
32
33
/** Master key for wallet encryption */
34
class CMasterKey
35
{
36
public:
37
    std::vector<unsigned char> vchCryptedKey;
38
    std::vector<unsigned char> vchSalt;
39
    //! 0 = EVP_sha512()
40
    //! 1 = scrypt()
41
    unsigned int nDerivationMethod;
42
    unsigned int nDeriveIterations;
43
    //! Use this for more parameters to key derivation,
44
    //! such as the various parameters to scrypt
45
    std::vector<unsigned char> vchOtherDerivationParameters;
46
47
    SERIALIZE_METHODS(CMasterKey, obj)
48
0
    {
49
0
        READWRITE(obj.vchCryptedKey, obj.vchSalt, obj.nDerivationMethod, obj.nDeriveIterations, obj.vchOtherDerivationParameters);
50
0
    }
Unexecuted instantiation: _ZN6wallet10CMasterKey16SerializationOpsI10DataStreamKS0_15ActionSerializeEEvRT0_RT_T1_
Unexecuted instantiation: _ZN6wallet10CMasterKey16SerializationOpsI10DataStreamS0_17ActionUnserializeEEvRT0_RT_T1_
51
52
    CMasterKey()
53
0
    {
54
        // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
55
        // ie slightly lower than the lowest hardware we need bother supporting
56
0
        nDeriveIterations = 25000;
57
0
        nDerivationMethod = 0;
58
0
        vchOtherDerivationParameters = std::vector<unsigned char>(0);
59
0
    }
60
};
61
62
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
63
64
namespace wallet_crypto_tests
65
{
66
    class TestCrypter;
67
}
68
69
/** Encryption/decryption context with key information */
70
class CCrypter
71
{
72
friend class wallet_crypto_tests::TestCrypter; // for test access to chKey/chIV
73
private:
74
    std::vector<unsigned char, secure_allocator<unsigned char>> vchKey;
75
    std::vector<unsigned char, secure_allocator<unsigned char>> vchIV;
76
    bool fKeySet;
77
78
    int BytesToKeySHA512AES(std::span<const unsigned char> salt, const SecureString& key_data, int count, unsigned char* key, unsigned char* iv) const;
79
80
public:
81
    bool SetKeyFromPassphrase(const SecureString& key_data, std::span<const unsigned char> salt, const unsigned int rounds, const unsigned int derivation_method);
82
    bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext) const;
83
    bool Decrypt(std::span<const unsigned char> ciphertext, CKeyingMaterial& plaintext) const;
84
    bool SetKey(const CKeyingMaterial& new_key, std::span<const unsigned char> new_iv);
85
86
    void CleanKey()
87
0
    {
88
0
        memory_cleanse(vchKey.data(), vchKey.size());
89
0
        memory_cleanse(vchIV.data(), vchIV.size());
90
0
        fKeySet = false;
91
0
    }
92
93
    CCrypter()
94
0
    {
95
0
        fKeySet = false;
96
0
        vchKey.resize(WALLET_CRYPTO_KEY_SIZE);
97
0
        vchIV.resize(WALLET_CRYPTO_IV_SIZE);
98
0
    }
99
100
    ~CCrypter()
101
0
    {
102
0
        CleanKey();
103
0
    }
104
};
105
106
bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
107
bool DecryptSecret(const CKeyingMaterial& master_key, std::span<const unsigned char> ciphertext, const uint256& iv, CKeyingMaterial& plaintext);
108
bool DecryptKey(const CKeyingMaterial& master_key, std::span<const unsigned char> crypted_secret, const CPubKey& pub_key, CKey& key);
109
} // namespace wallet
110
111
#endif // BITCOIN_WALLET_CRYPTER_H