Skip to content

test(crypto): restore unequal-width MtA CT regression - #27

Merged
piotr-roslaniec merged 2 commits into
devfrom
codex/ct-unequal-width-regression
Sep 29, 2026
Merged

piotr-roslaniec merged 2 commits into
devfrom
codex/ct-unequal-width-regression

Conversation

@piotr-roslaniec

Copy link
Copy Markdown

Summary

Test-only PR that closes the one remaining test-only gap tracked from the #8/#10
supersession review (agent-docs/pr-integration/8-10.md, finding 17-S1).

#17 (codex/ct-defaults-and-bounds) backported all of #10's functional fixes onto
dev, but dropped #10's TestShareProtocolUnequalWidthsCTEquivalence instead of
adapting it. That test is the only guard that byte-exact-compares the complete MtA
share protocol
transcript (AliceInit → BobMid/BobMidWC → AliceEnd/AliceEndWC,
including all proof bytes, the homomorphic ciphertexts, and the decrypted shares)
across constant-time ops off vs on, with a q5-width betaPrm secret witness.

Regression this test catches

A future change that makes the CT path's secret-exponent modular arithmetic diverge
from the math/big path anywhere in the full share-protocol path would make the CT-on
transcript stop matching the CT-off one and fail this test. Concretely:

  • an exponent padding width reintroduced from the auxiliary modulus instead of
    the public plaintext bound (pk.N.BitLen(), per fix(crypto): handle CT exponent bounds, zero values, and toggle changes #10's ExpCTWithBitLen fix), or
  • any width/determinism change in the CT secret-exponent sites (h1^b, h1^betaPrm
    in ProveBobWC, h1^m in ProveRangeAlice, plus the CT Encrypt/HomoMult
    paths) that makes the two modes produce different bytes.

Without it, that regression class is uncaught in the full MtA path on dev.

Adaptation notes (dev vs #10)

  • Auxiliary modulus: dev's hardened verifiers enforce a 2048-bit
    unknown-order-modulus floor (verifyMinModulusBitLen), so the full protocol's
    internal Verify calls cannot complete against fix(crypto): handle CT exponent bounds, zero values, and toggle changes #10's tiny 11*23 modulus. This
    adaptation uses the keygen fixture's ~2048-bit auxiliary moduli
    (NTildei/h1i/h2i, NTildej/h1j/h2j from LoadNTildeH1H2FromTestFixture),
    matching the neighboring TestShareProtocolWCConstantTime. The betaPrm witness
    remains a q5-width random (up to five secp256k1 curve orders) exercised through
    the CT exponentiations with the pk.N.BitLen() width bound.
  • Width assertion: the fix(crypto): handle CT exponent bounds, zero values, and toggle changes #10 betaPrm.BitLen() > 8*len(NTilde.Bytes())+16
    assertion was sound only against the tiny modulus; with the 2048-bit fixture
    modulus it would be false. It is replaced by exact guards: betaPrm is a valid
    Paillier plaintext (betaPrm < pk.N), the homomorphic result does not wrap the
    plaintext domain, and the MtA shares sum to a*b mod q.
  • Isolation: ambient CT mode and the replayed entropy stream are set per subtest
    and restored on cleanup (same pattern as the sibling setMTAProofTestMode tests and
    fix(crypto): extend constant-time coverage to Schnorr proofs and signing rounds 3-5 #23's withCTMode isolation), so the test does not leak state into other tests and
    works under dev's default-on CT mode.
  • The test asserts on consumer-visible output (the serialized transcript bytes,
    proof parts, ciphertexts, and shares), not merely that the protocol does not panic.

Scope

Supersedes finding 17-S1 from agent-docs/pr-integration/8-10.md §5 ("Proposed
durable tests").

Restore the closed #10 test-only regression that #17 dropped when
backporting #10's functional fixes (finding 17-S1):
TestShareProtocolUnequalWidthsCTEquivalence in crypto/mta/constant_time_equiv_test.go.

The test byte-exactly compares the complete MtA share-protocol transcript
(AliceInit -> BobMid/BobMidWC -> AliceEnd/AliceEndWC, incl. all proof
bytes, homomorphic ciphertexts, and decrypted shares) with a fixed
replayed entropy stream across constant-time ops off vs on. It guards
the regression class where the CT path's secret-exponent modular
arithmetic diverges from the math/big path in the full share protocol:
an exponent padding width reintroduced from the auxiliary modulus
instead of the public plaintext bound (pk.N.BitLen()), or any width
change breaking CT-path determinism.

Adapted to the current APIs and dev's hardened verifiers:
- uses the keygen fixture's ~2048-bit auxiliary moduli (NTildei/h1i/h2i,
  NTildej/h1j/h2j) so the protocol's internal Verify calls complete,
  which is impossible with #10's tiny 11*23 modulus under dev's
  2048-bit unknown-order-modulus verifier floor.
- explicitly sets and restores the ambient CT mode per subtest via the
  same cleanup pattern as the sibling tests (the #23 withCTMode
  isolation pattern), and compares the consumer-visible transcript
  bytes, not just the absence of a panic.
- replaces the #10 'witness wider than aux modulus' width assertion
  (sound only against the tiny NTilde) with exact guards: betaPrm is a
  valid Paillier plaintext, the homomorphic result does not wrap the
  domain, and the MtA shares sum to a*b mod q.

No production code changes; no new dependencies; no timing assertions.
@piotr-roslaniec
piotr-roslaniec merged commit dec6df0 into dev Sep 29, 2026
2 checks passed
@piotr-roslaniec

Copy link
Copy Markdown
Author

Merged into dev.

Verification:

  • Test-only delta: one 81-line test in crypto/mta/constant_time_equiv_test.go; no production or dependency changes.
  • The full AliceInit -> BobMid/BobMidWC -> AliceEnd/AliceEndWC path produces byte-identical CT-on/off ciphertexts, proofs, masks, and shares under replayed entropy. It also asserts valid Paillier plaintext bounds, no plaintext-domain wrap, and shares summing to a*b mod q.
  • Uses real 2048-bit fixture auxiliary moduli, so it exercises the verifier floor that made fix(crypto): handle CT exponent bounds, zero values, and toggle changes #10's tiny-modulus version invalid on current dev.
  • Ambient CT mode is explicitly set/restored per subtest.
  • Focused test passes at -count=3; tidy/build/vet/format and full CI green.

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.

1 participant