1 // Copyright (c) 2009-2020 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 const unsigned int WALLET_CRYPTO_KEY_SIZE = 32; 14 const unsigned int WALLET_CRYPTO_SALT_SIZE = 8; 15 const unsigned int WALLET_CRYPTO_IV_SIZE = 16; 16 17 /** 18 * Private key encryption is done based on a CMasterKey, 19 * which holds a salt and random encryption key. 20 * 21 * CMasterKeys are encrypted using AES-256-CBC using a key 22 * derived using derivation method nDerivationMethod 23 * (0 == EVP_sha512()) and derivation iterations nDeriveIterations. 24 * vchOtherDerivationParameters is provided for alternative algorithms 25 * which may require more parameters (such as scrypt). 26 * 27 * Wallet Private Keys are then encrypted using AES-256-CBC 28 * with the double-sha256 of the public key as the IV, and the 29 * master key's key as the encryption key (see keystore.[ch]). 30 */ 31 32 /** Master key for wallet encryption */ 33 class CMasterKey 34 { 35 public: 36 std::vector<unsigned char> vchCryptedKey; 37 std::vector<unsigned char> vchSalt; 38 //! 0 = EVP_sha512() 39 //! 1 = scrypt() 40 unsigned int nDerivationMethod; 41 unsigned int nDeriveIterations; 42 //! Use this for more parameters to key derivation, 43 //! such as the various parameters to scrypt 44 std::vector<unsigned char> vchOtherDerivationParameters; 45 SERIALIZE_METHODS(CMasterKey,obj)46 SERIALIZE_METHODS(CMasterKey, obj) 47 { 48 READWRITE(obj.vchCryptedKey, obj.vchSalt, obj.nDerivationMethod, obj.nDeriveIterations, obj.vchOtherDerivationParameters); 49 } 50 CMasterKey()51 CMasterKey() 52 { 53 // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M 54 // ie slightly lower than the lowest hardware we need bother supporting 55 nDeriveIterations = 25000; 56 nDerivationMethod = 0; 57 vchOtherDerivationParameters = std::vector<unsigned char>(0); 58 } 59 }; 60 61 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial; 62 63 namespace wallet_crypto_tests 64 { 65 class TestCrypter; 66 } 67 68 /** Encryption/decryption context with key information */ 69 class CCrypter 70 { 71 friend class wallet_crypto_tests::TestCrypter; // for test access to chKey/chIV 72 private: 73 std::vector<unsigned char, secure_allocator<unsigned char>> vchKey; 74 std::vector<unsigned char, secure_allocator<unsigned char>> vchIV; 75 bool fKeySet; 76 77 int BytesToKeySHA512AES(const std::vector<unsigned char>& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const; 78 79 public: 80 bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod); 81 bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext) const; 82 bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext) const; 83 bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV); 84 CleanKey()85 void CleanKey() 86 { 87 memory_cleanse(vchKey.data(), vchKey.size()); 88 memory_cleanse(vchIV.data(), vchIV.size()); 89 fKeySet = false; 90 } 91 CCrypter()92 CCrypter() 93 { 94 fKeySet = false; 95 vchKey.resize(WALLET_CRYPTO_KEY_SIZE); 96 vchIV.resize(WALLET_CRYPTO_IV_SIZE); 97 } 98 ~CCrypter()99 ~CCrypter() 100 { 101 CleanKey(); 102 } 103 }; 104 105 bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext); 106 bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext); 107 bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key); 108 109 #endif // BITCOIN_WALLET_CRYPTER_H 110