Skip to content

Commit

Permalink
Auto merge of zcash#1569 - str4d:1552-disable-wallet-encryption, r=daira
Browse files Browse the repository at this point in the history
Disable wallet encryption

Closes zcash#1552
  • Loading branch information
zkbot committed Oct 20, 2016
2 parents bb891cb + d8e06e3 commit f905265
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 2 deletions.
28 changes: 28 additions & 0 deletions doc/security-warnings.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
--------------------

Expand Down
2 changes: 1 addition & 1 deletion qa/rpc-tests/keypool.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
4 changes: 4 additions & 0 deletions qa/rpc-tests/wallet_nullifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

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()
Expand Down
3 changes: 3 additions & 0 deletions src/test/rpc_wallet_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 12 additions & 1 deletion src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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.");

Expand Down

0 comments on commit f905265

Please sign in to comment.