crypter.h raw
1 // Copyright (c) 2009-present 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 SERIALIZE_METHODS(CMasterKey, obj)
51 {
52 READWRITE(obj.vchCryptedKey, obj.vchSalt, obj.nDerivationMethod, obj.nDeriveIterations, obj.vchOtherDerivationParameters);
53 }
54
55 CMasterKey()
56 {
57 nDeriveIterations = DEFAULT_DERIVE_ITERATIONS;
58 nDerivationMethod = 0;
59 vchOtherDerivationParameters = std::vector<unsigned char>(0);
60 }
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, unsigned int rounds, 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 void CleanKey()
88 {
89 memory_cleanse(vchKey.data(), vchKey.size());
90 memory_cleanse(vchIV.data(), vchIV.size());
91 fKeySet = false;
92 }
93
94 CCrypter()
95 {
96 fKeySet = false;
97 vchKey.resize(WALLET_CRYPTO_KEY_SIZE);
98 vchIV.resize(WALLET_CRYPTO_IV_SIZE);
99 }
100
101 ~CCrypter()
102 {
103 CleanKey();
104 }
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
113