Subject: [bitcoindev] Reiterating centralized coinjoin (Wasabi & Samourai) deanonymization attacks

From: Yuval Kogman <[email-masked]>
Date: Sat, 21 Dec 2024 15:16:09 +0100

Following the recent Wasabi & GingerWallet vulnerability report[^1]
and its "fix", I would like to bring up (reiterate, but for the first
time on the mailing lists) some broader deanonymization issues with
both Wasabi / GingerWallet and Samourai wallet's CoinJoin protocols.

These vulnerabilities were never truly discovered and consequentially
not disclosed, responsibly or otherwise, because they had always been
in the protocols. Neither team seems capable of addressing these for a
variety of reasons.

Personal disclosure: I was involved in the design of WabiSabi, as well
as its implementation but left in protest before its release. I
maintain that this software is not fit for purpose and should not be
used unless users trust the coordinators with their privacy.
Furthermore, I allege that rent seeking behavior explains the apparent
incompetence and willful ignorance, and caution against applying
Hanlon's razor too charitibly.

In regards to Wasabi/GingerWallet, especially in light of the various
"community" WabiSabi protocol coordinators, it's important to make
users aware of the degree of trust they place in these services.
Wasabi developers are still claiming that these issues are not
fixable, which is incorrect to say the least, especially considering
that when I was contributing to the project and taking for granted
that these issues would be addressed I got no pushback, nor any
indication that they did not understand the issue at the time.

Whirlpool is now defunct, but Samourai proponents are claiming that
their developers have warned about the Wasabi vulnerability, despite
the Whirlpool protocol having a more blatant and easily exploitable
version of the same category of attack, so it's worth setting the
record straight. The whirlpool client code was included in Sparrow
wallet until v1.9.0 when it was removed following the shutdown of the
whirlpool service.

[^1]: https://bitcoinops.org/en/newsletters/2024/12/13/#deanonymization-vulnerability-affecting-wasabi-and-related-software

## Preliminaries

Both protocols facilitate multiparty transaction construction,
ostensibly utilizing cryptography for privacy preserving denial of
service protection. TxOut addition requires authorization tokens, an
unblinded signature in Whirlpool's case, or an anonymous credential in
WabiSabi's, that is supposed to not be linkable to any of the client's
added TxIns.

In both protocols a malicious coordinator can trick the existing
client implementations into making fully deanonymized requests. In
Whirlpool this means a TxOut is linkable to a TxIn. In WabiSabi this
means that the set of TxOuts is  linkable to the set of TxIns of a
single client.

### Whirlpool

This is a trivial deanonymization attack reliant on the fact that the
client completely trusts the server with regards to the consistency of
the blind signing key.

In Whirlpool, the server's blind signing key is obtained by the client
by extracting it from the response to the input registration
request.[^2]

Subsequently, this key is used to make blind signing requests during
the confirmation phase.[^3]

After a blind signature is given to the client the unblinded signature
is used to request an output registration.[^4]

Because the key is not announced a priori, nor is it signed by the
participants' spending keys before output registration or signing[^5],
the server can provide each input with a unique RSA key. Since the
unblinded signatures are made by different keys, the server can learn
the mapping from inputs to outputs.

This description along with some preliminaries is also posted on github.[^6].

[^2]:  https://github.com/Archive-Samourai-Wallet/whirlpool-client/blob/99c1acc101f53fef21fbcc5d23cb05eafb7324e9/src/main/java/com/samourai/whirlpool/client/mix/MixProcess.java#L140-L141
[^3]: https://github.com/Archive-Samourai-Wallet/whirlpool-client/blob/99c1acc101f53fef21fbcc5d23cb05eafb7324e9/src/main/java/com/samourai/whirlpool/client/mix/MixProcess.java#L146
[^4]: https://github.com/Archive-Samourai-Wallet/whirlpool-client/blob/99c1acc101f53fef21fbcc5d23cb05eafb7324e9/src/main/java/com/samourai/whirlpool/client/mix/MixProcess.java#L185
[^5]: https://github.com/Archive-Samourai-Wallet/whirlpool-client/blob/99c1acc101f53fef21fbcc5d23cb05eafb7324e9/src/main/java/com/samourai/whirlpool/client/mix/MixProcess.java#L216
[^6]:  https://gist.github.com/nothingmuch/74d0b0bd63a2d663efce5e8a82d32bca

### WabiSabi

This affects Wasabi Wallet, and Ginger Wallet which is a fork of
Wasabi. Trezor Suite was also affected, but has subsequently removed
support for coinjoins[^18]. They too were made aware of various issues
and chose to ignore them, despite contributing the limited (read:
purely theater for privacy, only addressing hardware wallet specific
theft scenario) ownership proof verification.

Here the issue is more complex, but ultimately reduces to key
consistency as well.

In the protocol clients register their Bitcoin UTXOs independently. A
valid input registration request includes a BIP-322 ownership proof,
which commits to the so called *Round ID*. This in turn is a hash
commitment to the parameters of the round, including the server's
anonymous credential issuance parameters (analogous to a public key).

The parameters are obtained by polling the server for information
about active rounds. If inconsistent round IDs are given to clients,
this effectively partitions them, allowing deanonymization.

Although clients obtain the ownership proofs of other clients and
seemingly verify them, BIP-322 proofs verification requires knowledge
of the spent outputs `scriptPubKey` which light clients cannot obtain
on their own. This public key is included alongside the ownership
proofs, which makes their verification non-binding, the server can
generate unrelated public keys, and create ownership proofs with those
keys that commit to the per-client round IDs, which the client will
accept as valid.

This issue was described before the initial release[^7] but never
addressed. Although subsequently ownership proofs were given to
clients[^8], this change only addressed the use of ownership proofs to
identify a wallet's own inputs in a stateless signing device, without
addressing the consistency issues. Because the server provides the
public key against which unknown inputs ownership proofs must be
verified, that places them under adversarial control.

Related issues and comments I have posted over the years:

- unimplemented consistency check that does not depend on prevout also
not implemented[^9]
- no commitment to coordinator address in the round parameters[^10],
although this was temporarily fixed the fix was reverted[^11]
- additional missing fields in the round parameter commitments, and
rationale addressing tagging attacks[^12]
- initial description of blind signature based protocol, which
predates my collaboration and design of the anonymous credential based
protocol which also addresses this explicitly[^13]

Finally, although not in scope I will also note that poor coin
selection (bad randomization and de-randomization), improper
randomization of input registration timing, and tor circuit management
increase the probability of the success of such an attack, by making
it easier to target specific users. Additional concerns exist for
alternative clients due to use of JSON and HTTP in the protocol, in
the C# implementation serialization by a 3rd party JSON library, which
may canonicalize JSON differently (e.g. ordering of properties in JSON
objects), etc. Additionally, although designed with coordination fees
in mind, the anonymous credential mechanism did not enforce that
coordination fees are fair or incentive compatible (nor can it with
non-binding ownership proofs, though the main privacy concern there is
the coordinator lying about the values of other clients' prevouts
leading to poor amount decomposition), resulting in thefts of user
funds[^14][^15], but this has now been removed[^16].

Again a version of this with some preliminaries is also on github.[^17]

[^7]: https://github.com/WalletWasabi/WalletWasabi/issues/5533
[^8]: https://github.com/WalletWasabi/WalletWasabi/pull/8708
[^9]: https://github.com/WalletWasabi/WalletWasabi/issues/6394#issuecomment-920225648
[^10]: https://github.com/WalletWasabi/WalletWasabi/issues/5992
[^11]: https://github.com/WalletWasabi/WalletWasabi/pull/8708/files#diff-04b849802b4adf5b34756a49b498f2ac97247cbb64424e5a69ee64c28a7033bcR120
[^12]: https://github.com/WalletWasabi/WalletWasabi/issues/5439
[^13]: https://gist.github.com/nothingmuch/61968fde675a596758bffd4c278ac096
[^14]: https://github.com/WalletWasabi/WalletWasabi/discussions/13249
[^15]: https://bitcointalk.org/index.php?topic=5499439.msg64309927#msg64309927
[^16]: https://archive.is/xFRHO
[^17]: https://gist.github.com/nothingmuch/4d717e12e451ff4ce43474972e41c6ba
[^18]: https://blog.trezor.io/important-update-transitioning-from-coinjoin-in-trezor-suite-9dfc63d2662f

-- 
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email-masked].
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/CAAQdECCdRVV%2B3ZoJhOotKEvmUV4yrV7EYWE8SOWCE1CF9tZ6Yg%40mail.gmail.com.