Branch data Line data Source code
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.
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 : : unsigned int nDerivationMethod;
41 : : unsigned int nDeriveIterations;
42 : : //! Use this for more parameters to key derivation (currently unused)
43 : : std::vector<unsigned char> vchOtherDerivationParameters;
44 : :
45 : : //! Default/minimum number of key derivation rounds
46 : : // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
47 : : // ie slightly lower than the lowest hardware we need bother supporting
48 : : static constexpr unsigned int DEFAULT_DERIVE_ITERATIONS = 25000;
49 : :
50 : 0 : SERIALIZE_METHODS(CMasterKey, obj)
51 : : {
52 : 0 : READWRITE(obj.vchCryptedKey, obj.vchSalt, obj.nDerivationMethod, obj.nDeriveIterations, obj.vchOtherDerivationParameters);
53 : : }
54 : :
55 : 0 : CMasterKey()
56 [ # # ]: 0 : {
57 : 0 : nDeriveIterations = DEFAULT_DERIVE_ITERATIONS;
58 : 0 : nDerivationMethod = 0;
59 [ # # ]: 0 : vchOtherDerivationParameters = std::vector<unsigned char>(0);
60 : 0 : }
61 : : };
62 : :
63 : : typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
64 : :
65 : : namespace wallet_crypto_tests
66 : : {
67 : : class TestCrypter;
68 : : }
69 : :
70 : : /** Encryption/decryption context with key information */
71 : : class CCrypter
72 : : {
73 : : friend class wallet_crypto_tests::TestCrypter; // for test access to chKey/chIV
74 : : private:
75 : : std::vector<unsigned char, secure_allocator<unsigned char>> vchKey;
76 : : std::vector<unsigned char, secure_allocator<unsigned char>> vchIV;
77 : : bool fKeySet;
78 : :
79 : : int BytesToKeySHA512AES(std::span<const unsigned char> salt, const SecureString& key_data, int count, unsigned char* key, unsigned char* iv) const;
80 : :
81 : : public:
82 : : bool SetKeyFromPassphrase(const SecureString& key_data, std::span<const unsigned char> salt, const unsigned int rounds, const unsigned int derivation_method);
83 : : bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext) const;
84 : : bool Decrypt(std::span<const unsigned char> ciphertext, CKeyingMaterial& plaintext) const;
85 : : bool SetKey(const CKeyingMaterial& new_key, std::span<const unsigned char> new_iv);
86 : :
87 : 2050 : void CleanKey()
88 : : {
89 : 2050 : memory_cleanse(vchKey.data(), vchKey.size());
90 : 2050 : memory_cleanse(vchIV.data(), vchIV.size());
91 : 2050 : fKeySet = false;
92 : 2050 : }
93 : :
94 : 2050 : CCrypter()
95 [ + - ]: 2050 : {
96 : 2050 : fKeySet = false;
97 [ + - ]: 2050 : vchKey.resize(WALLET_CRYPTO_KEY_SIZE);
98 [ + - ]: 2050 : vchIV.resize(WALLET_CRYPTO_IV_SIZE);
99 : 2050 : }
100 : :
101 : 2050 : ~CCrypter()
102 : : {
103 : 2050 : CleanKey();
104 : 2050 : }
105 : : };
106 : :
107 : : bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
108 : : bool DecryptSecret(const CKeyingMaterial& master_key, std::span<const unsigned char> ciphertext, const uint256& iv, CKeyingMaterial& plaintext);
109 : : bool DecryptKey(const CKeyingMaterial& master_key, std::span<const unsigned char> crypted_secret, const CPubKey& pub_key, CKey& key);
110 : : } // namespace wallet
111 : :
112 : : #endif // BITCOIN_WALLET_CRYPTER_H
|