| 679 | } |
| 680 | |
| 681 | bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) |
| 682 | { |
| 683 | if (IsCrypted()) |
| 684 | return false; |
| 685 | |
| 686 | CKeyingMaterial _vMasterKey; |
| 687 | |
| 688 | _vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE); |
| 689 | GetStrongRandBytes(_vMasterKey.data(), WALLET_CRYPTO_KEY_SIZE); |
| 690 | |
| 691 | CMasterKey kMasterKey; |
| 692 | |
| 693 | kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE); |
| 694 | GetStrongRandBytes(kMasterKey.vchSalt.data(), WALLET_CRYPTO_SALT_SIZE); |
| 695 | |
| 696 | CCrypter crypter; |
| 697 | int64_t nStartTime = GetTimeMillis(); |
| 698 | crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod); |
| 699 | kMasterKey.nDeriveIterations = static_cast<unsigned int>(2500000 / ((double)(GetTimeMillis() - nStartTime))); |
| 700 | |
| 701 | nStartTime = GetTimeMillis(); |
| 702 | crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod); |
| 703 | kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2; |
| 704 | |
| 705 | if (kMasterKey.nDeriveIterations < 25000) |
| 706 | kMasterKey.nDeriveIterations = 25000; |
| 707 | |
| 708 | WalletLogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations); |
| 709 | |
| 710 | if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod)) |
| 711 | return false; |
| 712 | if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey)) |
| 713 | return false; |
| 714 | |
| 715 | { |
| 716 | LOCK(cs_wallet); |
| 717 | mapMasterKeys[++nMasterKeyMaxID] = kMasterKey; |
| 718 | WalletBatch* encrypted_batch = new WalletBatch(GetDatabase()); |
| 719 | if (!encrypted_batch->TxnBegin()) { |
| 720 | delete encrypted_batch; |
| 721 | encrypted_batch = nullptr; |
| 722 | return false; |
| 723 | } |
| 724 | encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey); |
| 725 | |
| 726 | for (const auto& spk_man_pair : m_spk_managers) { |
| 727 | auto spk_man = spk_man_pair.second.get(); |
| 728 | if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) { |
| 729 | encrypted_batch->TxnAbort(); |
| 730 | delete encrypted_batch; |
| 731 | encrypted_batch = nullptr; |
| 732 | // We now probably have half of our keys encrypted in memory, and half not... |
| 733 | // die and let the user reload the unencrypted wallet. |
| 734 | assert(false); |
| 735 | } |
| 736 | } |
| 737 | |
| 738 | // Encryption was introduced in version 0.4.0 |
no test coverage detected