Wallet: no way to remove a private key (add removeprivkey, and signmessagewithprivkey) #46
Labels
No labels
do-not-open-till-X-Day
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
SubGeniusFinance/dobbscoin-source#46
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
There is no way to take a private key back out of a wallet once it is in. The only key RPCs are
importprivkeyanddumpprivkey(src/rpcdump.cpp); there is no removal, and no way to sign with a key without importing it first.Why it matters
Signing a message with a cold or paper key (for example, to claim an address on a block explorer rich list, or to prove ownership) currently means
importprivkeyinto a running wallet, thensignmessage. After that the key is inwallet.datfor good, and in every backup made from then on. The coins are effectively hot for the rest of the wallet's life, which is the opposite of what the owner wanted from a one-off signature.Proposal
signmessagewithprivkey "privkey" "message": port Bitcoin Core's RPC (added in 0.13, bitcoin/bitcoin#7953). It signs with a key passed in the call and never touches the wallet. That alone covers the signing use case.removeprivkey "address" ( keepwatchonly ): remove a key from the wallet.key/ckeyandkeymetarecords and drops the key frommapKeys/mapCryptedKeys.keepwatchonly=true, adds the address as watch-only so the balance stays visible.Acceptance
qa/rpc-tests:signmessagewithprivkeyoutput verifies withverifymessage. Afterremoveprivkey,dumpprivkeyfails,validateaddressreportsismine: false(or watch-only), and the key survives neither a restart nor abackupwallet.Related: #41 (wallet backend). Whatever backend replaces Berkeley DB should support key removal from the start.
Implemented on branch
feat/46-removeprivkey(62b6577a).signmessagewithprivkey "privkey" "message"signs without touching the wallet. Its output is identical tosignmessage(RFC 6979) and checks withverifymessage.removeprivkey "address" ( keepwatchonly )removes the key from memory (mapKeys/mapCryptedKeys,mapKeyMetadata) and from disk (key/wkey/ckey/keymetarecords).keepwatchonly=trueleaves the address as watch-only.Correction to the issue text: no file rewrite is needed. The wallet is SQLite since v0.14.0 (#41's "Berkeley DB only" is out of date), and it already runs with
PRAGMA secure_delete = ON, so deleted records are overwritten in place. Backups made before a removal still contain the key, which the RPC help says.Not done yet: the GUI "Forget private key" action, and refusing addresses already used for change (only keys still in the keypool are guarded).
Tests: new
qa/rpc-tests/removeprivkey.py. It covers signing on a node without the key; removal on plain and encrypted wallets; persistence across restart; the secret bytes and key records absent fromwallet.dat;keepwatchonly; and re-import.qa/run-all.sh: 27 passed, 0 failed.