Auto merge of #1569 - str4d:1552-disable-wallet-encryption, r=daira

Disable wallet encryption

Closes #1552
This commit is contained in:
zkbot 2016-10-20 17:01:51 -04:00
commit f90526579b
5 changed files with 48 additions and 2 deletions

View File

@ -14,6 +14,34 @@ make proving keys generated on 64-bit systems unusable on 32-bit and big-endian
systems. It's unclear if a warning will be issued in this case, or if the
proving system will be silently compromised.
Wallet Encryption
-----------------
Wallet encryption is disabled, for several reasons:
- Encrypted wallets are unable to correctly detect shielded spends (due to the
nature of unlinkability of JoinSplits) and can incorrectly show larger
available shielded balances until the next time the wallet is unlocked. This
problem was not limited to failing to recognize the spend; it was possible for
the shown balance to increase by the amount of change from a spend, without
deducting the spent amount.
- While encrypted wallets prevent spending of funds, they do not maintain the
shielding properties of JoinSplits (due to the need to detect spends). That
is, someone with access to an encrypted wallet.dat has full visibility of
your entire transaction graph (other than newly-detected spends, which suffer
from the earlier issue).
- We were concerned about the resistance of the algorithm used to derive wallet
encryption keys (inherited from Bitcoin) to dictionary attacks by a powerful
attacker. If and when we re-enable wallet encryption, it is likely to be with
a modern passphrase-based key derivation algorithm designed for greater
resistance to dictionary attack, such as Argon2i.
You should use full-disk encryption (or encryption of your home directory) to
protect your wallet at rest, and should assume (even unprivileged) users who are
runnng on your OS can read your wallet.dat file.
Side-Channel Attacks
--------------------

View File

@ -98,7 +98,7 @@ def main():
os.makedirs(options.tmpdir)
initialize_chain(options.tmpdir)
nodes = start_nodes(1, options.tmpdir)
nodes = start_nodes(1, options.tmpdir, extra_args=[['-developerencryptwallet']])
run_test(nodes, options.tmpdir)

View File

@ -10,6 +10,10 @@ from time import *
class WalletNullifiersTest (BitcoinTestFramework):
def setup_nodes(self):
return start_nodes(4, self.options.tmpdir,
extra_args=[['-developerencryptwallet']] * 4)
def run_test (self):
# add zaddr to node 0
myzaddr0 = self.nodes[0].z_getnewaddress()

View File

@ -1090,6 +1090,9 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_encrypted_wallet_zkeys)
Array arr = retValue.get_array();
BOOST_CHECK(arr.size() == n);
// Verify that the wallet encryption RPC is disabled
BOOST_CHECK_THROW(CallRPC("encryptwallet passphrase"), runtime_error);
// Encrypt the wallet (we can't call RPC encryptwallet as that shuts down node)
SecureString strWalletPass;
strWalletPass.reserve(100);

View File

@ -1979,10 +1979,18 @@ Value encryptwallet(const Array& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
auto fEnableWalletEncryption = GetBoolArg("-developerencryptwallet", false);
std::string strWalletEncryptionDisabledMsg = "";
if (!fEnableWalletEncryption) {
strWalletEncryptionDisabledMsg = "\nWARNING: Wallet encryption is DISABLED. This call always fails.\n";
}
if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
throw runtime_error(
"encryptwallet \"passphrase\"\n"
+ strWalletEncryptionDisabledMsg +
"\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
"After this, any calls that interact with private keys such as sending or signing \n"
"will require the passphrase to be set prior the making these calls.\n"
@ -2008,6 +2016,9 @@ Value encryptwallet(const Array& params, bool fHelp)
if (fHelp)
return true;
if (!fEnableWalletEncryption) {
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: wallet encryption is disabled.");
}
if (pwalletMain->IsCrypted())
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");