/ 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 (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      SERIALIZE_METHODS(CMasterKey, obj)
 48      {
 49          READWRITE(obj.vchCryptedKey, obj.vchSalt, obj.nDerivationMethod, obj.nDeriveIterations, obj.vchOtherDerivationParameters);
 50      }
 51  
 52      CMasterKey()
 53      {
 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          nDeriveIterations = 25000;
 57          nDerivationMethod = 0;
 58          vchOtherDerivationParameters = std::vector<unsigned char>(0);
 59      }
 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(const std::vector<unsigned char>& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const;
 79  
 80  public:
 81      bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
 82      bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext) const;
 83      bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext) const;
 84      bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV);
 85  
 86      void CleanKey()
 87      {
 88          memory_cleanse(vchKey.data(), vchKey.size());
 89          memory_cleanse(vchIV.data(), vchIV.size());
 90          fKeySet = false;
 91      }
 92  
 93      CCrypter()
 94      {
 95          fKeySet = false;
 96          vchKey.resize(WALLET_CRYPTO_KEY_SIZE);
 97          vchIV.resize(WALLET_CRYPTO_IV_SIZE);
 98      }
 99  
100      ~CCrypter()
101      {
102          CleanKey();
103      }
104  };
105  
106  bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
107  bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
108  bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key);
109  } // namespace wallet
110  
111  #endif // BITCOIN_WALLET_CRYPTER_H