crypter.h
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 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, 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 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