| 685 | } |
| 686 | |
| 687 | bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) |
| 688 | { |
| 689 | if (IsCrypted()) |
| 690 | return false; |
| 691 | |
| 692 | CKeyingMaterial _vMasterKey; |
| 693 | |
| 694 | _vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE); |
| 695 | GetRandBytes(&_vMasterKey[0], WALLET_CRYPTO_KEY_SIZE); |
| 696 | |
| 697 | CMasterKey kMasterKey; |
| 698 | |
| 699 | kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE); |
| 700 | GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE); |
| 701 | |
| 702 | CCrypter crypter; |
| 703 | int64_t nStartTime = GetTimeMillis(); |
| 704 | crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod); |
| 705 | kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime)); |
| 706 | |
| 707 | nStartTime = GetTimeMillis(); |
| 708 | crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod); |
| 709 | kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2; |
| 710 | |
| 711 | if (kMasterKey.nDeriveIterations < 25000) |
| 712 | kMasterKey.nDeriveIterations = 25000; |
| 713 | |
| 714 | LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations); |
| 715 | |
| 716 | if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod)) |
| 717 | return false; |
| 718 | if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey)) |
| 719 | return false; |
| 720 | |
| 721 | { |
| 722 | LOCK(cs_wallet); |
| 723 | mapMasterKeys[++nMasterKeyMaxID] = kMasterKey; |
| 724 | if (fFileBacked) { |
| 725 | assert(!pwalletdbEncryption); |
| 726 | pwalletdbEncryption = new CWalletDB(strWalletFile); |
| 727 | if (!pwalletdbEncryption->TxnBegin()) { |
| 728 | delete pwalletdbEncryption; |
| 729 | pwalletdbEncryption = NULL; |
| 730 | return false; |
| 731 | } |
| 732 | pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey); |
| 733 | } |
| 734 | // must get current HD chain before EncryptKeys |
| 735 | CHDChain hdChainCurrent; |
| 736 | GetHDChain(hdChainCurrent); |
| 737 | |
| 738 | if (!EncryptKeys(_vMasterKey)) { |
| 739 | if (fFileBacked) { |
| 740 | pwalletdbEncryption->TxnAbort(); |
| 741 | delete pwalletdbEncryption; |
| 742 | } |
| 743 | // We now probably have half of our keys encrypted in memory, and half not... |
| 744 | // die and let the user reload their unencrypted wallet. |
no test coverage detected