New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

payment disclosure #2036

Open
nathan-at-least opened this Issue Jan 23, 2017 · 40 comments

Comments

Projects
8 participants
@nathan-at-least
Contributor

nathan-at-least commented Jan 23, 2017

Ticket #737 has a broader scope that allows changes to the protocol to implement a strong proof-of-payment protocol. This ticket is about a much more limited feature that can be implemented with the current protocol.

  • modify the wallet to give users a 'payment disclosure' which is an opaque string that can reveal JS output plaintexts. A 'payment disclosure' includes: (jsoutput, recipient address (pk_enc, a_pk), ephemeral secret key)
  • this begins life as an 'experimental feature', see #2035.
  • for now, a payment disclosure will reveal both outputs of a given JS, which is a privacy leak, see #2102 about a wallet feature to mitigate this leak. (An earlier approach was #2037, we favor #2102)
  • add an RPC call which can consume a 'payment disclosure' and reveal the plaintext, locate the transaction in the blockchain. (XXX FIXME: Doesn't this require txindex=1? Is this possible otherwise?)

@nathan-at-least nathan-at-least changed the title from bilateral-only "proof" of payment that's compatible w/ current protocol to payment disclosure Jan 23, 2017

@zmanian

This comment has been minimized.

Show comment
Hide comment
@zmanian

zmanian Jan 24, 2017

What if instead of revealing ephemeral secret key, you did a XEDDSA signature with the Esk of (jsouput, recipient address, challenge)? https://whispersystems.org/docs/specifications/xeddsa/#xeddsa

This solves your replayability problem inside the proof?

zmanian commented Jan 24, 2017

What if instead of revealing ephemeral secret key, you did a XEDDSA signature with the Esk of (jsouput, recipient address, challenge)? https://whispersystems.org/docs/specifications/xeddsa/#xeddsa

This solves your replayability problem inside the proof?

@arielgabizon

This comment has been minimized.

Show comment
Hide comment
@arielgabizon

arielgabizon Jan 26, 2017

Contributor

Maybe.. I'm slightly confused about what we need to defend against.
If it's a replay attack where some time later after I have sent my proof of payment, someone else replays that proof..can't the receiver just assume whomever sent the proof was the first time is the legitimate payment sender?
On the other hand, if it's a man-in-the-middle attack where someone is online between sender and receiver, he could still show that he payed even when there's an interactive signing challenge.
But I wonder, if for a first implementation, it's enough to just have what @nathan-at-least suggested above, and have the receiver assume whomever sent the proof of payment first is the legitimate one.

Contributor

arielgabizon commented Jan 26, 2017

Maybe.. I'm slightly confused about what we need to defend against.
If it's a replay attack where some time later after I have sent my proof of payment, someone else replays that proof..can't the receiver just assume whomever sent the proof was the first time is the legitimate payment sender?
On the other hand, if it's a man-in-the-middle attack where someone is online between sender and receiver, he could still show that he payed even when there's an interactive signing challenge.
But I wonder, if for a first implementation, it's enough to just have what @nathan-at-least suggested above, and have the receiver assume whomever sent the proof of payment first is the legitimate one.

@zookozcash

This comment has been minimized.

Show comment
Hide comment
@zookozcash

zookozcash Jan 26, 2017

@arielgabizon: a good defense against those sorts of replay/MITM attacks is to include identifiers (e.g. public keys or addresses) of the prover and the verifier into the proof.

In this case, it might not be the identifier (address) of the original address that paid, but instead a "reply/receipt/refund address", chosen by the prover (the original payer). The verifier would know that the proof proves not that whoever emailed him the proof paid, but that the person who controls the included refund address paid.

zookozcash commented Jan 26, 2017

@arielgabizon: a good defense against those sorts of replay/MITM attacks is to include identifiers (e.g. public keys or addresses) of the prover and the verifier into the proof.

In this case, it might not be the identifier (address) of the original address that paid, but instead a "reply/receipt/refund address", chosen by the prover (the original payer). The verifier would know that the proof proves not that whoever emailed him the proof paid, but that the person who controls the included refund address paid.

@arielgabizon

This comment has been minimized.

Show comment
Hide comment
@arielgabizon

arielgabizon Jan 26, 2017

Contributor

That's a nice idea. It can partially be implemented just with the memo field. Though a payer would have to know in advance he'll want to do such a proof of payment later so that he would include this receipt in the encrypted memo. Though still I'm wondering in practice, how bad it would be if the receiver would just assume the first person to send him the proof of payment is the real sender

Contributor

arielgabizon commented Jan 26, 2017

That's a nice idea. It can partially be implemented just with the memo field. Though a payer would have to know in advance he'll want to do such a proof of payment later so that he would include this receipt in the encrypted memo. Though still I'm wondering in practice, how bad it would be if the receiver would just assume the first person to send him the proof of payment is the real sender

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Jan 26, 2017

Contributor

@arielgabizon wrote:

On the other hand, if it's a man-in-the-middle attack where someone is online between sender and receiver, he could still show that he payed even when there's an interactive signing challenge.

If you have a secure channel with a purported (potentially anonymous) sender, and they perform an interactive proof with you over that channel, then you know that subsequent communications on the channel are with the actual sender (or someone who knows the sender's secrets).

Contributor

daira commented Jan 26, 2017

@arielgabizon wrote:

On the other hand, if it's a man-in-the-middle attack where someone is online between sender and receiver, he could still show that he payed even when there's an interactive signing challenge.

If you have a secure channel with a purported (potentially anonymous) sender, and they perform an interactive proof with you over that channel, then you know that subsequent communications on the channel are with the actual sender (or someone who knows the sender's secrets).

@jackgavigan

This comment has been minimized.

Show comment
Hide comment
@jackgavigan

jackgavigan Jan 30, 2017

Contributor

@nathan-at-least wrote:

A 'payment disclosure' includes: (jsoutput, recipient address (pk_enc, a_pk), ephemeral secret key)

Am I correct in thinking that the 'payment disclosure' consists of data that the Recipient will possess, so therefore a 'payment disclosure' can be created and shared by either the Sender or the Recipient?

Contributor

jackgavigan commented Jan 30, 2017

@nathan-at-least wrote:

A 'payment disclosure' includes: (jsoutput, recipient address (pk_enc, a_pk), ephemeral secret key)

Am I correct in thinking that the 'payment disclosure' consists of data that the Recipient will possess, so therefore a 'payment disclosure' can be created and shared by either the Sender or the Recipient?

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Jan 30, 2017

Contributor

@jackgavigan The recipient doesn't initially know the ephemeral secret key (esk). It does know its own viewing key skenc which would be sufficient to decrypt the ciphertext, but that is also sufficient to decrypt all other ciphertexts sent to the recipient address.

Contributor

daira commented Jan 30, 2017

@jackgavigan The recipient doesn't initially know the ephemeral secret key (esk). It does know its own viewing key skenc which would be sufficient to decrypt the ciphertext, but that is also sufficient to decrypt all other ciphertexts sent to the recipient address.

@bitcartel

This comment has been minimized.

Show comment
Hide comment
@bitcartel

bitcartel Feb 16, 2017

Contributor

Could the following help increase the level of confidence that a presenter of the payment disclosure is indeed the sender (where the sender did not include anything in the memo field) ?

  • Sender retains the ephemeral JoinSplitSig Private Key.
  • Sender uses this private key to sign a payment disclosure / refund address / message.
  • Recipient verifies signed data using the JoinSplitSig Public Key.
Contributor

bitcartel commented Feb 16, 2017

Could the following help increase the level of confidence that a presenter of the payment disclosure is indeed the sender (where the sender did not include anything in the memo field) ?

  • Sender retains the ephemeral JoinSplitSig Private Key.
  • Sender uses this private key to sign a payment disclosure / refund address / message.
  • Recipient verifies signed data using the JoinSplitSig Public Key.
@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Feb 24, 2017

Contributor

There's a problem I hadn't thought of (documented in the draft zip here): in some cases (such as for t -> multiple z transactions), both outputs of each JoinSplit will be used as non-change outputs. In that case the "KDF Tweak" approach won't work, because that relies on the sender of a change output knowing skenc.

There are several possible resolutions:

  1. Make sure that each JoinSplit has at most one non-change output, at the expense of doubling the number of JoinSplits in the problematic case. E.g. for a transaction sending transparent input to two z-addresses, now two JoinSplits are needed instead of one.
  2. Only reveal the symmetric key Kenci (which is different for each output). The verifier decrypts and checks the commitment cmnewi. This has the disadvantage that it is possible to provide a "valid" proof of payment, even though the recipient could not have decrypted the payment: The attacker does this by creating a transaction in which the shared secret - out of which Kenci will be computed - is generated from recipient's public address together with e'sk not corresponding to the published epk; thus, the recipient will not manage to decrypt this note while scanning the blockchain. Note that the attacker needs to burn money to carry this out.
  3. A payment disclosure contains the inputs to the KDF, i.e. (i, hSig, sharedSecreti, epk, pknewenc,i), and a proof (e.g. Chaum-Pedersen) that (g, epk, pknewenc,i, sharedSecreti) is a DH tuple. Note that to avoid an information leak, we need that pknewenc,0 and pknewenc,1 are distinct (because if they are equal, then sharedSecret0 = sharedSecret1). But it is easy to avoid this case.

(edited by Ariel)

Contributor

daira commented Feb 24, 2017

There's a problem I hadn't thought of (documented in the draft zip here): in some cases (such as for t -> multiple z transactions), both outputs of each JoinSplit will be used as non-change outputs. In that case the "KDF Tweak" approach won't work, because that relies on the sender of a change output knowing skenc.

There are several possible resolutions:

  1. Make sure that each JoinSplit has at most one non-change output, at the expense of doubling the number of JoinSplits in the problematic case. E.g. for a transaction sending transparent input to two z-addresses, now two JoinSplits are needed instead of one.
  2. Only reveal the symmetric key Kenci (which is different for each output). The verifier decrypts and checks the commitment cmnewi. This has the disadvantage that it is possible to provide a "valid" proof of payment, even though the recipient could not have decrypted the payment: The attacker does this by creating a transaction in which the shared secret - out of which Kenci will be computed - is generated from recipient's public address together with e'sk not corresponding to the published epk; thus, the recipient will not manage to decrypt this note while scanning the blockchain. Note that the attacker needs to burn money to carry this out.
  3. A payment disclosure contains the inputs to the KDF, i.e. (i, hSig, sharedSecreti, epk, pknewenc,i), and a proof (e.g. Chaum-Pedersen) that (g, epk, pknewenc,i, sharedSecreti) is a DH tuple. Note that to avoid an information leak, we need that pknewenc,0 and pknewenc,1 are distinct (because if they are equal, then sharedSecret0 = sharedSecret1). But it is easy to avoid this case.

(edited by Ariel)

@bitcartel

This comment has been minimized.

Show comment
Hide comment
@bitcartel

bitcartel Feb 24, 2017

Contributor

In 2. an independent judge/arbiter would require the recipient to provide a viewing key, if the recipient continues to claim they did not receive funds. So there could be a situation where an attacker burns funds, opens a dispute and provides a "valid" proof of payment, where the intent is to get the recipient to reveal their viewing key.

Contributor

bitcartel commented Feb 24, 2017

In 2. an independent judge/arbiter would require the recipient to provide a viewing key, if the recipient continues to claim they did not receive funds. So there could be a situation where an attacker burns funds, opens a dispute and provides a "valid" proof of payment, where the intent is to get the recipient to reveal their viewing key.

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Feb 24, 2017

Contributor

Actually in case 2., revealing Kenci would then allow the recipient to spend the funds (provided that the commitment is correct). So the issue is that the recipient would not previously have been able to spend them, and the payment might have been time-sensitive.

Contributor

daira commented Feb 24, 2017

Actually in case 2., revealing Kenci would then allow the recipient to spend the funds (provided that the commitment is correct). So the issue is that the recipient would not previously have been able to spend them, and the payment might have been time-sensitive.

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Feb 24, 2017

Contributor

Here's the original paper on Chaum-Pedersen: http://www.cs.elte.hu/~rfid/chaum_pedersen.pdf (see section 3.2). It adapts straightforwardly to Curve25519.

It's presented as a signature scheme, but one that is constructed from a proof-of-DH-tuple. There are other possible ways to prove a DH tuple based on pairings, but Curve25519 isn't pairing-friendly.

Contributor

daira commented Feb 24, 2017

Here's the original paper on Chaum-Pedersen: http://www.cs.elte.hu/~rfid/chaum_pedersen.pdf (see section 3.2). It adapts straightforwardly to Curve25519.

It's presented as a signature scheme, but one that is constructed from a proof-of-DH-tuple. There are other possible ways to prove a DH tuple based on pairings, but Curve25519 isn't pairing-friendly.

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Feb 24, 2017

Contributor

A possible refinement of 3. is to use a Chaum-Pedersen signature to sign the information that should be nonmalleable (e.g. refund address). This is similar to @zmanian's idea of using XEdDSA.

Edit: it is easier-said-than-done to combine the proof-of-DH-tuple with a signature. A single instance of Chaum-Pedersen won't do it because the group element that depends on the message representative (z in the Chaum-Pedersen paper) is different than the ones (epk and pknewenc,i) involved in the proof that the note encryption was done correctly.

Contributor

daira commented Feb 24, 2017

A possible refinement of 3. is to use a Chaum-Pedersen signature to sign the information that should be nonmalleable (e.g. refund address). This is similar to @zmanian's idea of using XEdDSA.

Edit: it is easier-said-than-done to combine the proof-of-DH-tuple with a signature. A single instance of Chaum-Pedersen won't do it because the group element that depends on the message representative (z in the Chaum-Pedersen paper) is different than the ones (epk and pknewenc,i) involved in the proof that the note encryption was done correctly.

@zmanian

This comment has been minimized.

Show comment
Hide comment
@zmanian

zmanian Feb 25, 2017

Mike Hamburg has an x25519 signatures scheme in Strobe.
https://www.reddit.com/r/crypto/comments/5u7i3z/signature_with_a_montgomery_curve/ddu8or0/?context=3 See @Bascule's comment and Mike's response

zmanian commented Feb 25, 2017

Mike Hamburg has an x25519 signatures scheme in Strobe.
https://www.reddit.com/r/crypto/comments/5u7i3z/signature_with_a_montgomery_curve/ddu8or0/?context=3 See @Bascule's comment and Mike's response

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Feb 25, 2017

Contributor

In #1360 (comment) I point out that using both outputs of a JoinSplit entails an information leak. So there is a privacy-performance trade-off which, if we resolved it in favour of privacy at the cost of sometimes using more JoinSplits, would also allow us to use the simpler KDF Tweak approach (#2102) for payment disclosures.

Contributor

daira commented Feb 25, 2017

In #1360 (comment) I point out that using both outputs of a JoinSplit entails an information leak. So there is a privacy-performance trade-off which, if we resolved it in favour of privacy at the cost of sometimes using more JoinSplits, would also allow us to use the simpler KDF Tweak approach (#2102) for payment disclosures.

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Feb 25, 2017

Contributor

In the next circuit change, we can eliminate this privacy-performance tension by implementing #647, as I pointed out in #647 (comment) .

Contributor

daira commented Feb 25, 2017

In the next circuit change, we can eliminate this privacy-performance tension by implementing #647, as I pointed out in #647 (comment) .

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Feb 25, 2017

Contributor

I think we should exclude using an unconventional signature scheme. We have the joinSplitSig private Ed25519 key available to sign the associated nonmalleable information. Ed25519 is pleasantly boring, and this means we do not have to consider the joint security of the note encryption and the disclosure protocol with the same keys. (It is straightforward to ensure that inputs to the Ed25519 signature scheme for the disclosure protocol are not valid as dataToBeSigned for JoinSplit signatures, and vice versa.)

Contributor

daira commented Feb 25, 2017

I think we should exclude using an unconventional signature scheme. We have the joinSplitSig private Ed25519 key available to sign the associated nonmalleable information. Ed25519 is pleasantly boring, and this means we do not have to consider the joint security of the note encryption and the disclosure protocol with the same keys. (It is straightforward to ensure that inputs to the Ed25519 signature scheme for the disclosure protocol are not valid as dataToBeSigned for JoinSplit signatures, and vice versa.)

@nathan-at-least

This comment has been minimized.

Show comment
Hide comment
@nathan-at-least

nathan-at-least Feb 27, 2017

Contributor

Let's implement the new multi-joinsplit algorithm as an opt-in 'experimental feature', and point out it has better privacy and worse performance in the specific cases of many recipients (and many input notes). Then we'll get feedback from the wild-and-wooly about this.

Contributor

nathan-at-least commented Feb 27, 2017

Let's implement the new multi-joinsplit algorithm as an opt-in 'experimental feature', and point out it has better privacy and worse performance in the specific cases of many recipients (and many input notes). Then we'll get feedback from the wild-and-wooly about this.

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Feb 28, 2017

Contributor

The worse performance is only when there are many output notes (and fewer than twice as many input notes than output notes). The better privacy is whenever either vpubin or vpubout is nonzero.

Contributor

daira commented Feb 28, 2017

The worse performance is only when there are many output notes (and fewer than twice as many input notes than output notes). The better privacy is whenever either vpubin or vpubout is nonzero.

@arielgabizon

This comment has been minimized.

Show comment
Hide comment
@arielgabizon

arielgabizon Feb 28, 2017

Contributor

@nathan-at-least - Not sure why you posted this here. Does that mean we implement payment disclosure only after implementing new multi-joinsplit?
Can someone link here to a description of this new multi join-split algorithm?

Contributor

arielgabizon commented Feb 28, 2017

@nathan-at-least - Not sure why you posted this here. Does that mean we implement payment disclosure only after implementing new multi-joinsplit?
Can someone link here to a description of this new multi join-split algorithm?

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Mar 8, 2017

Contributor

I think we decided that we were going to implement the new multijoinsplit algorithm in such a way that no more than one output of each JoinSplit would need a payment disclosure (because that reduces information leakage in vpubin,out values), and therefore that option 3 is not needed.

Contributor

daira commented Mar 8, 2017

I think we decided that we were going to implement the new multijoinsplit algorithm in such a way that no more than one output of each JoinSplit would need a payment disclosure (because that reduces information leakage in vpubin,out values), and therefore that option 3 is not needed.

@arielgabizon

This comment has been minimized.

Show comment
Hide comment
@arielgabizon

arielgabizon Mar 9, 2017

Contributor

OK, I guess if we're implementing JoinSplit that way it will be fine to give esk

Contributor

arielgabizon commented Mar 9, 2017

OK, I guess if we're implementing JoinSplit that way it will be fine to give esk

@daira daira modified the milestones: 1.0.9, 1.0.8 Mar 20, 2017

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Mar 24, 2017

Contributor

@bitcartel wrote:

Could the following help increase the level of confidence that a presenter of the payment disclosure is indeed the sender (where the sender did not include anything in the memo field) ?

  • Sender retains the ephemeral JoinSplitSig Private Key.
  • Sender uses this private key to sign a payment disclosure / refund address / message.
  • Recipient verifies signed data using the JoinSplitSig Public Key.

Yes, that's what I suggested in #737 (comment) . @nathan-at-least opened this ticket to be for something simpler. However I think we'll end up adding a signature, just not in the initial implementation.

Contributor

daira commented Mar 24, 2017

@bitcartel wrote:

Could the following help increase the level of confidence that a presenter of the payment disclosure is indeed the sender (where the sender did not include anything in the memo field) ?

  • Sender retains the ephemeral JoinSplitSig Private Key.
  • Sender uses this private key to sign a payment disclosure / refund address / message.
  • Recipient verifies signed data using the JoinSplitSig Public Key.

Yes, that's what I suggested in #737 (comment) . @nathan-at-least opened this ticket to be for something simpler. However I think we'll end up adding a signature, just not in the initial implementation.

@bitcartel

This comment has been minimized.

Show comment
Hide comment
@bitcartel

bitcartel Apr 24, 2017

Contributor

@daira et al remind me.. why can't we simply retain a record of the symmetric key used for each call to crypto_aead_chacha20poly1305_ietf_encrypt? In JoinSplit.cpp we use the same encryptor object for both note outputs, where for each output, the nonce input to the KDF is incremented in NoteEncryption::encrypt. The resulting symmetric key is different for each note output.

Edit: To (perhaps) answer my own question, with esk if a non-authorized party were to obtain a copy of the payment disclosure, they would still need to know the recipient's payment address in order to get pk_enc needed for decrypting the cipher text. In which case, it would be preferable to what I just wrote above.

Contributor

bitcartel commented Apr 24, 2017

@daira et al remind me.. why can't we simply retain a record of the symmetric key used for each call to crypto_aead_chacha20poly1305_ietf_encrypt? In JoinSplit.cpp we use the same encryptor object for both note outputs, where for each output, the nonce input to the KDF is incremented in NoteEncryption::encrypt. The resulting symmetric key is different for each note output.

Edit: To (perhaps) answer my own question, with esk if a non-authorized party were to obtain a copy of the payment disclosure, they would still need to know the recipient's payment address in order to get pk_enc needed for decrypting the cipher text. In which case, it would be preferable to what I just wrote above.

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Apr 24, 2017

Contributor

Only recording the secret key would not be sufficient information to prove that the recipient could have decrypted the note ciphertext from the block chain.

I was thinking that the payment disclosure would include pkenc, because it's supposed to be a proof that a given address received a payment, which necessarily reveals the address.

Contributor

daira commented Apr 24, 2017

Only recording the secret key would not be sufficient information to prove that the recipient could have decrypted the note ciphertext from the block chain.

I was thinking that the payment disclosure would include pkenc, because it's supposed to be a proof that a given address received a payment, which necessarily reveals the address.

@bitcartel

This comment has been minimized.

Show comment
Hide comment
@bitcartel

bitcartel Apr 24, 2017

Contributor

Wouldn't an arbitrator need the full payment address, rather than just pkenc ?

Contributor

bitcartel commented Apr 24, 2017

Wouldn't an arbitrator need the full payment address, rather than just pkenc ?

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Apr 25, 2017

Contributor

Given esk, pkenc, and the transaction visible on the block chain they can decrypt apk, they don't need to be given it explicitly. (If they were given it then they would still have to check it against the decrypted version.)

Edit: if we have multiple kinds of z-addresses in future, there could in general be information in an address, beside the encryption public key, that isn't in the commitment. Technically this is already the case because the commitment doesn't include whether it is a mainnet or testnet z-address. So the payment disclosure does need to include such information.

Contributor

daira commented Apr 25, 2017

Given esk, pkenc, and the transaction visible on the block chain they can decrypt apk, they don't need to be given it explicitly. (If they were given it then they would still have to check it against the decrypted version.)

Edit: if we have multiple kinds of z-addresses in future, there could in general be information in an address, beside the encryption public key, that isn't in the commitment. Technically this is already the case because the commitment doesn't include whether it is a mainnet or testnet z-address. So the payment disclosure does need to include such information.

@nathan-at-least nathan-at-least removed this from the 1.0.9 milestone May 10, 2017

@nathan-at-least

This comment has been minimized.

Show comment
Hide comment
@nathan-at-least

nathan-at-least May 10, 2017

Contributor

Bumped out of 1.0.9 which is focused on stabilization rather than big new features.

Contributor

nathan-at-least commented May 10, 2017

Bumped out of 1.0.9 which is focused on stabilization rather than big new features.

@bitcartel

This comment has been minimized.

Show comment
Hide comment
@bitcartel

bitcartel May 23, 2017

Contributor

@daira So to clarify, the payment disclosure should include the recipient's shielded payment address.
This would allow the recipient to verify that the payment disclosure belongs to / is relevant to them (since they have the spending key in their wallet for that payment address). It also means that any person looking to validate the payment disclosure would have apk and pkenc, where pkenc is required for decrypting the ciphertext.

Contributor

bitcartel commented May 23, 2017

@daira So to clarify, the payment disclosure should include the recipient's shielded payment address.
This would allow the recipient to verify that the payment disclosure belongs to / is relevant to them (since they have the spending key in their wallet for that payment address). It also means that any person looking to validate the payment disclosure would have apk and pkenc, where pkenc is required for decrypting the ciphertext.

@tromer

This comment has been minimized.

Show comment
Hide comment
@tromer

tromer Sep 15, 2017

Contributor

Is the payment disclosure supposed to convince a third party that doesn't trust the recipient (as implied in https://github.com/zcash/zips/pull/119/files)?

I think the current protocol doesn't achieve that: the sender and receipient can collude to lie to a third party. For example, suppose they want to hide the fact that they've transferring 100000000 zatoshis. They agree OOB on a note plaintext with v=100000000, but in the broadcast transaction the sender puts a ciphertext which is the encryption of a fake note plaintext with v=3. JoinSplit verification still passes (it never uses the note ciphertexts). And if they produce a payment disclosure using the fake note, the 3rd party verifier will accept it since it matches the ciphertext on the blockchain.

Contributor

tromer commented Sep 15, 2017

Is the payment disclosure supposed to convince a third party that doesn't trust the recipient (as implied in https://github.com/zcash/zips/pull/119/files)?

I think the current protocol doesn't achieve that: the sender and receipient can collude to lie to a third party. For example, suppose they want to hide the fact that they've transferring 100000000 zatoshis. They agree OOB on a note plaintext with v=100000000, but in the broadcast transaction the sender puts a ciphertext which is the encryption of a fake note plaintext with v=3. JoinSplit verification still passes (it never uses the note ciphertexts). And if they produce a payment disclosure using the fake note, the 3rd party verifier will accept it since it matches the ciphertext on the blockchain.

@tromer

This comment has been minimized.

Show comment
Hide comment
@tromer

tromer Sep 15, 2017

Contributor

Another attack on the ZIP's protocol, again exploiting inconsistency between ciphertext and JoinSplit:

The sender broadcasts a JoinSplit creating a low-value note, but attaches a ciphertext which is the encryption of a note plaintext claiming high value. He can then claim that he sent a high-value note, and present a payment disclosure that passes verification. But the recipient never received a high-value note, and the sender never nullified one.

Contributor

tromer commented Sep 15, 2017

Another attack on the ZIP's protocol, again exploiting inconsistency between ciphertext and JoinSplit:

The sender broadcasts a JoinSplit creating a low-value note, but attaches a ciphertext which is the encryption of a note plaintext claiming high value. He can then claim that he sent a high-value note, and present a payment disclosure that passes verification. But the recipient never received a high-value note, and the sender never nullified one.

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Sep 15, 2017

Contributor

Yes, I believe that payment disclosure proofs that are robust against collusion between the sender and recipient will only be possible with Sapling.

(In the current proposal on #2277, the correctness of epk and the note commitment, which contains esk, are both checked by the circuit, and so even though the correctness of the symmetric encryption isn't directly checked, it must be the case that either the note ciphertext is correct or the payment proof verifier can detect that it is not.)

Contributor

daira commented Sep 15, 2017

Yes, I believe that payment disclosure proofs that are robust against collusion between the sender and recipient will only be possible with Sapling.

(In the current proposal on #2277, the correctness of epk and the note commitment, which contains esk, are both checked by the circuit, and so even though the correctness of the symmetric encryption isn't directly checked, it must be the case that either the note ciphertext is correct or the payment proof verifier can detect that it is not.)

@tromer

This comment has been minimized.

Show comment
Hide comment
@tromer

tromer Sep 15, 2017

Contributor

@daira, the attack in #2036 (comment) doesn't require collusion.

In any case, the ZIP must be clearer about the claimed security properties of the protocol.

Contributor

tromer commented Sep 15, 2017

@daira, the attack in #2036 (comment) doesn't require collusion.

In any case, the ZIP must be clearer about the claimed security properties of the protocol.

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Sep 16, 2017

Contributor

I don't think that attack works: the note commitment revealed by the JoinSplit won't match the one computed from the decrypted note plaintext.

Contributor

daira commented Sep 16, 2017

I don't think that attack works: the note commitment revealed by the JoinSplit won't match the one computed from the decrypted note plaintext.

@tromer

This comment has been minimized.

Show comment
Hide comment
@tromer

tromer Sep 18, 2017

Contributor

The ZIP is ambiguous on what check is done (see https://github.com/zcash/zips/pull/119/files#r139325414), and the implementation PR does not verify the note commitment (https://github.com/zcash/zcash/pull/2159/files#r139326256).

Contributor

tromer commented Sep 18, 2017

The ZIP is ambiguous on what check is done (see https://github.com/zcash/zips/pull/119/files#r139325414), and the implementation PR does not verify the note commitment (https://github.com/zcash/zcash/pull/2159/files#r139326256).

@tromer

This comment has been minimized.

Show comment
Hide comment
@tromer

tromer Nov 21, 2017

Contributor

Can the receiver of a transaction generate a payment disclosure, that will convince a third party?
The ZIP (https://github.com/zcash/zips/pull/119/files) and doc (https://github.com/zcash/zcash/blob/master/doc/payment-disclosure.md) are both silent/ambiguous about this point.

Contributor

tromer commented Nov 21, 2017

Can the receiver of a transaction generate a payment disclosure, that will convince a third party?
The ZIP (https://github.com/zcash/zips/pull/119/files) and doc (https://github.com/zcash/zcash/blob/master/doc/payment-disclosure.md) are both silent/ambiguous about this point.

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Nov 23, 2017

Contributor

Not on their own, because they don't have the JoinSplit signature private key. I agree that the ZIP should say this explicitly. Note that anyone can replay a payment disclosure, but only with a message that was signed by a holder of the JoinSplit signature private key. So it is possible to do an interactive proof of payment by requiring a fresh nonce to be included in the message.

Contributor

daira commented Nov 23, 2017

Not on their own, because they don't have the JoinSplit signature private key. I agree that the ZIP should say this explicitly. Note that anyone can replay a payment disclosure, but only with a message that was signed by a holder of the JoinSplit signature private key. So it is possible to do an interactive proof of payment by requiring a fresh nonce to be included in the message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment