Merge #10027: Set to nullptr after delete
[bitcoinplatinum.git] / src / wallet / crypter.h
blob275e435f73b87f0d4dfd1f082b60e6b4140fba50
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
8 #include "keystore.h"
9 #include "serialize.h"
10 #include "support/allocators/secure.h"
12 class uint256;
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;
18 /**
19 * Private key encryption is done based on a CMasterKey,
20 * which holds a salt and random encryption key.
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).
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]).
33 /** Master key for wallet encryption */
34 class CMasterKey
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;
47 ADD_SERIALIZE_METHODS;
49 template <typename Stream, typename Operation>
50 inline void SerializationOp(Stream& s, Operation ser_action) {
51 READWRITE(vchCryptedKey);
52 READWRITE(vchSalt);
53 READWRITE(nDerivationMethod);
54 READWRITE(nDeriveIterations);
55 READWRITE(vchOtherDerivationParameters);
58 CMasterKey()
60 // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
61 // ie slightly lower than the lowest hardware we need bother supporting
62 nDeriveIterations = 25000;
63 nDerivationMethod = 0;
64 vchOtherDerivationParameters = std::vector<unsigned char>(0);
68 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
70 namespace wallet_crypto
72 class TestCrypter;
75 /** Encryption/decryption context with key information */
76 class CCrypter
78 friend class wallet_crypto::TestCrypter; // for test access to chKey/chIV
79 private:
80 std::vector<unsigned char, secure_allocator<unsigned char>> vchKey;
81 std::vector<unsigned char, secure_allocator<unsigned char>> vchIV;
82 bool fKeySet;
84 int BytesToKeySHA512AES(const std::vector<unsigned char>& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const;
86 public:
87 bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
88 bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext) const;
89 bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext) const;
90 bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV);
92 void CleanKey()
94 memory_cleanse(vchKey.data(), vchKey.size());
95 memory_cleanse(vchIV.data(), vchIV.size());
96 fKeySet = false;
99 CCrypter()
101 fKeySet = false;
102 vchKey.resize(WALLET_CRYPTO_KEY_SIZE);
103 vchIV.resize(WALLET_CRYPTO_IV_SIZE);
106 ~CCrypter()
108 CleanKey();
112 /** Keystore which keeps the private keys encrypted.
113 * It derives from the basic key store, which is used if no encryption is active.
115 class CCryptoKeyStore : public CBasicKeyStore
117 private:
118 CryptedKeyMap mapCryptedKeys;
120 CKeyingMaterial vMasterKey;
122 //! if fUseCrypto is true, mapKeys must be empty
123 //! if fUseCrypto is false, vMasterKey must be empty
124 bool fUseCrypto;
126 //! keeps track of whether Unlock has run a thorough check before
127 bool fDecryptionThoroughlyChecked;
129 protected:
130 bool SetCrypted();
132 //! will encrypt previously unencrypted keys
133 bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
135 bool Unlock(const CKeyingMaterial& vMasterKeyIn);
137 public:
138 CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false)
142 bool IsCrypted() const
144 return fUseCrypto;
147 bool IsLocked() const
149 if (!IsCrypted())
150 return false;
151 bool result;
153 LOCK(cs_KeyStore);
154 result = vMasterKey.empty();
156 return result;
159 bool Lock();
161 virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
162 bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
163 bool HaveKey(const CKeyID &address) const
166 LOCK(cs_KeyStore);
167 if (!IsCrypted())
168 return CBasicKeyStore::HaveKey(address);
169 return mapCryptedKeys.count(address) > 0;
171 return false;
173 bool GetKey(const CKeyID &address, CKey& keyOut) const;
174 bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
175 void GetKeys(std::set<CKeyID> &setAddress) const
177 if (!IsCrypted())
179 CBasicKeyStore::GetKeys(setAddress);
180 return;
182 setAddress.clear();
183 CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
184 while (mi != mapCryptedKeys.end())
186 setAddress.insert((*mi).first);
187 mi++;
192 * Wallet status (encrypted, locked) changed.
193 * Note: Called without locks held.
195 boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
198 #endif // BITCOIN_WALLET_CRYPTER_H