Post
Topic
Board Development & Technical Discussion
Re: New ashigaru whirlpool coordinator can de-anonymize users
by
1440000bytes
on 23/06/2025, 14:18:47 UTC
It seems they aren't using code from whirlpool-client repository in the terminal. Instead hardcoded a public key for signing:

Code:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp5iSNzsR0S77fby4CFkG
OHF2oKNKsAYyK8e8SEwQrqmheYHF2t3mRAoYa0iN1OUXqhl3AkN5pOZQxJosIUFL
GR2tVNtYFv0ehzxUwYWBTIFNblNysccayBlFwQMuZaCa7/Cz/MGuemmn9/tBh1Vp
7CxfYRYVXHlSe08cYImtVg6dtrcarw/rm24ke1siUxLnrM6/LbgCWfvR6SKTZ7Zm
Ox5pi0TRTkcL1dJli5QDkUA6sLFUxmvG03rZLJ61LFFqm495VLsRCHVT5jDHz5aK
Xljk9Hhe2II9iHiy3GRy+01w1ZvPZ6Am2mO1usgAu1J5Zilnt0ahxLEQB2wRnXTP
UQIDAQAB
-----END PUBLIC KEY-----


Code:

        // use receiveAddress as bordereau. keep it private, but transmit blindedBordereau
        // clear receiveAddress will be provided with unblindedSignedBordereau by connecting with
        // another identity for REGISTER_OUTPUT
        final RSAKeyParameters rsaPublicKey;
        byte[] publicKey = WhirlpoolProtocol.decodeBytes(confirmInputMixStatusNotification.publicKey64);
        if (publicKey != null && publicKey.length > 0) {
            throw new ProtocolException("not expected to receive public key for blind signature from whirlpool server");
            //rsaPublicKey = ClientUtils.publicKeyUnserialize(publicKey);
        } else {
            rsaPublicKey = blindSignaturePublicKey;
        }

        this.blindingParams = clientCryptoService.computeBlindingParams(rsaPublicKey);

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

        confirmedInput = true;
        return confirmInputRequest;
    }


This introduces other issues in the coinjoin process. I will add more details after doing some research and testing.