/ src / wallet / crypter.h
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