Skip to content

Wallet passphrases silently ignore everything after a null character #27067

@john-moffett

Description

@john-moffett

Problem

Encrypting a wallet through JSON RPC or Qt appears to allow a user to include null characters in the passphrase, but silently ignores everything including and after the first null character.

For instance (on regtest), trying to set a passphrase of "a{null character}b":

curl --user __cookie__ --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "encryptwallet", "params": ["a\u0000b"]}' -H 'content-type: text/plain;' http://127.0.0.1:18443/

This will succeed, but allow the user to unlock with the passphrase "a", instead of the expected full passphrase (which also works):

curl --user __cookie__ --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "walletpassphrase", "params": ["a",10]}' -H 'content-type: text/plain;' http://127.0.0.1:18443/

I am also able to replicate it in Qt on my macOS machine by running printf 'a\0b' | pbcopy and pasting the result into the passphrase dialog.

My main concern is a user thinking that they're generating, say, 32 random bytes as a passphrase, and if they're unlucky and get a zero in the first few bytes, it unexpectedly cuts their security down to almost nothing.

Root Cause

The reason is due to our SecureString type. SecureString is a std::string specialization with a secure allocator. However, when assigned, it's treated like a C- string (no explicit length and null-terminated). See the original PR for more details.

Potential Solutions

I think there are two plausible approaches to take. The first (and my preference) is to allow and support null characters, and I will submit a PR that enables that (by making SecureString use the entire string). The second is to explicitly reject any passphrases that contain null characters.

One significant complication may be that, if anyone is already using a passphrase with a null, then my first solution would stop their wallet from unlocking. However, it would still be unlockable just by trimming the null and any subsequent characters.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions