Master Core  v0.0.9 - 49a5c0d97abf09ef2911ddfe8d9551df59f9efd3-dirty
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 "script.h"
8 
9 #include <string>
10 #include <vector>
11 #include <boost/foreach.hpp>
12 #include <openssl/aes.h>
13 #include <openssl/evp.h>
14 
15 bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
16 {
17  if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
18  return false;
19 
20  int i = 0;
21  if (nDerivationMethod == 0)
22  i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
23  (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV);
24 
25  if (i != (int)WALLET_CRYPTO_KEY_SIZE)
26  {
27  OPENSSL_cleanse(chKey, sizeof(chKey));
28  OPENSSL_cleanse(chIV, sizeof(chIV));
29  return false;
30  }
31 
32  fKeySet = true;
33  return true;
34 }
35 
36 bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV)
37 {
38  if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE)
39  return false;
40 
41  memcpy(&chKey[0], &chNewKey[0], sizeof chKey);
42  memcpy(&chIV[0], &chNewIV[0], sizeof chIV);
43 
44  fKeySet = true;
45  return true;
46 }
47 
48 bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext)
49 {
50  if (!fKeySet)
51  return false;
52 
53  // max ciphertext len for a n bytes of plaintext is
54  // n + AES_BLOCK_SIZE - 1 bytes
55  int nLen = vchPlaintext.size();
56  int nCLen = nLen + AES_BLOCK_SIZE, nFLen = 0;
57  vchCiphertext = std::vector<unsigned char> (nCLen);
58 
59  EVP_CIPHER_CTX ctx;
60 
61  bool fOk = true;
62 
63  EVP_CIPHER_CTX_init(&ctx);
64  if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
65  if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen);
66  if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen);
67  EVP_CIPHER_CTX_cleanup(&ctx);
68 
69  if (!fOk) return false;
70 
71  vchCiphertext.resize(nCLen + nFLen);
72  return true;
73 }
74 
75 bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext)
76 {
77  if (!fKeySet)
78  return false;
79 
80  // plaintext will always be equal to or lesser than length of ciphertext
81  int nLen = vchCiphertext.size();
82  int nPLen = nLen, nFLen = 0;
83 
84  vchPlaintext = CKeyingMaterial(nPLen);
85 
86  EVP_CIPHER_CTX ctx;
87 
88  bool fOk = true;
89 
90  EVP_CIPHER_CTX_init(&ctx);
91  if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
92  if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen);
93  if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen);
94  EVP_CIPHER_CTX_cleanup(&ctx);
95 
96  if (!fOk) return false;
97 
98  vchPlaintext.resize(nPLen + nFLen);
99  return true;
100 }
101 
102 
103 bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext)
104 {
105  CCrypter cKeyCrypter;
106  std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
107  memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE);
108  if(!cKeyCrypter.SetKey(vMasterKey, chIV))
109  return false;
110  return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext);
111 }
112 
113 bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
114 {
115  CCrypter cKeyCrypter;
116  std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
117  memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE);
118  if(!cKeyCrypter.SetKey(vMasterKey, chIV))
119  return false;
120  return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext));
121 }
122 
124 {
125  LOCK(cs_KeyStore);
126  if (fUseCrypto)
127  return true;
128  if (!mapKeys.empty())
129  return false;
130  fUseCrypto = true;
131  return true;
132 }
133 
135 {
136  if (!SetCrypted())
137  return false;
138 
139  {
140  LOCK(cs_KeyStore);
141  vMasterKey.clear();
142  }
143 
144  NotifyStatusChanged(this);
145  return true;
146 }
147 
148 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
149 {
150  {
151  LOCK(cs_KeyStore);
152  if (!SetCrypted())
153  return false;
154 
155  CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
156  for (; mi != mapCryptedKeys.end(); ++mi)
157  {
158  const CPubKey &vchPubKey = (*mi).second.first;
159  const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
160  CKeyingMaterial vchSecret;
161  if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
162  return false;
163  if (vchSecret.size() != 32)
164  return false;
165  CKey key;
166  key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
167  if (key.GetPubKey() == vchPubKey)
168  break;
169  return false;
170  }
171  vMasterKey = vMasterKeyIn;
172  }
173  NotifyStatusChanged(this);
174  return true;
175 }
176 
177 bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
178 {
179  {
180  LOCK(cs_KeyStore);
181  if (!IsCrypted())
182  return CBasicKeyStore::AddKeyPubKey(key, pubkey);
183 
184  if (IsLocked())
185  return false;
186 
187  std::vector<unsigned char> vchCryptedSecret;
188  CKeyingMaterial vchSecret(key.begin(), key.end());
189  if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret))
190  return false;
191 
192  if (!AddCryptedKey(pubkey, vchCryptedSecret))
193  return false;
194  }
195  return true;
196 }
197 
198 
199 bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
200 {
201  {
202  LOCK(cs_KeyStore);
203  if (!SetCrypted())
204  return false;
205 
206  mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
207  }
208  return true;
209 }
210 
211 bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
212 {
213  {
214  LOCK(cs_KeyStore);
215  if (!IsCrypted())
216  return CBasicKeyStore::GetKey(address, keyOut);
217 
218  CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
219  if (mi != mapCryptedKeys.end())
220  {
221  const CPubKey &vchPubKey = (*mi).second.first;
222  const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
223  CKeyingMaterial vchSecret;
224  if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
225  return false;
226  if (vchSecret.size() != 32)
227  return false;
228  keyOut.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
229  return true;
230  }
231  }
232  return false;
233 }
234 
235 bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
236 {
237  {
238  LOCK(cs_KeyStore);
239  if (!IsCrypted())
240  return CKeyStore::GetPubKey(address, vchPubKeyOut);
241 
242  CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
243  if (mi != mapCryptedKeys.end())
244  {
245  vchPubKeyOut = (*mi).second.first;
246  return true;
247  }
248  }
249  return false;
250 }
251 
253 {
254  {
255  LOCK(cs_KeyStore);
256  if (!mapCryptedKeys.empty() || IsCrypted())
257  return false;
258 
259  fUseCrypto = true;
260  BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
261  {
262  const CKey &key = mKey.second;
263  CPubKey vchPubKey = key.GetPubKey();
264  CKeyingMaterial vchSecret(key.begin(), key.end());
265  std::vector<unsigned char> vchCryptedSecret;
266  if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
267  return false;
268  if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
269  return false;
270  }
271  mapKeys.clear();
272  }
273  return true;
274 }
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< unsigned char > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
Definition: crypter.cpp:15
bool IsCrypted() const
Definition: crypter.h:137
CCriticalSection cs_KeyStore
Definition: keystore.h:20
const unsigned char * begin() const
Definition: key.h:234
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext)
Definition: crypter.cpp:48
const unsigned int WALLET_CRYPTO_KEY_SIZE
Definition: crypter.h:14
unsigned char chIV[WALLET_CRYPTO_KEY_SIZE]
Definition: crypter.h:71
bool SetKey(const CKeyingMaterial &chNewKey, const std::vector< unsigned char > &chNewIV)
Definition: crypter.cpp:36
Encryption/decryption context with key information.
Definition: crypter.h:67
const unsigned char * end() const
Definition: key.h:235
bool SetCrypted()
Definition: crypter.cpp:123
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
Definition: crypter.h:64
bool EncryptKeys(CKeyingMaterial &vMasterKeyIn)
Definition: crypter.cpp:252
bool IsLocked() const
Definition: crypter.h:142
CKeyingMaterial vMasterKey
Definition: crypter.h:118
virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector< unsigned char > &vchCryptedSecret)
Definition: crypter.cpp:199
bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey)
Definition: keystore.cpp:27
bool GetKey(const CKeyID &address, CKey &keyOut) const
Definition: crypter.cpp:211
bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
Definition: crypter.cpp:235
boost::signals2::signal< void(CCryptoKeyStore *wallet)> NotifyStatusChanged
Definition: crypter.h:189
bool GetKey(const CKeyID &address, CKey &keyOut) const
Definition: keystore.h:75
virtual bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
Definition: keystore.cpp:14
CPubKey GetPubKey() const
Definition: key.cpp:388
#define LOCK(cs)
Definition: sync.h:156
bool fKeySet
Definition: crypter.h:72
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: allocators.h:253
An encapsulated public key.
Definition: key.h:42
bool Unlock(const CKeyingMaterial &vMasterKeyIn)
Definition: crypter.cpp:148
bool Decrypt(const std::vector< unsigned char > &vchCiphertext, CKeyingMaterial &vchPlaintext)
Definition: crypter.cpp:75
uint256 GetHash() const
Definition: key.h:136
bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey)
Definition: crypter.cpp:177
void Set(const T pbegin, const T pend, bool fCompressedIn)
Definition: key.h:218
unsigned char chKey[WALLET_CRYPTO_KEY_SIZE]
Definition: crypter.h:70
KeyMap mapKeys
Definition: keystore.h:48
bool IsCompressed() const
Definition: key.h:151
256-bit unsigned integer
Definition: uint256.h:531
const unsigned int WALLET_CRYPTO_SALT_SIZE
Definition: crypter.h:15
CryptedKeyMap mapCryptedKeys
Definition: crypter.h:116
void * memcpy(void *a, const void *b, size_t c)
Definition: glibc_compat.cpp:7
bool DecryptSecret(const CKeyingMaterial &vMasterKey, const std::vector< unsigned char > &vchCiphertext, const uint256 &nIV, CKeyingMaterial &vchPlaintext)
Definition: crypter.cpp:113
A reference to a CKey: the Hash160 of its serialized public key.
Definition: key.h:26
bool EncryptSecret(const CKeyingMaterial &vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256 &nIV, std::vector< unsigned char > &vchCiphertext)
Definition: crypter.cpp:103
bool fUseCrypto
Definition: crypter.h:122
An encapsulated private key.
Definition: key.h:179
CKeyID GetID() const
Definition: key.h:131