]> Git Repo - VerusCoin.git/blob - src/wallet/crypter.h
Update z_sendmany logging
[VerusCoin.git] / src / wallet / crypter.h
1 // Copyright (c) 2009-2014 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 "keystore.h"
9 #include "serialize.h"
10 #include "streams.h"
11 #include "support/allocators/secure.h"
12 #include "zcash/Address.hpp"
13
14 class uint256;
15
16 const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
17 const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
18
19 /**
20  * Private key encryption is done based on a CMasterKey,
21  * which holds a salt and random encryption key.
22  * 
23  * CMasterKeys are encrypted using AES-256-CBC using a key
24  * derived using derivation method nDerivationMethod
25  * (0 == EVP_sha512()) and derivation iterations nDeriveIterations.
26  * vchOtherDerivationParameters is provided for alternative algorithms
27  * which may require more parameters (such as scrypt).
28  * 
29  * Wallet Private Keys are then encrypted using AES-256-CBC
30  * with the double-sha256 of the public key as the IV, and the
31  * master key's key as the encryption key (see keystore.[ch]).
32  */
33
34 /** Master key for wallet encryption */
35 class CMasterKey
36 {
37 public:
38     std::vector<unsigned char> vchCryptedKey;
39     std::vector<unsigned char> vchSalt;
40     //! 0 = EVP_sha512()
41     //! 1 = scrypt()
42     unsigned int nDerivationMethod;
43     unsigned int nDeriveIterations;
44     //! Use this for more parameters to key derivation,
45     //! such as the various parameters to scrypt
46     std::vector<unsigned char> vchOtherDerivationParameters;
47
48     ADD_SERIALIZE_METHODS;
49
50     template <typename Stream, typename Operation>
51     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
52         READWRITE(vchCryptedKey);
53         READWRITE(vchSalt);
54         READWRITE(nDerivationMethod);
55         READWRITE(nDeriveIterations);
56         READWRITE(vchOtherDerivationParameters);
57     }
58
59     CMasterKey()
60     {
61         // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
62         // ie slightly lower than the lowest hardware we need bother supporting
63         nDeriveIterations = 25000;
64         nDerivationMethod = 0;
65         vchOtherDerivationParameters = std::vector<unsigned char>(0);
66     }
67 };
68
69 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
70
71 class CSecureDataStream : public CBaseDataStream<CKeyingMaterial>
72 {
73 public:
74     explicit CSecureDataStream(int nTypeIn, int nVersionIn) : CBaseDataStream(nTypeIn, nVersionIn) { }
75
76     CSecureDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) :
77             CBaseDataStream(pbegin, pend, nTypeIn, nVersionIn) { }
78
79     CSecureDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) :
80             CBaseDataStream(vchIn, nTypeIn, nVersionIn) { }
81 };
82
83 /** Encryption/decryption context with key information */
84 class CCrypter
85 {
86 private:
87     unsigned char chKey[WALLET_CRYPTO_KEY_SIZE];
88     unsigned char chIV[WALLET_CRYPTO_KEY_SIZE];
89     bool fKeySet;
90
91 public:
92     bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
93     bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext);
94     bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext);
95     bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV);
96
97     void CleanKey()
98     {
99         memory_cleanse(chKey, sizeof(chKey));
100         memory_cleanse(chIV, sizeof(chIV));
101         fKeySet = false;
102     }
103
104     CCrypter()
105     {
106         fKeySet = false;
107
108         // Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
109         // Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
110         // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
111         LockedPageManager::Instance().LockRange(&chKey[0], sizeof chKey);
112         LockedPageManager::Instance().LockRange(&chIV[0], sizeof chIV);
113     }
114
115     ~CCrypter()
116     {
117         CleanKey();
118
119         LockedPageManager::Instance().UnlockRange(&chKey[0], sizeof chKey);
120         LockedPageManager::Instance().UnlockRange(&chIV[0], sizeof chIV);
121     }
122 };
123
124 /** Keystore which keeps the private keys encrypted.
125  * It derives from the basic key store, which is used if no encryption is active.
126  */
127 class CCryptoKeyStore : public CBasicKeyStore
128 {
129 private:
130     CryptedKeyMap mapCryptedKeys;
131     CryptedSpendingKeyMap mapCryptedSpendingKeys;
132
133     CKeyingMaterial vMasterKey;
134
135     //! if fUseCrypto is true, mapKeys and mapSpendingKeys must be empty
136     //! if fUseCrypto is false, vMasterKey must be empty
137     bool fUseCrypto;
138
139     //! keeps track of whether Unlock has run a thorough check before
140     bool fDecryptionThoroughlyChecked;
141
142 protected:
143     bool SetCrypted();
144
145     //! will encrypt previously unencrypted keys
146     bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
147
148     bool Unlock(const CKeyingMaterial& vMasterKeyIn);
149
150 public:
151     CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false)
152     {
153     }
154
155     bool IsCrypted() const
156     {
157         return fUseCrypto;
158     }
159
160     bool IsLocked() const
161     {
162         if (!IsCrypted())
163             return false;
164         bool result;
165         {
166             LOCK(cs_KeyStore);
167             result = vMasterKey.empty();
168         }
169         return result;
170     }
171
172     bool Lock();
173
174     virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
175     bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
176     bool HaveKey(const CKeyID &address) const
177     {
178         {
179             LOCK(cs_KeyStore);
180             if (!IsCrypted())
181                 return CBasicKeyStore::HaveKey(address);
182             return mapCryptedKeys.count(address) > 0;
183         }
184         return false;
185     }
186     bool GetKey(const CKeyID &address, CKey& keyOut) const;
187     bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
188     void GetKeys(std::set<CKeyID> &setAddress) const
189     {
190         if (!IsCrypted())
191         {
192             CBasicKeyStore::GetKeys(setAddress);
193             return;
194         }
195         setAddress.clear();
196         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
197         while (mi != mapCryptedKeys.end())
198         {
199             setAddress.insert((*mi).first);
200             mi++;
201         }
202     }
203     virtual bool AddCryptedSpendingKey(const libzcash::PaymentAddress &address,
204                                        const libzcash::ViewingKey &vk,
205                                        const std::vector<unsigned char> &vchCryptedSecret);
206     bool AddSpendingKey(const libzcash::SpendingKey &sk);
207     bool HaveSpendingKey(const libzcash::PaymentAddress &address) const
208     {
209         {
210             LOCK(cs_KeyStore);
211             if (!IsCrypted())
212                 return CBasicKeyStore::HaveSpendingKey(address);
213             return mapCryptedSpendingKeys.count(address) > 0;
214         }
215         return false;
216     }
217     bool GetSpendingKey(const libzcash::PaymentAddress &address, libzcash::SpendingKey &skOut) const;
218     void GetPaymentAddresses(std::set<libzcash::PaymentAddress> &setAddress) const
219     {
220         if (!IsCrypted())
221         {
222             CBasicKeyStore::GetPaymentAddresses(setAddress);
223             return;
224         }
225         setAddress.clear();
226         CryptedSpendingKeyMap::const_iterator mi = mapCryptedSpendingKeys.begin();
227         while (mi != mapCryptedSpendingKeys.end())
228         {
229             setAddress.insert((*mi).first);
230             mi++;
231         }
232     }
233
234     /**
235      * Wallet status (encrypted, locked) changed.
236      * Note: Called without locks held.
237      */
238     boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
239 };
240
241 #endif // BITCOIN_WALLET_CRYPTER_H
This page took 0.039677 seconds and 4 git commands to generate.