On May 10, Ondřej Vejpustek from TREZOR sent a PGP encrypted message to Wasabi. The message had an insightful explanation about a possible Conjoin denial of service vulnerability under Wasabi’s security disclosure policy. These attacks were designed to exploit the Wasabi Bitcoin privacy wallet to steal some coins
An attacker could have exploited the vulnerability to conduct a DoS (denial-of-service) attack before the v4 Hard Fork. In that scenario, it was challenging to identify the source of the attack. Through DoS, the hacker would stop the whole CoinJoin process for every other participant and the Wasabi rounds would no longer operate.
Since there is no DoS attempt this far, it is assumed that no Wasabi user has been affected by the vulnerability. It is important to note that the attacker could neither steal users’ funds nor deanonymize anyone. What they could do, however, was to prevent the completion of the CoinJoin process.
Users who have already downloaded Wasabi Wallet v1.1.12 that was released on August 5, 2020, can benefit fully from the v4 Hard Fork. The Hard Fork fixed that vulnerability and therefore no user action is necessary. For anyone who is yet to upgrade their Wasabi to v1.1.12 version, they are encouraged to do so since the Hard Fork breaks the compatibility with older software.
Blind Schnorr Signatures
At the start of every round, a new blind Schnorr signature key pair is generated for each round level. At the input registration phase, a participant of the CoinJoin records all unspent outputs in their possession as inputs to the coinjoin transaction. It also registers one or even more blinded addresses as outputs of the coinjoin transaction.
The coordinator determines the number of levels the participant has funds to participate in during the connection confirmation phase. They then return the participant to the corresponding number of blinded addresses that are signed with the corresponding level keys. Turning to the output registration phase, the participant using a different identity reveals their unblended outputs with the unblended signatures that are validated by the coordinator.
Every signature uses a freshly generated nonce for blind Schnorr signatures. In the scenario that a signer generates two signatures using one nonce, it is easy to determine their private key as same as the private part of the particular nonce.
The issue arises that the nonce in the implementation phase is a part of the key pair. As a result, the nonce is the same for all outputs that are registered on the same level. Thus, a participant that registers two or more outputs on the same level can determine the signer’s private key.
How Attackers Operate Before v4 Hard Fork Upgrade
Any attacker who knows the signer’s private key can easily generate a valid signature for every message. Hence, they can register an output that was never blind signed by the coordinator. What happens next? Provided that the implementation of the client is correct and sound, attackers cannot steal many coins and they can also not deanonymize anyone.
The attacker can just prevent the completion of the coinjoin resulting in a denial-of-service attack. The attacker starts by registering their real and fake outputs in the output registration phase. Eventually, several participants are prohibited from registering their outputs because the output registration phase concludes when the registered outputs equal the returned blinded signatures in the connection confirmation phase.
These participants normally refuse to sign the conjoin transaction. In the end, their unspent output that is registered as input to the coinjoin is banned. The attacker registers one of their real outputs. Apart from that, they register a fake output on a higher level. Since they registered outputs equal to the number of blinded signatures that they got, the other participants might register their outputs.
If that happens, the coordinator creates a transaction that is invalid because the sum of all inputs is less than the sum of all outputs.
Possible Fixes For The Bug
The coordinator generates nonce pair on request, remembers both public part and private part, and then returns the public one. Any participant that registers their unspent outputs and blinded addresses uses this nonce to blind the addresses and sends the nonce in his request. Then, the coordinator gets the corresponding private nonce, blind signs the addresses, and it forgets the nonce pair. Therefore, it is not used repeatedly.
Users can also replace Schnorr blind signatures with RSA blind signatures. That can work because the RSA signature does not need nonce. But, this approach is not popular since RSA in contrast with elliptic-curve cryptography is not quite widespread in the bitcoin community.