Post
Topic
Board Development & Technical Discussion
Merits 32 from 7 users
Topic OP
New ashigaru whirlpool coordinator can de-anonymize users
by
1440000bytes
on 23/06/2025, 07:25:17 UTC
⭐ Merited by LoyceV (12) ,NotATether (6) ,cAPSLOCK (5) ,d5000 (5) ,theymos (2) ,DireWolfM14 (1) ,ABCbits (1)
Ashigaru announcement: https://ashigaru.rs/news/announcement-whirlpool/

https://i.ibb.co/Q7G2rDBr/rsa.png

Background: Nothingmuch had reported a vulnerability in whirlpool in December 2024: https://groups.google.com/g/bitcoindev/c/CbfbEGozG7c/m/w2B-RRdUCQAJ

This allows a malicious coordinator to link inputs and outputs by providing each input with a unique RSA public key. Since the unblinded signatures are made by different keys, the server can learn the mapping from inputs to outputs.

The blind signing process requires a server or coordinator to share the public key. The highlighted text in the announcement is misleading. I looked at the code in [Whirlpool-Client](http://ashicodepbnpvslzsl2bz7l2pwrjvajgumgac423pp3y2deprbnzz7id.onion/Ashigaru/Ashigaru-Whirlpool-Client) and [Whirlpool-Server](http://ashicodepbnpvslzsl2bz7l2pwrjvajgumgac423pp3y2deprbnzz7id.onion/Ashigaru/Ashigaru-Whirlpool-Server) and found that the vulnerability is not fixed.

Code:

    // generate a secret bordereau. keep it private and register INPUT with blindedBordereau
    // bordereau will be provided with unblindedSignedBordereau to register POSTMIX with another
    // identity
    this.bordereau = ClientUtils.generateBordereau();
    byte[] publicKey = WhirlpoolProtocol.decodeBytes(confirmInputMixStatusNotification.publicKey64);
    RSAKeyParameters serverPublicKey = ClientUtils.publicKeyUnserialize(publicKey);
    this.blindingParams = clientCryptoService.computeBlindingParams(serverPublicKey);

    String mixId = confirmInputMixStatusNotification.mixId;
    String blindedBordereau64 =
        WhirlpoolProtocol.encodeBytes(clientCryptoService.blind(bordereau, blindingParams));
    String userHash = premixHandler.computeUserHash(mixId);
    ConfirmInputRequest confirmInputRequest =
        new ConfirmInputRequest(mixId, blindedBordereau64, userHash);

    confirmedInput = true;
    return confirmInputRequest;
  }


http://ashicodepbnpvslzsl2bz7l2pwrjvajgumgac423pp3y2deprbnzz7id.onion/Ashigaru/Ashigaru-Whirlpool-Client/src/commit/a64bd8b4e0ee8a4cfab03da4565f166d07caa7ec/src/main/java/com/samourai/whirlpool/client/mix/MixProcess.java

Code:

        // register confirming input
        String publicKey64 = WhirlpoolProtocol.encodeBytes(mix.getPublicKey());
        ConfirmInputMixStatusNotification confirmInputMixStatusNotification =
                new ConfirmInputMixStatusNotification(mix.getMixId(), publicKey64);
        mix.registerConfirmingInput(registeredInput);

http://ashicodepbnpvslzsl2bz7l2pwrjvajgumgac423pp3y2deprbnzz7id.onion/Ashigaru/Ashigaru-Whirlpool-Server/src/branch/main/src/main/java/com/samourai/whirlpool/server/services/MixService.java

Conclusion: Users should not trust this centralized coordinator and do their own research before paying 5% coordinator fees.