Backport tBTC-relevant BNB v4 hardening#4
Merged
Conversation
This was referenced May 21, 2026
492bdd6 to
c09f596
Compare
mswilkison
added a commit
that referenced
this pull request
May 21, 2026
Doc + small defensive-code follow-ups to the PR #2/#4/#5 review thread. None of these are security-blocking; they close out the cosmetic and pre-existing items that did not warrant their own PR earlier. - common/hash_utils.go: strengthen RejectionSample doc so the name does not mislead future readers — the function is modular reduction, not true rejection sampling, and the bias bound depends on q vs the hash width. - crypto/paillier/factor_proof.go: document that the tagged and legacy FactorChallenge paths emit different challenge distributions (positive-only vs signed), and note that FactorVerify's CmpAbs bounds exist to accommodate the legacy signed encoding. - tss/params.go: expand SetSessionNonceBytes docstring with the collision/uniqueness/entropy guidance reviewers asked for. - ecdsa/{keygen,signing}/rounds.go: document the round-1-capture invariant for getSSID so future refactors do not silently drift the hashed round.number domain separator. - crypto/ecpoint.go: flag SetCurve's in-place mutation in the doc comment; the chained-call style is a footgun on shared points. - crypto/vss/feldman_vss.go: reject nil shares, nil/zero share IDs, and duplicate IDs in ReConstruct before the Lagrange loop, so malformed inputs return an error instead of panicking through ModInverse(0). Add focused test coverage for each rejection path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
piotr-roslaniec
approved these changes
May 23, 2026
piotr-roslaniec
pushed a commit
that referenced
this pull request
Jun 15, 2026
Doc + small defensive-code follow-ups to the PR #2/#4/#5 review thread. None of these are security-blocking; they close out the cosmetic and pre-existing items that did not warrant their own PR earlier. - common/hash_utils.go: strengthen RejectionSample doc so the name does not mislead future readers — the function is modular reduction, not true rejection sampling, and the bias bound depends on q vs the hash width. - crypto/paillier/factor_proof.go: document that the tagged and legacy FactorChallenge paths emit different challenge distributions (positive-only vs signed), and note that FactorVerify's CmpAbs bounds exist to accommodate the legacy signed encoding. - tss/params.go: expand SetSessionNonceBytes docstring with the collision/uniqueness/entropy guidance reviewers asked for. - ecdsa/{keygen,signing}/rounds.go: document the round-1-capture invariant for getSSID so future refactors do not silently drift the hashed round.number domain separator. - crypto/ecpoint.go: flag SetCurve's in-place mutation in the doc comment; the chained-call style is a footgun on shared points. - crypto/vss/feldman_vss.go: reject nil shares, nil/zero share IDs, and duplicate IDs in ReConstruct before the Lagrange loop, so malformed inputs return an error instead of panicking through ModInverse(0). Add focused test coverage for each rejection path.
5e9e99e to
e041e82
Compare
The round-9 `!ok || len(values) != 4` guard prevents a malicious peer from binding their commitment to more than four secrets, sending the same payload back as the decommitment, and letting round 9 silently read `values[0..3]` as attacker-chosen Uj/Tj coordinates. No hash collision is required, since the attacker controls both C and D in their own messages. Extract the check into `decommitFour` and add focused tests that fail when the operator is reverted to `&&` (the pre-fix logic).
`hasBitLen` was tightened from `>= bits` to `== bits` in the review-feedback pass of this hardening series, and the same exact-equality contract lives in `ecdsa/keygen/round_2.go`. Existing tests cover BitLen=1 (way under) and BitLen=2049 (over by one) but leave the just-below-2048 case implicit; add explicit assertions in both the keygen and resharing message test files so a future relaxation of the comparison cannot silently let a 2047-bit modulus through.
Record the tBTC-relevant BNB bnb-chain#332 defensive hardening as non-breaking entries (EC point/Schnorr/DLN/FactorProof/MtA/VSS verifier guards, the round-9 decommitment and round-4 nil-inverse fixes, and the keygen round-1 modulus-width check), plus the new mta.ErrRangeProofVerify sentinel. Tag entries with PR #4 and add it to the composing-PRs list. No new wire/source breaking changes vs PR #2.
e041e82 to
ee9b6c5
Compare
piotr-roslaniec
pushed a commit
that referenced
this pull request
Jun 15, 2026
Doc + small defensive-code follow-ups to the PR #2/#4/#5 review thread. None of these are security-blocking; they close out the cosmetic and pre-existing items that did not warrant their own PR earlier. - common/hash_utils.go: strengthen RejectionSample doc so the name does not mislead future readers — the function is modular reduction, not true rejection sampling, and the bias bound depends on q vs the hash width. - crypto/paillier/factor_proof.go: document that the tagged and legacy FactorChallenge paths emit different challenge distributions (positive-only vs signed), and note that FactorVerify's CmpAbs bounds exist to accommodate the legacy signed encoding. - tss/params.go: expand SetSessionNonceBytes docstring with the collision/uniqueness/entropy guidance reviewers asked for. - ecdsa/{keygen,signing}/rounds.go: document the round-1-capture invariant for getSSID so future refactors do not silently drift the hashed round.number domain separator. - crypto/ecpoint.go: flag SetCurve's in-place mutation in the doc comment; the chained-call style is a footgun on shared points. - crypto/vss/feldman_vss.go: reject nil shares, nil/zero share IDs, and duplicate IDs in ReConstruct before the Lagrange loop, so malformed inputs return an error instead of panicking through ModInverse(0). Add focused test coverage for each rejection path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
piotr-roslaniec
added a commit
that referenced
this pull request
Jun 15, 2026
Add the exported tss.ReSharingParameters / NewReSharingParameters and crypto.ECPoint.EightInvEight removals to the Removed section (both are source/compile breaks), correct the source-compatibility note that wrongly claimed a single source break, drop the stale EightInvEight reference from the PR #4 EC-guard entry, and fix the protob/message.proto attribution.
piotr-roslaniec
pushed a commit
that referenced
this pull request
Jun 15, 2026
Doc + small defensive-code follow-ups to the PR #2/#4/#5 review thread. None of these are security-blocking; they close out the cosmetic and pre-existing items that did not warrant their own PR earlier. - common/hash_utils.go: strengthen RejectionSample doc so the name does not mislead future readers — the function is modular reduction, not true rejection sampling, and the bias bound depends on q vs the hash width. - crypto/paillier/factor_proof.go: document that the tagged and legacy FactorChallenge paths emit different challenge distributions (positive-only vs signed), and note that FactorVerify's CmpAbs bounds exist to accommodate the legacy signed encoding. - tss/params.go: expand SetSessionNonceBytes docstring with the collision/uniqueness/entropy guidance reviewers asked for. - ecdsa/{keygen,signing}/rounds.go: document the round-1-capture invariant for getSSID so future refactors do not silently drift the hashed round.number domain separator. - crypto/ecpoint.go: flag SetCurve's in-place mutation in the doc comment; the chained-call style is a footgun on shared points. - crypto/vss/feldman_vss.go: reject nil shares, nil/zero share IDs, and duplicate IDs in ReConstruct before the Lagrange loop, so malformed inputs return an error instead of panicking through ModInverse(0). Add focused test coverage for each rejection path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacked on #2. This draft backports the BNB bnb-chain#332 fixes that map cleanly to Threshold's current ECDSA/tBTC path without taking BNB's v4 module-path churn or EdDSA/package cleanup.
Included:
Alphaand nil input guards.FactorProofW1,W2,Sigma, andVabsolute bounds.ECPointscalar multiplication returns nil on invalid inputs.&&to||.mta.ErrRangeProofVerifyand signing-round attribution text for peer range-proof rejection.Review follow-up:
ScalarMultErr/ScalarBaseMultErrpublic API surface.BobMid/BobMidWCcallers are inecdsa/signing/round_2.go, wheremta.ErrRangeProofVerifyattribution is now wired.Alphacheck is verifier-only tightening. Honest provers already produceAlphain(1, N); this rejects malformed values that previously only passed after reduction moduloN.edwards.PrivKeyFromScalaras a fixed-width 32-byte buffer.Alphaand nilTentries.ProofBobWC.Verifynil result check afterxE.Add(pf.U)explicit.decommitFour, mutation-detectable against the&&→||fix) and the just-below-2048 boundary of the keygen/resharinghasBitLenchecks.Not included in this draft:
KGRound2Message2NTilde proof field. Threshold's fork already carries and verifiesmodproof_tildein ECDSA keygen round 1, so this needs separate review before adding another wire field.Validation
go test -count=1 ./crypto ./crypto/dlnproof ./crypto/mta ./crypto/paillier ./crypto/schnorr ./crypto/vss ./ecdsa/keygen ./ecdsa/signinggo test -count=1 ./ecdsa/resharinggo test -count=1 ./eddsa/keygen ./eddsa/signing ./eddsa/resharinggo test -count=1 ./crypto/mta ./ecdsa/signingafter the final MtA nil-guard tweakgo test -count=1 -timeout 25m ./ecdsa/keygenafter the review follow-up commitgo test -count=1 -timeout 25m ./eddsa/keygenafter the CI scalar-width flake fixgo test -count=1 ./crypto/dlnproof ./crypto/mtaafter the Gemini follow-up commitgit diff --checkgo test -count=1 -run TestDecommitFour ./ecdsa/signingandgo test -count=1 -timeout 25m ./ecdsa/keygen ./ecdsa/resharingafter the new test additions.