Can malicious payer deanonymize payee in Zcash?

Isabella: 5 weeks ago

Looking at both the Zcash original paper ( and the updated Zcash protocol specification (, it seems that after Alice paid Bob, she can reveal to the world that she did so.

Alice can do so by revealing the randomness of the new coin commitments she generated, one of which contains Bob's PK and the amount. For example, in the image below, Alice reveals the elements highlighted in red (i.e., Alice's randomness) and purple (i.e., Bob's PK and the value), while the elements in yellow are already public.

Zcash Pour TXN description from Oakland paper

The same attack works in the updated Zcash proposal (see Section 4.4 on page 19 in v2018-beta2.0 (, plus image below).

Zcash coin commitment from their protocol spec

I just want to confirm that (1) I am not missing anything and this is possible and (2) it's potentially problematic. For example, if Alice paid Bob for some illicit goods or services, she can later reveal that she did so.

Thoughts would be welcome!

Evelyn: 5 weeks ago

tl;dr Alice can reveal payments she made to Bob. She cannot reveal payments that others made to Bob, or reveal what (if anything) Bob does with the ZEC that Alice sent.

Revealing the pre-image of the note commitment only proves that Alice knows the pre-image. It does not prove that Alice sent the transaction, because the proof is replayable: once revealed, anyone can take the randomness and note data, and show it to someone else.

In order for Alice to prove to someone that she sent the transaction, she can do the following:

  • Write a message that contains:
    • The private key esk used to encrypt the note (randomness and value) to Bob.
    • Bob's payment address.
    • A challenge string chosen by the person Alice is convincing.
  • Sign the message using the private key joinSplitPrivKey corresponding to the joinsplitPubKey that was originally used to sign the transaction.

The signed message is proof that Alice currently has access to joinSplitPrivKey (because the challenge string is fresh). Assuming that joinSplitPrivKey is never revealed, Alice is indistinguishable from the person who created the transaction (i.e. either she or someone with her spending keys made the payment). This is what we call a payment disclosure (, and is how e.g. you would prove to an exchange (or a third party dispute resolution service) that you did indeed pay them.

What you are describing is fundamentally the same issue that messaging apps have with end-to-end encryption: someone with intended access to the data can accidentally or intentionally reveal it. Removing this potential privacy leak would by definition mean that Alice cannot see some or all details about her own outgoing transactions, which is either a contradiction (in the Zcash model, Alice needs to be able to calculate a commitment from its pre-image in order to create valid transactions), or a completely unusable payment system!

Note however that even though Alice can prove that she sent a transaction to Bob, she cannot reveal anything about what Bob does with the note he received (because she does not have Bob's spending key, and thus can't calculate the nullifier that will would be revealed at spend time). Alice's ability to reveal information is limited to information she was ever able to view.