Describe the bug
In Settings > Advanced > Sign & verify messages, the address picker offers the wallet's
Silent Payment (sp1...) address. Signing a message with it succeeds and returns a signature,
but that signature is produced with the wallet's mainHd key, which is unrelated to the sp1
address shown in the UI. No error or warning is displayed.
The problem is not that Silent Payment message signing is unsupported. The problem is that it
fails silently and hands the user something that looks like a valid ownership proof.
Root cause
cw_bitcoin/lib/electrum_wallet.dart, signMessage():
Future<String> signMessage(String message, {String? address = null}) async {
final addressRecord = address != null
? walletAddresses.allAddresses.firstWhereOrNull((addr) => addr.address == address)
: null;
...
final hd = addressRecord != null
? _hdFor(record: addressRecord).childKey(Bip32KeyIndex(addressRecord.index))
: mainHd;
...
}
walletAddresses.allAddresses returns only _addresses (List<BitcoinAddressRecord>).
Silent Payment addresses live in a separate list, silentAddresses
(List<BitcoinSilentPaymentAddressRecord>), which is never included in allAddresses.
firstWhereOrNull therefore never matches the sp1 string, addressRecord stays null,
and execution takes the mainHd fallback.
Steps to reproduce
- Create or restore a Bitcoin wallet with Silent Payments enabled
- Go to Settings > Advanced > Sign & verify messages
- Select the wallet's sp1... address
- Sign any message
- Recover the public key from the signature (BIP137 ECDSA recovery over the
"Bitcoin Signed Message" magic hash)
- The recovered key does not match either public key encoded in the sp1 address
(bech32m, 66-byte payload: 33 bytes B_scan || 33 bytes B_spend). It matches the
wallet's mainHd key instead, confirming the fallback path above.
Expected behavior
Signing must never silently use a key unrelated to the address the user selected. Minimal
acceptable fix, either:
- exclude sp1 entries from the address picker on this screen, or
- have
signMessage raise an explicit error when the selected address has no signable record
Whether an sp1 address should be signable at all, and under which scheme, is a separate design
question. I've written it up in a comment below rather than bundling it here, so this issue can
stay scoped to the silent wrong-key fallback.
Impact
Cake Wallet's message signing cannot currently be used to prove ownership of a Silent Payment
address, for example by a third party service verifying an SP address before sending recurring
payments. The failure is silent, so both the user and the verifier are given false confidence
that ownership was proven.
Describe the bug
In Settings > Advanced > Sign & verify messages, the address picker offers the wallet's
Silent Payment (sp1...) address. Signing a message with it succeeds and returns a signature,
but that signature is produced with the wallet's
mainHdkey, which is unrelated to the sp1address shown in the UI. No error or warning is displayed.
The problem is not that Silent Payment message signing is unsupported. The problem is that it
fails silently and hands the user something that looks like a valid ownership proof.
Root cause
cw_bitcoin/lib/electrum_wallet.dart,signMessage():walletAddresses.allAddressesreturns only_addresses(List<BitcoinAddressRecord>).Silent Payment addresses live in a separate list,
silentAddresses(
List<BitcoinSilentPaymentAddressRecord>), which is never included inallAddresses.firstWhereOrNulltherefore never matches the sp1 string,addressRecordstaysnull,and execution takes the
mainHdfallback.Steps to reproduce
"Bitcoin Signed Message" magic hash)
(bech32m, 66-byte payload: 33 bytes B_scan || 33 bytes B_spend). It matches the
wallet's
mainHdkey instead, confirming the fallback path above.Expected behavior
Signing must never silently use a key unrelated to the address the user selected. Minimal
acceptable fix, either:
signMessageraise an explicit error when the selected address has no signable recordWhether an sp1 address should be signable at all, and under which scheme, is a separate design
question. I've written it up in a comment below rather than bundling it here, so this issue can
stay scoped to the silent wrong-key fallback.
Impact
Cake Wallet's message signing cannot currently be used to prove ownership of a Silent Payment
address, for example by a third party service verifying an SP address before sending recurring
payments. The failure is silent, so both the user and the verifier are given false confidence
that ownership was proven.