1 // Copyright (c) 2009-2013 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.
7 #include "script/script.h"
8 #include "script/standard.h"
13 #include <boost/foreach.hpp>
14 #include <openssl/aes.h>
15 #include <openssl/evp.h>
17 bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
19 if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
23 if (nDerivationMethod == 0)
24 i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
25 (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV);
27 if (i != (int)WALLET_CRYPTO_KEY_SIZE)
29 memory_cleanse(chKey, sizeof(chKey));
30 memory_cleanse(chIV, sizeof(chIV));
38 bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV)
40 if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE)
43 memcpy(&chKey[0], &chNewKey[0], sizeof chKey);
44 memcpy(&chIV[0], &chNewIV[0], sizeof chIV);
50 bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext)
55 // max ciphertext len for a n bytes of plaintext is
56 // n + AES_BLOCK_SIZE - 1 bytes
57 int nLen = vchPlaintext.size();
58 int nCLen = nLen + AES_BLOCK_SIZE, nFLen = 0;
59 vchCiphertext = std::vector<unsigned char> (nCLen);
65 EVP_CIPHER_CTX_init(&ctx);
66 if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0;
67 if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen) != 0;
68 if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0]) + nCLen, &nFLen) != 0;
69 EVP_CIPHER_CTX_cleanup(&ctx);
71 if (!fOk) return false;
73 vchCiphertext.resize(nCLen + nFLen);
77 bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext)
82 // plaintext will always be equal to or lesser than length of ciphertext
83 int nLen = vchCiphertext.size();
84 int nPLen = nLen, nFLen = 0;
86 vchPlaintext = CKeyingMaterial(nPLen);
92 EVP_CIPHER_CTX_init(&ctx);
93 if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0;
94 if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen) != 0;
95 if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0]) + nPLen, &nFLen) != 0;
96 EVP_CIPHER_CTX_cleanup(&ctx);
98 if (!fOk) return false;
100 vchPlaintext.resize(nPLen + nFLen);
105 static bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext)
107 CCrypter cKeyCrypter;
108 std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
109 memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE);
110 if(!cKeyCrypter.SetKey(vMasterKey, chIV))
112 return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext);
115 static bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
117 CCrypter cKeyCrypter;
118 std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
119 memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE);
120 if(!cKeyCrypter.SetKey(vMasterKey, chIV))
122 return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext));
125 static bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key)
127 CKeyingMaterial vchSecret;
128 if(!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
131 if (vchSecret.size() != 32)
134 key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
135 return key.VerifyPubKey(vchPubKey);
138 bool CCryptoKeyStore::SetCrypted()
143 if (!mapKeys.empty())
149 bool CCryptoKeyStore::Lock()
159 NotifyStatusChanged(this);
163 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
170 bool keyPass = false;
171 bool keyFail = false;
172 CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
173 for (; mi != mapCryptedKeys.end(); ++mi)
175 const CPubKey &vchPubKey = (*mi).second.first;
176 const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
178 if (!DecryptKey(vMasterKeyIn, vchCryptedSecret, vchPubKey, key))
184 if (fDecryptionThoroughlyChecked)
187 if (keyPass && keyFail)
189 LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.");
192 if (keyFail || !keyPass)
194 vMasterKey = vMasterKeyIn;
195 fDecryptionThoroughlyChecked = true;
197 NotifyStatusChanged(this);
201 bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
206 return CBasicKeyStore::AddKeyPubKey(key, pubkey);
211 std::vector<unsigned char> vchCryptedSecret;
212 CKeyingMaterial vchSecret(key.begin(), key.end());
213 if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret))
216 if (!AddCryptedKey(pubkey, vchCryptedSecret))
223 bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
230 mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
235 bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
240 return CBasicKeyStore::GetKey(address, keyOut);
242 CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
243 if (mi != mapCryptedKeys.end())
245 const CPubKey &vchPubKey = (*mi).second.first;
246 const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
247 return DecryptKey(vMasterKey, vchCryptedSecret, vchPubKey, keyOut);
253 bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
258 return CKeyStore::GetPubKey(address, vchPubKeyOut);
260 CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
261 if (mi != mapCryptedKeys.end())
263 vchPubKeyOut = (*mi).second.first;
270 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
274 if (!mapCryptedKeys.empty() || IsCrypted())
278 BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
280 const CKey &key = mKey.second;
281 CPubKey vchPubKey = key.GetPubKey();
282 CKeyingMaterial vchSecret(key.begin(), key.end());
283 std::vector<unsigned char> vchCryptedSecret;
284 if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
286 if (!AddCryptedKey(vchPubKey, vchCryptedSecret))