Backport tBTC-relevant BNB v4 hardening#4
Open
mswilkison wants to merge 5 commits into
Open
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>
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.
piotr-roslaniec
approved these changes
May 23, 2026
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.