Skip to content
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

Replay protection fix #1867

Merged
merged 8 commits into from
Oct 24, 2023
Merged

Replay protection fix #1867

merged 8 commits into from
Oct 24, 2023

Conversation

grarco
Copy link
Contributor

@grarco grarco commented Sep 6, 2023

Describe your changes

Closes #1530.
Closes #1683.

This PR includes the signature on the raw transaction header made by the inner tx signer(s) and the corresponding validation in the VPs.

It also fixes the replay protection issue but in a different way than the one discussed in #1530. There we stated that the problem was that using the raw transaction header to avoid replaying the inner transaction was flawed because the hash of this header can be trivially modified by changing some of its field. This problem is actually solved if we force a signature on the raw header which cannot be modified anymore. So, to summarize:

  • The signer(s) of the inner transaction sign the Raw transaction header
  • We keep the current implementation of replay protection based on two hashes:
    • Hash of the Wrapper header
    • Hash of the Raw header
  • Given that the header contains the commitments to Data and Code these sections are not signed anymore (we sign the header with the commitments and than check the validity of these commitments)
  • Masp section doesn't need to be replay protected nor signed and a commitment to it is present in the Data section
  • ExtraData section doesn't need to be replay protected. A commitment to this optional section is present in Data
  • Since neither the Masp nor the ExtraData sections are mentioned in the header, adding, modifying or removing these sections wouldn't change the hash used for replay protection (but would still invalidate the commitments). So no malleability attack of these section can deceive the replay protection mechanism (of course the real signers of the tx can always produce valid transactions with different Masp or ExtraData sections simply by changing the hash of the header)
  • The only problem could be in case a transaction carried more than one Data or Code section. In this case, since we don't sign these sections directly anymore, malleability attacks could be mounted on the transaction. Still, this is a use case which we are not considering at the moment, and, in case, I suspect that we should add commitments for each of these sections in the header. The signatures alone, indeed, would not prevent a malicious user from modifying these sections. By adding these commitments, the safety of the transaction should be guaranteed.

Also, given that the header of both the inner and wrapper tx must match (expect for the TxType), this PR removes some checks on the raw header hash that don't make sense anymore, together with the corresponding error codes and some unit tests.

Indicate on which release or other PRs this topic is based on

v0.23.0

Checklist before merging to draft

  • I have added a changelog
  • Git history is in acceptable state

@grarco grarco force-pushed the grarco/fix-replay-protection branch 3 times, most recently from 15a2c6e to 7667d5b Compare September 7, 2023 14:35
@grarco grarco marked this pull request as ready for review September 8, 2023 16:15
@grarco grarco force-pushed the grarco/fix-replay-protection branch 2 times, most recently from 4c21ed9 to 0651ca3 Compare September 27, 2023 19:48
@murisi
Copy link
Contributor

murisi commented Sep 28, 2023

Since neither the Masp nor the ExtraData sections are mentioned in the header, adding, modifying or removing these sections wouldn't change the hash used for replay protection (but would still invalidate the commitments). So no malleability attack of these section can deceive the replay protection mechanism.

Hi @grarco , thanks for looking into the replay protection issues. If the Masp, ExtraData, or inner Signature section is tampered with, when would it be detected that the commitments have been invalidated? Before the gas fee is deducted from the wrapper signer or after? I am thinking back to the issue you brought up here: #1567 .

@murisi
Copy link
Contributor

murisi commented Sep 28, 2023

Also, given that the hardware wallet code is being frozen for auditing, is there a way to solve some of these issues without modifying the transaction format or the signing algorithm? Like, could we not somehow store the hash of the signature section over the wrapper, and the hash of the signature section over (data, code, MASP, extras) (as returned by verify_signatures) in replay storage? cc @adrianbrink

@grarco
Copy link
Contributor Author

grarco commented Sep 28, 2023

Since neither the Masp nor the ExtraData sections are mentioned in the header, adding, modifying or removing these sections wouldn't change the hash used for replay protection (but would still invalidate the commitments). So no malleability attack of these section can deceive the replay protection mechanism.

Hi @grarco , thanks for looking into the replay protection issues. If the Masp, ExtraData, or inner Signature section is tampered with, when would it be detected that the commitments have been invalidated? Before the gas fee is deducted from the wrapper signer or after? I am thinking back to the issue you brought up here: #1567 .

So if the tampering happens directly on the encrypted sections, it's discovered while validating the wrapper transaction, so the tx is discarded and no fees are paid. This is because the wrapper signer still signs over all of the sections. If instead the tampering happens on the sections before they are encrypted, it gets discovered when we run the decrypted transaction, so after the fees have been paid. But this scenario can only happen if:

  • The tampering has been performed by the wrapper signer themselves
  • The tampering happened on the communication channel between the wrapper signer and the entity that produced the inner tx, still the wrapper signer is responsible for checking the validity of the received message

So fee payment looks correct to me in this case

@grarco
Copy link
Contributor Author

grarco commented Sep 28, 2023

Also, given that the hardware wallet code is being frozen for auditing, is there a way to solve some of these issues without modifying the transaction format or the signing algorithm? Like, could we not somehow store the hash of the signature section over the wrapper, and the hash of the signature section over (data, code, MASP, extras) (as returned by verify_signatures) in replay storage? cc @adrianbrink

I see, so this PR, if correct, I think proposes the least effort (in terms signatures effort) but it requires changing the Signature section format (and therefore the tx format) and also the signing algorithm. This is because the PR aims at closing #1683 too, it actually comes down to collapsing this and #1530 to the same problem, the lack of a signature on the Header coming from the inner tx signer.

The Signature struct has been changed in a single field, the targets field which has been turned from a Vec to a single Hash: in theory we can bring back the Vec without any problem (it will simply be a vector of one element).

For the signing algorithm we could do more or less the same, just revert it to the previous version's implementation (expecting an array of hashes) even though we'll provide only one hash.

If instead we are somehow bounded to the specific section's hashes that we pass to a signature, than of course non of this can be applied and we should probably stick to the solution proposed in #1530 (lexicographically sorted concatenation of sections' hashes), though this would not solve in any way the missing signature on the header

@grarco grarco force-pushed the grarco/fix-replay-protection branch from 0651ca3 to e6b0392 Compare October 4, 2023 17:36
grarco added a commit that referenced this pull request Oct 12, 2023
@grarco grarco force-pushed the grarco/fix-replay-protection branch from e6b0392 to bbf3d1a Compare October 12, 2023 16:19
grarco added a commit that referenced this pull request Oct 13, 2023
@grarco grarco force-pushed the grarco/fix-replay-protection branch from bbf3d1a to a607830 Compare October 13, 2023 16:59
grarco added a commit that referenced this pull request Oct 13, 2023
@grarco grarco force-pushed the grarco/fix-replay-protection branch from a607830 to b614a3f Compare October 13, 2023 21:00
@Fraccaman
Copy link
Member

is this mergeable in 0.24.0?

@Fraccaman Fraccaman mentioned this pull request Oct 16, 2023
grarco added a commit that referenced this pull request Oct 19, 2023
grarco added a commit that referenced this pull request Oct 19, 2023
@grarco grarco force-pushed the grarco/fix-replay-protection branch from b614a3f to acdcd28 Compare October 19, 2023 21:49
murisi
murisi previously approved these changes Oct 23, 2023
Copy link
Contributor

@murisi murisi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks!

@murisi murisi dismissed their stale review October 23, 2023 09:13

Oops, just realized that there will be issue with CompressedSignature section that will break web client.

Copy link
Contributor

@murisi murisi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. There's just a minor issue with CompressedSignature expansion.

.DS_Store Outdated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file supposed to be here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah definitely not 👍🏻

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CompressedSignature is the compressed form of a Signature returned by the hardware wallet. The software client expands it before sending it off to the protocol. Here, line 630 always expands the 0th index to the header_hash(). So how can we allow the hardware wallet to specify that a signature is over the raw_header_hash()? I'm thinking that we can use the sentinel index 255 to specify tx.raw_header_hash(). Like:

} else if idx == 255 {
    /// The 255th section is the raw header
    targets.push(tx.raw_header_hash());
} else {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! Yes I think this solution works fine

@grarco grarco force-pushed the grarco/fix-replay-protection branch from acdcd28 to c40cbc1 Compare October 23, 2023 10:02
Fraccaman added a commit that referenced this pull request Oct 23, 2023
* origin/grarco/fix-replay-protection:
  Changelog #1867
  Fixes raw header hash in compressed signature
  Removes redundant signature on `Code` and `Data`
  Client signs the raw transaction header
  Adds raw header signature in tests
  Removes useless checks on decrypted tx, error codes and unit tests
  Adds `raw_header_hash` method for `Tx`
  Inner tx signer also signs tx header
tzemanovic added a commit that referenced this pull request Oct 24, 2023
* origin/grarco/fix-replay-protection:
  Changelog #1867
  Fixes raw header hash in compressed signature
  Removes redundant signature on `Code` and `Data`
  Client signs the raw transaction header
  Adds raw header signature in tests
  Removes useless checks on decrypted tx, error codes and unit tests
  Adds `raw_header_hash` method for `Tx`
  Inner tx signer also signs tx header
@tzemanovic tzemanovic mentioned this pull request Oct 24, 2023
@tzemanovic tzemanovic merged commit c40cbc1 into main Oct 24, 2023
10 of 14 checks passed
@tzemanovic tzemanovic deleted the grarco/fix-replay-protection branch October 24, 2023 11:26
@grarco grarco mentioned this pull request Oct 24, 2023
2 tasks
brentstone pushed a commit that referenced this pull request Nov 11, 2023
* origin/grarco/fix-replay-protection:
  Changelog #1867
  Fixes raw header hash in compressed signature
  Removes redundant signature on `Code` and `Data`
  Client signs the raw transaction header
  Adds raw header signature in tests
  Removes useless checks on decrypted tx, error codes and unit tests
  Adds `raw_header_hash` method for `Tx`
  Inner tx signer also signs tx header
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Inner tx signer to sign the Header too Replay protection wrong hash
4 participants