static bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext) { CCrypter cKeyCrypter; std::vector<unsigned char> chIV(WALLET_CRYPTO_IV_SIZE); memcpy(chIV.data(), &nIV, WALLET_CRYPTO_IV_SIZE); if(!cKeyCrypter.SetKey(vMasterKey, chIV)) return false; return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext); }
bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CSecret& vchPlaintext) { CCrypter cKeyCrypter; std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE); memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); if(!cKeyCrypter.SetKey(vMasterKey, chIV)) return false; return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext)); }
static void TestPassphraseSingle(const std::vector<unsigned char>& vchSalt, const SecureString& passphrase, uint32_t rounds, const std::vector<unsigned char>& correctKey = std::vector<unsigned char>(), const std::vector<unsigned char>& correctIV=std::vector<unsigned char>()) { CCrypter crypt; crypt.SetKeyFromPassphrase(passphrase, vchSalt, rounds, 0); if(!correctKey.empty()) BOOST_CHECK_MESSAGE(memcmp(crypt.vchKey.data(), correctKey.data(), crypt.vchKey.size()) == 0, \ HexStr(crypt.vchKey.begin(), crypt.vchKey.end()) + std::string(" != ") + HexStr(correctKey.begin(), correctKey.end())); if(!correctIV.empty()) BOOST_CHECK_MESSAGE(memcmp(crypt.vchIV.data(), correctIV.data(), crypt.vchIV.size()) == 0, HexStr(crypt.vchIV.begin(), crypt.vchIV.end()) + std::string(" != ") + HexStr(correctIV.begin(), correctIV.end())); }
bool WalletUtilityDB::DecryptSecret(const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext) { CCrypter cKeyCrypter; std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE); memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); BOOST_FOREACH(const CKeyingMaterial vMKey, vMKeys) { if(!cKeyCrypter.SetKey(vMKey, chIV)) continue; if (cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext))) return true; } return false; }
bool WalletUtilityDB::Unlock() { CCrypter crypter; CKeyingMaterial vMasterKey; BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys) { if(!crypter.SetKeyFromPassphrase(mPass, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) return false; if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) continue; // try another master key vMKeys.push_back(vMasterKey); } return true; }
static void TestDecrypt(const CCrypter& crypt, const std::vector<unsigned char>& vchCiphertext, \ const std::vector<unsigned char>& vchPlaintext = std::vector<unsigned char>()) { CKeyingMaterial vchDecrypted; crypt.Decrypt(vchCiphertext, vchDecrypted); if (vchPlaintext.size()) BOOST_CHECK(CKeyingMaterial(vchPlaintext.begin(), vchPlaintext.end()) == vchDecrypted); }
static void TestEncryptSingle(const CCrypter& crypt, const CKeyingMaterial& vchPlaintext, const std::vector<unsigned char>& vchCiphertextCorrect = std::vector<unsigned char>()) { std::vector<unsigned char> vchCiphertext; crypt.Encrypt(vchPlaintext, vchCiphertext); if (!vchCiphertextCorrect.empty()) BOOST_CHECK(vchCiphertext == vchCiphertextCorrect); const std::vector<unsigned char> vchPlaintext2(vchPlaintext.begin(), vchPlaintext.end()); TestDecrypt(crypt, vchCiphertext, vchPlaintext2); }
bool CWallet::Unlock(const SecureString& strWalletPassphrase) { if (!IsLocked()) return false; CCrypter crypter; CKeyingMaterial vMasterKey; { LOCK(cs_wallet); BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys) { if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) return false; if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) return false; if (CCryptoKeyStore::Unlock(vMasterKey)) return true; } } return false; }
static void TestPassphraseSingle(const std::vector<unsigned char>& vchSalt, const SecureString& passphrase, uint32_t rounds, const std::vector<unsigned char>& correctKey = std::vector<unsigned char>(), const std::vector<unsigned char>& correctIV=std::vector<unsigned char>()) { unsigned char chKey[WALLET_CRYPTO_KEY_SIZE]; unsigned char chIV[WALLET_CRYPTO_IV_SIZE]; CCrypter crypt; crypt.SetKeyFromPassphrase(passphrase, vchSalt, rounds, 0); OldSetKeyFromPassphrase(passphrase, vchSalt, rounds, 0, chKey, chIV); BOOST_CHECK_MESSAGE(memcmp(chKey, crypt.vchKey.data(), crypt.vchKey.size()) == 0, \ HexStr(chKey, chKey+sizeof(chKey)) + std::string(" != ") + HexStr(crypt.vchKey)); BOOST_CHECK_MESSAGE(memcmp(chIV, crypt.vchIV.data(), crypt.vchIV.size()) == 0, \ HexStr(chIV, chIV+sizeof(chIV)) + std::string(" != ") + HexStr(crypt.vchIV)); if(!correctKey.empty()) BOOST_CHECK_MESSAGE(memcmp(chKey, &correctKey[0], sizeof(chKey)) == 0, \ HexStr(chKey, chKey+sizeof(chKey)) + std::string(" != ") + HexStr(correctKey.begin(), correctKey.end())); if(!correctIV.empty()) BOOST_CHECK_MESSAGE(memcmp(chIV, &correctIV[0], sizeof(chIV)) == 0, HexStr(chIV, chIV+sizeof(chIV)) + std::string(" != ") + HexStr(correctIV.begin(), correctIV.end())); }
static void TestEncryptSingle(const CCrypter& crypt, const CKeyingMaterial& vchPlaintext, const std::vector<unsigned char>& vchCiphertextCorrect = std::vector<unsigned char>()) { std::vector<unsigned char> vchCiphertext1; std::vector<unsigned char> vchCiphertext2; int result1 = crypt.Encrypt(vchPlaintext, vchCiphertext1); int result2 = OldEncrypt(vchPlaintext, vchCiphertext2, crypt.vchKey.data(), crypt.vchIV.data()); BOOST_CHECK(result1 == result2); BOOST_CHECK(vchCiphertext1 == vchCiphertext2); if (!vchCiphertextCorrect.empty()) BOOST_CHECK(vchCiphertext2 == vchCiphertextCorrect); const std::vector<unsigned char> vchPlaintext2(vchPlaintext.begin(), vchPlaintext.end()); if(vchCiphertext1 == vchCiphertext2) TestDecrypt(crypt, vchCiphertext1, vchPlaintext2); }
bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase) { bool fWasLocked = IsLocked(); { LOCK(cs_wallet); Lock(); CCrypter crypter; CKeyingMaterial vMasterKey; BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys) { if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) return false; if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) return false; if (CCryptoKeyStore::Unlock(vMasterKey)) { int64 nStartTime = GetTimeMillis(); crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod); pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime))); nStartTime = GetTimeMillis(); crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod); pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2; if (pMasterKey.second.nDeriveIterations < 25000) pMasterKey.second.nDeriveIterations = 25000; printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations); if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) return false; if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey)) return false; CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second); if (fWasLocked) Lock(); return true; } } } return false; }
static void TestDecrypt(const CCrypter& crypt, const std::vector<unsigned char>& vchCiphertext, \ const std::vector<unsigned char>& vchPlaintext = std::vector<unsigned char>()) { CKeyingMaterial vchDecrypted1; CKeyingMaterial vchDecrypted2; int result1, result2; result1 = crypt.Decrypt(vchCiphertext, vchDecrypted1); result2 = OldDecrypt(vchCiphertext, vchDecrypted2, crypt.vchKey.data(), crypt.vchIV.data()); BOOST_CHECK(result1 == result2); // These two should be equal. However, OpenSSL 1.0.1j introduced a change // that would zero all padding except for the last byte for failed decrypts. // This behavior was reverted for 1.0.1k. if (vchDecrypted1 != vchDecrypted2 && vchDecrypted1.size() >= AES_BLOCK_SIZE && SSLeay() == 0x100010afL) { for(CKeyingMaterial::iterator it = vchDecrypted1.end() - AES_BLOCK_SIZE; it != vchDecrypted1.end() - 1; it++) *it = 0; } BOOST_CHECK_MESSAGE(vchDecrypted1 == vchDecrypted2, HexStr(vchDecrypted1.begin(), vchDecrypted1.end()) + " != " + HexStr(vchDecrypted2.begin(), vchDecrypted2.end())); if (vchPlaintext.size()) BOOST_CHECK(CKeyingMaterial(vchPlaintext.begin(), vchPlaintext.end()) == vchDecrypted2); }
int main(int argc, char* argv[]) { if (argc != 7){ printf("Hashchecker needs to know the cryptographic details of your wallet!\nUsage: hashchecker pw_to_permute iterations salt crypted_key public_key crypted_secret\n"); return 1; } CCrypter crypter; CKeyingMaterial vMasterKey; // Try any password as input SecureString attempt = argv[1]; const unsigned int nDeriveIterations = atoi(argv[2]);//29731; const vector<unsigned char> chSalt = Convert(argv[3]);//"b29a2e128e8e0a2f");//argv[1]; const vector<unsigned char> vchCryptedKey = Convert(argv[4]);//"982a07407ccb8d70514e7b7ccae4b53d68318ec41fd2bf99bf9dbcafd2f150a92c6eb8f9ea743b782fc5b85403421c1d");//argv[2]; const vector<unsigned char> vchPubKey = Convert(argv[5]);//"03fefd771544971f3ab95b041bbce02cc799a335d0d12c3bcd46c7c61a4e3ba897"); const vector<unsigned char> vchCryptedSecret = Convert(argv[6]);//"17169083a74b07ff3497027af7423b9aec1593c90f15a57f52c368593947c85e37b03430840ad48ef409e97ba5a4cdeb"); double count = Factorial(attempt.size()); bool found = false; for (int i = 0; i <= count; i++) { if (i > 0) {//test the word as typed in on first iteration permutation(i-1, attempt); } const SecureString strWalletPassphrase = attempt; cout << i << "-" << strWalletPassphrase <<"\n"; if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, chSalt, nDeriveIterations, 0)) { cout << i << " " << strWalletPassphrase <<"\n"; continue; } if (!crypter.Decrypt(vchCryptedKey, vMasterKey)) { cout << i << " " << strWalletPassphrase <<"\n"; continue; } CSecret vchSecret; if(!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret)) { cout << "** didn't decrypt **" <<"\n"; continue; } if (vchSecret.size() != 32) { cout << "** wrong size secret **" <<"\n"; continue; } CKey key; key.SetPubKey(vchPubKey); key.SetSecret(vchSecret); if (key.GetPubKey() == vchPubKey) { cout<<"Found one: "<<strWalletPassphrase<<"\n"; found = true; break; } // else // cout << "** didn't get the pubkey back **\n"; } if (found) cout << "Found it! Congratulations\n"; return 0; }