-
Notifications
You must be signed in to change notification settings - Fork 955
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
Replay protection fix #1867
Conversation
15a2c6e
to
7667d5b
Compare
4c21ed9
to
0651ca3
Compare
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 . |
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 |
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:
So fee payment looks correct to me in this case |
I see, so this PR, if correct, I think proposes the least effort (in terms signatures effort) but it requires changing the The 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 |
0651ca3
to
e6b0392
Compare
e6b0392
to
bbf3d1a
Compare
bbf3d1a
to
a607830
Compare
a607830
to
b614a3f
Compare
is this mergeable in 0.24.0? |
b614a3f
to
acdcd28
Compare
There was a problem hiding this 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!
Oops, just realized that there will be issue with CompressedSignature section that will break web client.
There was a problem hiding this 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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah definitely not 👍🏻
There was a problem hiding this comment.
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 {
There was a problem hiding this comment.
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
acdcd28
to
c40cbc1
Compare
* 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
* 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
* 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
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:
Raw
transaction headerWrapper
headerRaw
headerData
andCode
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 theData
sectionExtraData
section doesn't need to be replay protected. A commitment to this optional section is present inData
Masp
nor theExtraData
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 differentMasp
orExtraData
sections simply by changing the hash of the header)Data
orCode
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