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 (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 : 15 : SERIALIZE_METHODS(CMasterKey, obj)
48 : : {
49 : 5 : READWRITE(obj.vchCryptedKey, obj.vchSalt, obj.nDerivationMethod, obj.nDeriveIterations, obj.vchOtherDerivationParameters);
50 : : }
51 : :
52 : 10 : CMasterKey()
53 [ + - ]: 10 : {
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 : 10 : nDeriveIterations = 25000;
57 : 10 : nDerivationMethod = 0;
58 [ + - ]: 10 : vchOtherDerivationParameters = std::vector<unsigned char>(0);
59 : 10 : }
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 : 5082 : void CleanKey()
87 : : {
88 : 5082 : memory_cleanse(vchKey.data(), vchKey.size());
89 : 5082 : memory_cleanse(vchIV.data(), vchIV.size());
90 : 5082 : fKeySet = false;
91 : 5082 : }
92 : :
93 : 5082 : CCrypter()
94 [ + - ]: 5082 : {
95 : 5082 : fKeySet = false;
96 [ + - ]: 5082 : vchKey.resize(WALLET_CRYPTO_KEY_SIZE);
97 [ + - ]: 5082 : vchIV.resize(WALLET_CRYPTO_IV_SIZE);
98 : 5082 : }
99 : :
100 : 5082 : ~CCrypter()
101 : : {
102 : 5082 : CleanKey();
103 : 5082 : }
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
|