- ADVERSARIAL-MATRIX.md: 5-verifier per-primitive attack matrix + the four assurances - RELEASE-MANIFEST.toml pinned to final SHAs (consensus ConsensusCert envelope now on main) - gate upgrades: ec-machine-check.sh (compiles every .ec), comment-aware axiom-budget, PASS_WITH_OPEN_ASSUMPTIONS verdict + open_assumptions; p3q redteam cmd fixed - EC-toolchain-live corrections; corona C11 = lemma; gate-results regenerated (verdict PASS_WITH_OPEN_ASSUMPTIONS)
7.7 KiB
Adversarial evidence matrix — release 2026-06-pq-threshold-stack
Per-primitive attack → test → status, produced by five independent adversarial
verifiers (2026-06-21), each running real tests at the pinned commits.
PASS = the attack is rejected / fails closed (the test passes). This is the
"adversarial tests per primitive" layer of the certificate — evidence, not the
proof. Pinned commits: see RELEASE-MANIFEST.toml.
The four final assurances (the verdict)
- No hidden theorem-critical axioms.
circular-proof.shexit 0 on pulsar / corona / magnetar; every load-bearing axiom is acknowledged inreviewed-axioms.txt. Open C-assumptions are disclosed, never silently closed. - All bridge assumptions discharged, or explicitly standard/external. Corona
C11 is a machine-checked lemma (residual = the narrow public
threshold_public_commitment_eq_central). The remaining bridges reduce to Module-LWE/MSIS, FRI proximity-gap, SLH-DSA hash-family, honest-majority — the standardSTANDARD-ASSUMPTIONS.mdbedrock. - All implementation/spec bridges tested/reviewed. Pulsar verifies byte-for- byte under three independent FIPS-204 verifiers; corona EC 14/14; magnetar production leg verifies under unmodified FIPS-205 (circl).
- All public verifiers total over malformed input. Pulsar ~13M fuzz execs,
corona fuzz +
errors.Isrejection, magnetar 200-random+63-bitflip probe, p3q random-bytes totality, consensus 2.2M-exec fuzz — zero panics anywhere.
Pulsar — threshold ML-DSA (c0ebd3c / v1.1.4)
| Attack | Test (file:name) | Status |
|---|---|---|
| corrupt c | partial_proof_test.go:TestPartialProofBindingMutationsRejected |
PASS |
| corrupt z | partial_proof_test.go:TestPartialProofBadZRejected |
PASS |
| corrupt h | wire_test.go:TestPulsar_Wire_FIPS204Verifiable (+ CIRCL reject) |
PASS |
| wrong ctx | bcc_sign_test.go:TestBCCSignRoundTripWithContext |
PASS |
| wrong message | sign_test.go:TestSignVerify_WrongMessage_Rejected |
PASS |
| bad SampleInBall | partial_proof_test.go:TestPartialProofRejectsDegenerateChallenge (ErrChallengeNotInBall) |
PASS |
| inserted CS2/CT0/LowBits/fullW | consensus_test.go:TestNoHintSecretFieldsInProductionWireTypes + nonce_test.go:TestNonceCertHasNoFullW |
PASS |
| reused nonce | threshold_test.go:TestThresholdSign_DifferentAttempt_Rejected (+ Consumed anti-replay) |
PASS |
Verifier total (≈13M fuzz, zero panics; 4 GiB-declared/truncated/wrong-magic →
typed errors). Bridge: Pulsar_N1.ec/Pulsar_N1_NoLeak.ec ↔ ref/go/pkg/pulsar/*,
interop under own/CIRCL/pq-crystals. Hardening applied this pass: added
FullW/LowBitsW to the generic forbidden-field sweep (was NonceCert-specific).
Corona — threshold Module-LWE (6b4d5d5 / v0.7.8)
| Attack | Test | Status |
|---|---|---|
| duplicate signer | reshare_test.go:TestReshareInvalidArgs/duplicate_ID (+ kernel uniq-guard added this pass) |
PASS |
| wrong SID | sign/nonce_reuse_test.go:TestSignRound1_NonceFreshAcrossReusedSession |
PASS |
| partial replay | reshare/negative_transcript_test.go:TestNegativeTranscriptMutationsRejected |
PASS |
| bitmap rewrite (→ signer-set/transcript) | negative_transcript_test.go (new_set_hash/threshold_*) |
PASS |
| malformed share encoding | threshold/wire_test.go:TestSignatureWireRejectMalformed + 6 FuzzCorona* |
PASS |
threshold_public_commitment mismatch |
dkg2/dkg2_test.go:TestDKG2_CommitDigestEquivocation |
PASS |
| combine proof dependency deletion | EC /tmp mutation: removing no_leak_z_aggregate → cannot close goals (exit 1); removing threshold_public_commitment_eq_central → cannot close goals (exit 1) |
PASS |
Verifier total (fuzz + errors.Is; surfaced 2 real lattice OOM/DoS surfaces,
pre-validated before allocation). Bridge: Corona_N1_Combine_Wrapper.ec ↔
threshold/threshold.go (Finalize/Round2), sign/sign.go; C11 = lemma.
Magnetar — threshold SLH-DSA (468e4e7 / v1.2.2)
Reframe: Magnetar is stateless FIPS-205 SLH-DSA — attacks framed for stateful schemes (leaf reuse / rollback / concurrent reservation / FORS-WOTS reuse) have no leaf-reservation surface; they map to the THBS-SE slot discipline.
| Attack (mapped) | Test | Status |
|---|---|---|
| slot reuse (← leaf reuse) | thbsse_test.go:TestThbsSE_SlotReuseRejected (equivocation evidence) |
PASS |
| wrong ADRS | thbsse_assemble_test.go:TestSlhdsaInternal_ByteEqualToCirclSign (any ADRS error breaks identity) |
PASS |
| seed export (production) | pvss_dkg_test.go:TestPVSS_DKG_ProductionTranscriptHidesMaster + build-gate added this pass |
PASS |
| share-material reuse (← FORS/WOTS) | TestThbsSE_RejectSeedReveal + RejectTamperedShareCommitMismatch |
PASS |
| rollback / concurrent-slot | (in-memory state; standalone leg stateless) | tests added this pass |
Verifier total (200-random+63-bitflip+shaped, zero panic). Production leg verifies
under unmodified FIPS-205 (circl); THBS-SE honestly research-only; no hidden axioms
(0/0/0). Hardening applied this pass: the seed-reconstructing assembleSignatureBytes
is now build-gated (//go:build !production), not prose-gated.
P3Q — STARK/FRI substrate (96f7db4 / v0.0.2)
| Attack | Test | Status |
|---|---|---|
| zero-constraint AIR | prover.rs:f4_zero_constraint_air_is_refused_by_{prover,verifier} |
PASS ×2 |
| transition-domain mismatch | prover.rs:f3_terminating_counter_is_rejected (is_transition excised; full vanishing poly) |
PASS |
| malformed FRI metadata | engine.rs:f2_adversarial_shape_returns_typed_error_no_panic + wire header rejects |
PASS ×6 |
| unbounded log values | prover.rs:f1_oversized_log_{blowup,trace_rows}_returns_typed_error_no_panic (catch_unwind) |
PASS ×2 |
| Merkle query-index confusion | verifier/lib.rs:echoed_query_index_mismatch_rejected + tampered-root rejects |
PASS ×6 |
verify_air total (zero unwrap/panic in production paths). zchain circuits are
audit-gated stubs (no Air impl). Deps PQ-clean (lint_forbidden.sh, CI-wired).
FRI proximity-gap disclosed as the standard conjecture. Fix applied this pass:
prove-release.sh p3q redteam command corrected (the redteam=warn was an invalid
multi-positional cargo test, not a coverage hole).
Consensus — finality cert (9b389ce origin/main)
The six envelope attacks are weighted-quorum-cert semantics; the canonical
ConsensusCert (certification, policy-gated) covers all six. Origin's CertPolicy
threshold-sig is independently fail-closed + total for its shape. Coverage lands
on the single unified envelope (the port + envelope pass): signer-count overflow,
duplicate weight, out-of-set signer, caller-supplied payload root, bitmap/sig
mismatch, cross-domain replay — each with a named test (see consensus_cert_test.go
quorum_redteam_test.go).VerifyWithRealKeysfail-closed (blsAggPubKey==nil && !verifiedAnyPQ → false);UnmarshalBinarytotal (2.2M-exec fuzz, zero panics). Build-integrity: consensusgo.sum[email protected]re-pinned to the canonical transparency-log hashes (force-republish divergence fixed).
Open hardening (remediated this pass, none release-blocking)
- corona kernel
uniq-PartyID guard (was caller-enforced) · magnetar seed-reconstruct build-gate (was prose-gated) · pulsar genericFullWfield guard · p3q prove-release command · doc/version nits. All tracked to PASS in the per-repo gates.
Standard assumptions (irreducible — stated, not "proven")
Module-LWE / Module-SIS (ML-DSA-65 Cat 3); SLH-DSA SHAKE hash-family EU-CMA
(SLH-DSA-192s Cat 3); FRI proximity-gap soundness; SHAKE/cSHAKE/KMAC as RO;
honest-validator BFT threshold. See STANDARD-ASSUMPTIONS.md. No pairing / DLOG /
factoring / trusted-setup — that absence is "fully PQ".