PRCYCoin  2.0.0.7rc1
P2P Digital Currency
crypter.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2013 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "crypter.h"
6 
7 #include "crypto/aes.h"
8 #include "crypto/sha512.h"
9 #include "script/script.h"
10 #include "script/standard.h"
11 #include "util.h"
12 
13 #include <string>
14 #include <vector>
15 
16 int CCrypter::BytesToKeySHA512AES(const std::vector<unsigned char>& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const
17 {
18  // This mimics the behavior of openssl's EVP_BytesToKey with an aes256cbc
19  // cipher and sha512 message digest. Because sha512's output size (64b) is
20  // greater than the aes256 block size (16b) + aes256 key size (32b),
21  // there's no need to process more than once (D_0).
22 
23  if(!count || !key || !iv)
24  return 0;
25 
26  unsigned char buf[CSHA512::OUTPUT_SIZE];
27  CSHA512 di;
28 
29  di.Write((const unsigned char*)strKeyData.c_str(), strKeyData.size());
30  if(chSalt.size())
31  di.Write(&chSalt[0], chSalt.size());
32  di.Finalize(buf);
33 
34  for(int i = 0; i != count - 1; i++)
35  di.Reset().Write(buf, sizeof(buf)).Finalize(buf);
36 
39  memory_cleanse(buf, sizeof(buf));
41 }
42 
43 bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
44 {
45  if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
46  return false;
47 
48  int i = 0;
49  if (nDerivationMethod == 0)
50  i = BytesToKeySHA512AES(chSalt, strKeyData, nRounds, chKey, chIV);
51 
52  if (i != (int)WALLET_CRYPTO_KEY_SIZE) {
53  memory_cleanse(chKey, sizeof(chKey));
54  memory_cleanse(chIV, sizeof(chIV));
55  return false;
56  }
57 
58  fKeySet = true;
59  return true;
60 }
61 
62 bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV)
63 {
64  if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_IV_SIZE)
65  return false;
66 
67  memcpy(&chKey[0], &chNewKey[0], sizeof chKey);
68  memcpy(&chIV[0], &chNewIV[0], sizeof chIV);
69 
70  fKeySet = true;
71  return true;
72 }
73 
74 bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char>& vchCiphertext) const
75 {
76  if (!fKeySet)
77  return false;
78 
79  // max ciphertext len for a n bytes of plaintext is
80  // n + AES_BLOCKSIZE bytes
81  vchCiphertext.resize(vchPlaintext.size() + AES_BLOCKSIZE);
82 
83  AES256CBCEncrypt enc(chKey, chIV, true);
84  size_t nLen = enc.Encrypt(&vchPlaintext[0], vchPlaintext.size(), &vchCiphertext[0]);
85  if(nLen < vchPlaintext.size())
86  return false;
87  vchCiphertext.resize(nLen);
88  return true;
89 }
90 
91 bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext) const
92 {
93  if (!fKeySet)
94  return false;
95 
96  // plaintext will always be equal to or lesser than length of ciphertext
97  int nLen = vchCiphertext.size();
98  vchPlaintext.resize(nLen);
99  AES256CBCDecrypt dec(chKey, chIV, true);
100  nLen = dec.Decrypt(&vchCiphertext[0], vchCiphertext.size(), &vchPlaintext[0]);
101  if(nLen == 0)
102  return false;
103  vchPlaintext.resize(nLen);
104  return true;
105 }
106 
107 bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial& vchPlaintext, const uint256& nIV, std::vector<unsigned char>& vchCiphertext)
108 {
109  CCrypter cKeyCrypter;
110  std::vector<unsigned char> chIV(WALLET_CRYPTO_IV_SIZE);
111  memcpy(&chIV[0], &nIV, WALLET_CRYPTO_IV_SIZE);
112  if (!cKeyCrypter.SetKey(vMasterKey, chIV))
113  return false;
114  return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext);
115 }
116 
117 bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
118 {
119  CCrypter cKeyCrypter;
120  std::vector<unsigned char> chIV(WALLET_CRYPTO_IV_SIZE);
121  memcpy(&chIV[0], &nIV, WALLET_CRYPTO_IV_SIZE);
122  if (!cKeyCrypter.SetKey(vMasterKey, chIV))
123  return false;
124  return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext));
125 }
126 
128 {
129  LOCK(cs_KeyStore);
130  if (fUseCrypto)
131  return true;
132  if (!mapKeys.empty())
133  return false;
134  fUseCrypto = true;
135  return true;
136 }
137 
138 bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey& pubkey)
139 {
140  {
141  LOCK(cs_KeyStore);
142  if (!IsCrypted())
143  return CBasicKeyStore::AddKeyPubKey(key, pubkey);
144 
145  if (IsLocked())
146  return false;
147 
148  std::vector<unsigned char> vchCryptedSecret;
149  CKeyingMaterial vchSecret(key.begin(), key.end());
150  if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret))
151  return false;
152 
153  if (!AddCryptedKey(pubkey, vchCryptedSecret))
154  return false;
155  }
156  return true;
157 }
158 
159 
160 bool CCryptoKeyStore::AddCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret)
161 {
162  {
163  LOCK(cs_KeyStore);
164  if (!SetCrypted())
165  return false;
166 
167  mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
168  }
169  return true;
170 }
171 
172 bool CCryptoKeyStore::GetKey(const CKeyID& address, CKey& keyOut) const
173 {
174  {
175  LOCK(cs_KeyStore);
176  if (!IsCrypted())
177  return CBasicKeyStore::GetKey(address, keyOut);
178 
179  CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
180  if (mi != mapCryptedKeys.end()) {
181  const CPubKey& vchPubKey = (*mi).second.first;
182  const std::vector<unsigned char>& vchCryptedSecret = (*mi).second.second;
183  CKeyingMaterial vchSecret;
184  if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
185  return false;
186  if (vchSecret.size() != 32)
187  return false;
188  keyOut.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
189  return true;
190  }
191  }
192  return false;
193 }
194 
195 bool CCryptoKeyStore::GetPubKey(const CKeyID& address, CPubKey& vchPubKeyOut) const
196 {
197  {
198  LOCK(cs_KeyStore);
199  if (!IsCrypted())
200  return CKeyStore::GetPubKey(address, vchPubKeyOut);
201 
202  CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
203  if (mi != mapCryptedKeys.end()) {
204  vchPubKeyOut = (*mi).second.first;
205  return true;
206  }
207  }
208  return false;
209 }
210 
212 {
213  {
214  LOCK(cs_KeyStore);
215  if (!mapCryptedKeys.empty() || IsCrypted())
216  return false;
217 
218  fUseCrypto = true;
219  for (KeyMap::value_type& mKey : mapKeys) {
220  const CKey& key = mKey.second;
221  CPubKey vchPubKey = key.GetPubKey();
222  CKeyingMaterial vchSecret(key.begin(), key.end());
223  std::vector<unsigned char> vchCryptedSecret;
224  if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
225  return false;
226  if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
227  return false;
228  }
229  mapKeys.clear();
230  }
231  return true;
232 }
233 
235 {
236  // should call EncryptKeys first
237  if (!IsCrypted())
238  return false;
239 
240  if (!cryptedHDChain.IsNull())
241  return true;
242 
244  return true;
245 
246  // make sure seed matches this chain
247  if (hdChain.GetID() != hdChain.GetSeedHash())
248  return false;
249 
250  std::vector<unsigned char> vchCryptedSeed;
251  if (!EncryptSecret(vMasterKeyIn, hdChain.GetSeed(), hdChain.GetID(), vchCryptedSeed))
252  return false;
253 
254  // hdChain.Debug(__func__);
257 
258  SecureVector vchSecureCryptedSeed(vchCryptedSeed.begin(), vchCryptedSeed.end());
259  if (!cryptedHDChain.SetSeed(vchSecureCryptedSeed, false))
260  return false;
261 
262  SecureVector vchMnemonic;
263  SecureVector vchMnemonicPassphrase;
264 
265  // it's ok to have no mnemonic if wallet was initialized via hdseed
266  if (hdChain.GetMnemonic(vchMnemonic, vchMnemonicPassphrase)) {
267  std::vector<unsigned char> vchCryptedMnemonic;
268  std::vector<unsigned char> vchCryptedMnemonicPassphrase;
269 
270  if (!vchMnemonic.empty() && !EncryptSecret(vMasterKeyIn, vchMnemonic, hdChain.GetID(), vchCryptedMnemonic))
271  return false;
272  if (!vchMnemonicPassphrase.empty() && !EncryptSecret(vMasterKeyIn, vchMnemonicPassphrase, hdChain.GetID(), vchCryptedMnemonicPassphrase))
273  return false;
274 
275  SecureVector vchSecureCryptedMnemonic(vchCryptedMnemonic.begin(), vchCryptedMnemonic.end());
276  SecureVector vchSecureCryptedMnemonicPassphrase(vchCryptedMnemonicPassphrase.begin(), vchCryptedMnemonicPassphrase.end());
277  if (!cryptedHDChain.SetMnemonic(vchSecureCryptedMnemonic, vchSecureCryptedMnemonicPassphrase, false))
278  return false;
279  }
280 
281  if (!hdChain.SetNull())
282  return false;
283 
284  return true;
285 }
286 
288 {
289  if (!IsCrypted())
290  return true;
291  if (cryptedHDChain.IsNull())
292  return false;
293  if (!cryptedHDChain.IsCrypted())
294  return false;
295  SecureVector vchSecureSeed;
296  SecureVector vchSecureCryptedSeed = cryptedHDChain.GetSeed();
297  std::vector<unsigned char> vchCryptedSeed(vchSecureCryptedSeed.begin(), vchSecureCryptedSeed.end());
298  if (!DecryptSecret(vMasterKey, vchCryptedSeed, cryptedHDChain.GetID(), vchSecureSeed))
299  return false;
300 
301  hdChainRet = cryptedHDChain;
302  if (!hdChainRet.SetSeed(vchSecureSeed, false))
303  return false;
304 
305  // hash of decrypted seed must match chain id
306  if (hdChainRet.GetSeedHash() != cryptedHDChain.GetID())
307  return false;
308 
309  SecureVector vchSecureCryptedMnemonic;
310  SecureVector vchSecureCryptedMnemonicPassphrase;
311 
312  // it's ok to have no mnemonic if wallet was initialized via hdseed
313  if (cryptedHDChain.GetMnemonic(vchSecureCryptedMnemonic, vchSecureCryptedMnemonicPassphrase)) {
314  SecureVector vchSecureMnemonic;
315  SecureVector vchSecureMnemonicPassphrase;
316 
317  std::vector<unsigned char> vchCryptedMnemonic(vchSecureCryptedMnemonic.begin(), vchSecureCryptedMnemonic.end());
318  std::vector<unsigned char> vchCryptedMnemonicPassphrase(vchSecureCryptedMnemonicPassphrase.begin(), vchSecureCryptedMnemonicPassphrase.end());
319 
320  if (!vchCryptedMnemonic.empty() && !DecryptSecret(vMasterKey, vchCryptedMnemonic, cryptedHDChain.GetID(), vchSecureMnemonic))
321  return false;
322  if (!vchCryptedMnemonicPassphrase.empty() && !DecryptSecret(vMasterKey, vchCryptedMnemonicPassphrase, cryptedHDChain.GetID(), vchSecureMnemonicPassphrase))
323  return false;
324  if (!hdChainRet.SetMnemonic(vchSecureMnemonic, vchSecureMnemonicPassphrase, false))
325  return false;
326  }
327 
328  hdChainRet.SetCrypted(false);
329  // hdChainRet.Debug(__func__);
330 
331  return true;
332 }
333 
335 {
336  if (IsCrypted())
337  return false;
338 
339  if (chain.IsCrypted())
340  return false;
341 
342  hdChain = chain;
343  return true;
344 }
345 
347 {
348  if (!SetCrypted())
349  return false;
350 
351  if (!chain.IsCrypted())
352  return false;
353 
354  cryptedHDChain = chain;
355  return true;
356 }
357 
358 bool CCryptoKeyStore::GetHDChain(CHDChain& hdChainRet) const
359 {
360  if(IsCrypted()) {
361  hdChainRet = cryptedHDChain;
362  return !cryptedHDChain.IsNull();
363  }
364 
365  hdChainRet = hdChain;
366  return !hdChain.IsNull();
367 }
CHDChain::GetID
uint256 GetID() const
Definition: hdchain.h:85
crypter.h
WALLET_CRYPTO_KEY_SIZE
const unsigned int WALLET_CRYPTO_KEY_SIZE
Definition: crypter.h:14
CCryptoKeyStore::EncryptHDChain
bool EncryptHDChain(const CKeyingMaterial &vMasterKeyIn)
Definition: crypter.cpp:234
CCryptoKeyStore::SetCrypted
bool SetCrypted()
Definition: crypter.cpp:127
EncryptSecret
bool EncryptSecret(const CKeyingMaterial &vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256 &nIV, std::vector< unsigned char > &vchCiphertext)
Definition: crypter.cpp:107
CHDChain::GetSeedHash
uint256 GetSeedHash()
Definition: hdchain.cpp:139
CHDChain::IsNull
bool IsNull() const
Definition: hdchain.cpp:23
CCryptoKeyStore::cryptedHDChain
CHDChain cryptedHDChain
Definition: crypter.h:149
CCrypter::fKeySet
bool fKeySet
Definition: crypter.h:83
CCrypter::Encrypt
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext) const
Definition: crypter.cpp:74
CCryptoKeyStore::SetHDChain
bool SetHDChain(const CHDChain &chain)
Definition: crypter.cpp:334
CCryptoKeyStore::GetKey
bool GetKey(const CKeyID &address, CKey &keyOut) const
Definition: crypter.cpp:172
CKeyingMaterial
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
Definition: crypter.h:69
CKey::Set
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:83
sha512.h
CCrypter::Decrypt
bool Decrypt(const std::vector< unsigned char > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
Definition: crypter.cpp:91
memcpy
void * memcpy(void *a, const void *b, size_t c)
Definition: glibc_compat.cpp:15
CKeyStore::GetPubKey
virtual bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
Definition: keystore.cpp:13
CKeyID
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:29
CHDChain::GetSeed
SecureVector GetSeed() const
Definition: hdchain.cpp:134
memory_cleanse
void memory_cleanse(void *ptr, size_t len)
Definition: cleanse.cpp:27
CKeyStore::cs_KeyStore
RecursiveMutex cs_KeyStore
Definition: keystore.h:24
DecryptSecret
bool DecryptSecret(const CKeyingMaterial &vMasterKey, const std::vector< unsigned char > &vchCiphertext, const uint256 &nIV, CKeyingMaterial &vchPlaintext)
Definition: crypter.cpp:117
CHDChain::SetMnemonic
bool SetMnemonic(const SecureVector &vchMnemonic, const SecureVector &vchMnemonicPassphrase, bool fUpdateID)
Definition: hdchain.cpp:65
CCryptoKeyStore::AddKeyPubKey
bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey)
Add a key to the store.
Definition: crypter.cpp:138
CKey::end
const unsigned char * end() const
Definition: key.h:101
WALLET_CRYPTO_IV_SIZE
const unsigned int WALLET_CRYPTO_IV_SIZE
Definition: crypter.h:16
CSHA512::Finalize
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: sha512.cpp:185
CCrypter::chIV
unsigned char chIV[WALLET_CRYPTO_IV_SIZE]
Definition: crypter.h:82
CKey::begin
const unsigned char * begin() const
Definition: key.h:100
CSHA512::OUTPUT_SIZE
static const size_t OUTPUT_SIZE
Definition: sha512.h:20
CCrypter::BytesToKeySHA512AES
int BytesToKeySHA512AES(const std::vector< unsigned char > &chSalt, const SecureString &strKeyData, int count, unsigned char *key, unsigned char *iv) const
Definition: crypter.cpp:16
AES256CBCDecrypt::Decrypt
int Decrypt(const unsigned char *data, int size, unsigned char *out) const
Definition: aes.cpp:177
CBasicKeyStore::GetKey
bool GetKey(const CKeyID &address, CKey &keyOut) const
Definition: keystore.h:89
CCryptoKeyStore::SetCryptedHDChain
bool SetCryptedHDChain(const CHDChain &chain)
Definition: crypter.cpp:346
CHDChain::SetNull
bool SetNull()
Definition: hdchain.cpp:12
aes.h
CBasicKeyStore::AddKeyPubKey
bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey)
Add a key to the store.
Definition: keystore.cpp:27
AES256CBCDecrypt
Definition: aes.h:79
CSHA512::Reset
CSHA512 & Reset()
Definition: sha512.cpp:202
CHDChain::GetMnemonic
bool GetMnemonic(SecureVector &vchMnemonicRet, SecureVector &vchMnemonicPassphraseRet) const
Definition: hdchain.cpp:100
CPubKey::GetHash
uint256 GetHash() const
Get the 256-bit hash of this public key.
Definition: pubkey.h:149
CCryptoKeyStore::fUseCrypto
bool fUseCrypto
if fUseCrypto is true, mapKeys must be empty if fUseCrypto is false, vMasterKey must be empty
Definition: crypter.h:132
SecureString
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: allocators.h:262
AES256CBCEncrypt
Definition: aes.h:66
CBasicKeyStore::hdChain
CHDChain hdChain
Definition: keystore.h:64
CCrypter::chKey
unsigned char chKey[WALLET_CRYPTO_KEY_SIZE]
Definition: crypter.h:81
standard.h
uint256
256-bit unsigned big integer.
Definition: uint256.h:38
CKey::GetPubKey
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:79
CHDChain::SetCrypted
void SetCrypted(bool fCryptedIn)
Definition: hdchain.cpp:28
CSHA512::Write
CSHA512 & Write(const unsigned char *data, size_t len)
Definition: sha512.cpp:159
CHDChain::IsCrypted
bool IsCrypted() const
Definition: hdchain.cpp:33
CCryptoKeyStore::AddCryptedKey
virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret)
Definition: crypter.cpp:160
CPubKey::IsCompressed
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:168
AES256CBCEncrypt::Encrypt
int Encrypt(const unsigned char *data, int size, unsigned char *out) const
Definition: aes.cpp:160
CPubKey
An encapsulated public key.
Definition: pubkey.h:37
CCrypter::SetKey
bool SetKey(const CKeyingMaterial &chNewKey, const std::vector< unsigned char > &chNewIV)
Definition: crypter.cpp:62
SecureVector
std::vector< unsigned char, secure_allocator< unsigned char > > SecureVector
Definition: allocators.h:267
CHDChain::SetSeed
bool SetSeed(const SecureVector &vchSeedIn, bool fUpdateID)
Definition: hdchain.cpp:123
CKey
An encapsulated private key.
Definition: key.h:39
CCrypter
Encryption/decryption context with key information.
Definition: crypter.h:77
CHDChain
Definition: hdchain.h:11
LOCK
#define LOCK(cs)
Definition: sync.h:182
CCryptoKeyStore::DecryptHDChain
bool DecryptHDChain(CHDChain &hdChainRet) const
Definition: crypter.cpp:287
key
CKey key
Definition: bip38tooldialog.cpp:173
CCryptoKeyStore::GetHDChain
bool GetHDChain(CHDChain &hdChainRet) const
Definition: crypter.cpp:358
CSHA512
A hasher class for SHA-512.
Definition: sha512.h:12
CCryptoKeyStore::mapCryptedKeys
CryptedKeyMap mapCryptedKeys
Definition: crypter.h:148
CCrypter::SetKeyFromPassphrase
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< unsigned char > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
Definition: crypter.cpp:43
CCryptoKeyStore::GetPubKey
bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
Definition: crypter.cpp:195
CCryptoKeyStore::IsCrypted
bool IsCrypted() const
Definition: crypter.h:154
script.h
WALLET_CRYPTO_SALT_SIZE
const unsigned int WALLET_CRYPTO_SALT_SIZE
Definition: crypter.h:15
CBasicKeyStore::mapKeys
KeyMap mapKeys
Definition: keystore.h:60
CCryptoKeyStore::vMasterKey
CKeyingMaterial vMasterKey
Definition: crypter.h:136
util.h
CCryptoKeyStore::IsLocked
bool IsLocked() const
Definition: crypter.h:159
CPubKey::GetID
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:143
CCryptoKeyStore::EncryptKeys
bool EncryptKeys(CKeyingMaterial &vMasterKeyIn)
will encrypt previously unencrypted keys
Definition: crypter.cpp:211