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