1 // Copyright (c) 2009-2016 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.
5 #ifndef BITCOIN_WALLET_CRYPTER_H
6 #define BITCOIN_WALLET_CRYPTER_H
10 #include "support/allocators/secure.h"
12 const unsigned int WALLET_CRYPTO_KEY_SIZE
= 32;
13 const unsigned int WALLET_CRYPTO_SALT_SIZE
= 8;
14 const unsigned int WALLET_CRYPTO_IV_SIZE
= 16;
17 * Private key encryption is done based on a CMasterKey,
18 * which holds a salt and random encryption key.
20 * CMasterKeys are encrypted using AES-256-CBC using a key
21 * derived using derivation method nDerivationMethod
22 * (0 == EVP_sha512()) and derivation iterations nDeriveIterations.
23 * vchOtherDerivationParameters is provided for alternative algorithms
24 * which may require more parameters (such as scrypt).
26 * Wallet Private Keys are then encrypted using AES-256-CBC
27 * with the double-sha256 of the public key as the IV, and the
28 * master key's key as the encryption key (see keystore.[ch]).
31 /** Master key for wallet encryption */
35 std::vector
<unsigned char> vchCryptedKey
;
36 std::vector
<unsigned char> vchSalt
;
39 unsigned int nDerivationMethod
;
40 unsigned int nDeriveIterations
;
41 //! Use this for more parameters to key derivation,
42 //! such as the various parameters to scrypt
43 std::vector
<unsigned char> vchOtherDerivationParameters
;
45 ADD_SERIALIZE_METHODS
;
47 template <typename Stream
, typename Operation
>
48 inline void SerializationOp(Stream
& s
, Operation ser_action
) {
49 READWRITE(vchCryptedKey
);
51 READWRITE(nDerivationMethod
);
52 READWRITE(nDeriveIterations
);
53 READWRITE(vchOtherDerivationParameters
);
58 // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
59 // ie slightly lower than the lowest hardware we need bother supporting
60 nDeriveIterations
= 25000;
61 nDerivationMethod
= 0;
62 vchOtherDerivationParameters
= std::vector
<unsigned char>(0);
66 typedef std::vector
<unsigned char, secure_allocator
<unsigned char> > CKeyingMaterial
;
68 namespace wallet_crypto
73 /** Encryption/decryption context with key information */
76 friend class wallet_crypto::TestCrypter
; // for test access to chKey/chIV
78 std::vector
<unsigned char, secure_allocator
<unsigned char>> vchKey
;
79 std::vector
<unsigned char, secure_allocator
<unsigned char>> vchIV
;
82 int BytesToKeySHA512AES(const std::vector
<unsigned char>& chSalt
, const SecureString
& strKeyData
, int count
, unsigned char *key
,unsigned char *iv
) const;
85 bool SetKeyFromPassphrase(const SecureString
&strKeyData
, const std::vector
<unsigned char>& chSalt
, const unsigned int nRounds
, const unsigned int nDerivationMethod
);
86 bool Encrypt(const CKeyingMaterial
& vchPlaintext
, std::vector
<unsigned char> &vchCiphertext
) const;
87 bool Decrypt(const std::vector
<unsigned char>& vchCiphertext
, CKeyingMaterial
& vchPlaintext
) const;
88 bool SetKey(const CKeyingMaterial
& chNewKey
, const std::vector
<unsigned char>& chNewIV
);
92 memory_cleanse(vchKey
.data(), vchKey
.size());
93 memory_cleanse(vchIV
.data(), vchIV
.size());
100 vchKey
.resize(WALLET_CRYPTO_KEY_SIZE
);
101 vchIV
.resize(WALLET_CRYPTO_IV_SIZE
);
110 /** Keystore which keeps the private keys encrypted.
111 * It derives from the basic key store, which is used if no encryption is active.
113 class CCryptoKeyStore
: public CBasicKeyStore
117 CKeyingMaterial vMasterKey
;
119 //! if fUseCrypto is true, mapKeys must be empty
120 //! if fUseCrypto is false, vMasterKey must be empty
123 //! keeps track of whether Unlock has run a thorough check before
124 bool fDecryptionThoroughlyChecked
;
129 //! will encrypt previously unencrypted keys
130 bool EncryptKeys(CKeyingMaterial
& vMasterKeyIn
);
132 bool Unlock(const CKeyingMaterial
& vMasterKeyIn
);
133 CryptedKeyMap mapCryptedKeys
;
136 CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false)
140 bool IsCrypted() const
145 bool IsLocked() const
152 result
= vMasterKey
.empty();
159 virtual bool AddCryptedKey(const CPubKey
&vchPubKey
, const std::vector
<unsigned char> &vchCryptedSecret
);
160 bool AddKeyPubKey(const CKey
& key
, const CPubKey
&pubkey
) override
;
161 bool HaveKey(const CKeyID
&address
) const override
166 return CBasicKeyStore::HaveKey(address
);
167 return mapCryptedKeys
.count(address
) > 0;
171 bool GetKey(const CKeyID
&address
, CKey
& keyOut
) const override
;
172 bool GetPubKey(const CKeyID
&address
, CPubKey
& vchPubKeyOut
) const override
;
173 void GetKeys(std::set
<CKeyID
> &setAddress
) const override
177 CBasicKeyStore::GetKeys(setAddress
);
181 CryptedKeyMap::const_iterator mi
= mapCryptedKeys
.begin();
182 while (mi
!= mapCryptedKeys
.end())
184 setAddress
.insert((*mi
).first
);
190 * Wallet status (encrypted, locked) changed.
191 * Note: Called without locks held.
193 boost::signals2::signal
<void (CCryptoKeyStore
* wallet
)> NotifyStatusChanged
;
196 #endif // BITCOIN_WALLET_CRYPTER_H