Skip to content

docs: add audit.md threat model + protocol-by-protocol security notes (closes #5)#8

Open
abhicris wants to merge 6 commits intoluxfi:mainfrom
abhicris:docs/audit-md
Open

docs: add audit.md threat model + protocol-by-protocol security notes (closes #5)#8
abhicris wants to merge 6 commits intoluxfi:mainfrom
abhicris:docs/audit-md

Conversation

@abhicris
Copy link
Copy Markdown

Closes #5.

Lands a substantive docs/audit.md that gives downstream integrators the information a security-minded evaluator actually needs: adversarial model, tolerance bounds protocol-by-protocol, post-quantum assumptions, deployment-level controls, and an honest audit-status statement.

Structure

  1. Threat model — static, malicious, rushing adversary; what is and isn't modelled (adaptive corruption, DoS, physical side channels); network and randomness assumptions; pointer to the echo-then-agree broadcast primitive in docs/Broadcast.md.
  2. Protocol-by-protocol security notes for every protocol in the tree:
    • CMP — CCS 2020 / eprint 2020/492 (and the 2021 update eprint 2021/060), t - 1 out of n dishonest-majority, Paillier + Strong-RSA + ROM assumptions, caveat that identifiable abort is only identifiable against the reference implementation.
    • FROST — SAC 2020 / eprint 2020/852 + the two-round OMDL analysis eprint 2023/899, t - 1 out of n, targets the committed-nonce-pair variant (not the vulnerable single-nonce FROST1), BIP-340 / SR25519 serialization notes.
    • LSS — Seesahai 2025, composes over CMP, dishonest-majority bound plus the reshare-cohort intersection requirement, rollback caveat (do not roll back past a compromise-triggered reshare).
    • Doerner — IEEE S&P 2018 / eprint 2018/499, 2-of-2 only, zero fault tolerance (splitting primitive, not BFT), VOLE/correlated-OT-based.
    • Ringtail — lattice, M-LWE / M-SIS, explicit warning that it has not been independently audited and is younger than classical schemes; hybrid-mode guidance.
  3. BFT tolerance bounds — quick reference table and an explanation of why threshold signing uses t - 1 out of n rather than t < n/3 (BFT-consensus bound), plus what changes when you compose with a BFT layer.
  4. Post-quantum assumptions — classical protocols don't survive Shor; Ringtail relies on M-LWE / M-SIS; hybrid-mode recipe (compose with ML-DSA / Dilithium) and an in-place migration path.
  5. Deployment considerations — share storage, refresh cadence, HSM integration (cross-linked to docs/hsm-integration.md from the HSM PR), audit logging, secure channels, broadcast.
  6. Audit status — no external audit yet (honest); upstream primitive audits (secp256k1 via decred/dcrd, Paillier adapted from taurushq-io/multi-party-sig, Ed25519 via filippo.io/edwards25519, BLAKE3 via lukechampine.com/blake3); responsible-disclosure process at security@lux.network; empty audit log table ready for future entries.
  7. Further reading — links to the existing Threshold.md, FROST.md, Broadcast.md, protocols/lss/README.md, and the companion hsm-integration.md.

Cross-checks

  • Protocol claims verified against the package headers and Keygen / Sign / Refresh signatures in protocols/cmp/cmp.go, protocols/frost/frost.go, protocols/lss/lss.go, protocols/doerner/doerner.go, and protocols/ringtail/ringtail.go.
  • FROST SR25519 caveat traced to the existing protocols/frost/frost_sr25519_test.go.
  • Curve / Paillier parameter notes traced to docs/Threshold.md and the pkg/paillier/ implementation.
  • No claim is made that any primitive has been audited in the context of this library; upstream audits are called out only as covering the primitive in isolation.

Relation to PR #7

There is an existing PR #7 on this repo (from the kcolbchain fork) that lands a shorter, lighter audit.md plus README link fixes. This PR subsumes the content of that one — same honest audit-status framing, same upstream-primitive attribution, same responsible-disclosure process — but adds the threat model, protocol-by-protocol detail, BFT bounds, PQ discussion, and deployment-considerations sections that issue #5 evaluators actually need. Happy for maintainers to pick whichever is preferred; I can rebase this atop #7 (or vice versa) or cherry-pick individual sections if splitting is useful.

hanzo-dev and others added 6 commits April 7, 2026 00:00
First practical threshold signature scheme compatible with NIST FIPS 204
ML-DSA. Outputs byte-identical standard ML-DSA signatures, enabling drop-in
replacement of classical threshold ECDSA/Schnorr wallets with a PQ scheme
that keeps the standardized verification path.

Paper: Celi, del Pino, Espitau, Niot, Prest — Efficient Threshold ML-DSA,
USENIX Security Symposium 2026.

Files:
- papers/threshold-mldsa.tex — paper summary + integration notes (LaTeX)
- protocols/mldsa/doc.go — package doc
- protocols/mldsa/params.go — (T,N) × level parameter tables (44/65/87)
  from paper Tables 3, 10, 11
- protocols/mldsa/rss.go — replicated secret sharing with hardcoded optimal
  partitions for 2 ≤ T ≤ N ≤ 6 (Appendix B, Algorithm 6)
- protocols/mldsa/hrej.go — imbalanced hyperball rejection (Fig. 4)
  — mathematical spec stub, ring ops pending CIRCL integration
- protocols/mldsa/rss_test.go — 6 tests covering subsets, recovery
  completeness, balance bounds, parameter coverage

Config range: 2 ≤ T ≤ N ≤ 6 (2-of-3, 3-of-5, etc.)
Security: static dishonest-majority in ROM under MLWE + ML-DSA unforgeability.
Rounds: 3 per attempt, K parallel instances for ≥ 1/2 success probability.
Bench harness for 3 / 5 / 10 / 100 node PQ signing patterns:
  - individual: each validator signs, no aggregation (baseline)
  - committee:  k-of-n sample signs, the LP-045 cluster cert
  - hierarchical: n validators in M clusters (LP-045 two-layer)

Uses deterministic light mnemonic derivation — 100 validators from a
single 32-byte master seed, no interactive keygen, no mainnet keys.

Results on MacBook M3 / 10 cores / arm64 at ML-DSA-44:
  n=100 individual: 8.87 ms sign / 3.57 ms verify / 242 kB
  n=100 committee (k=32): 3.57 ms sign / 4.14 ms verify / 77 kB
  n=100 hierarchical (4 clusters): 14.7 ms sign / 5.35 ms verify

Committee sampling cuts signing cost 3× vs all-100 signing.
ML-DSA-65 is ~3× slower. Even at Level III, 100 validators sign in
<30 ms per block — fine for quasar finality at any realistic block time.

.gitignore: scope mldsa-bench binary ignore to repo root only
so the cmd/mldsa-bench/ source dir is tracked.
Adds -mode=fixed which samples a fixed k-size committee regardless of
total validator count N. Proves the scale-invariance claim in LP-045 +
the PQ-finality-without-BLS proof (~/work/lux/proofs).

Measured on MacBook M3 (arm64, 10 cores) at ML-DSA-44, k=128:
  N=1,000     sign=7.9ms  verify=3.2ms  cert=310 kB
  N=10,000    sign=7.4ms  verify=3.2ms  cert=310 kB
  N=100,000   sign=7.8ms  verify=3.4ms  cert=310 kB
  N=100,000 (ML-DSA-65): sign=10.8ms verify=5.9ms cert=424 kB

Same cost from 10^3 to 10^5 validators. Only the VRF-based sampling
touches N, and that is O(log N) in a weighted-reservoir implementation.
…closes luxfi#5)

Land docs/audit.md covering:

  1. Threat model — static, malicious, rushing adversary; adaptive
     corruption / DoS / physical side channels out of scope; network
     and randomness assumptions.
  2. Protocol-by-protocol notes for CMP, FROST, LSS, Doerner, and
     Ringtail: reference papers (with eprint links), tolerance
     bound the proof gives, assumptions the proof relies on,
     implementation caveats specific to this repo.
  3. BFT tolerance bounds — quick reference table plus a note on
     why the bound is t-1-out-of-n for threshold signing and not
     t<n/3 as in BFT consensus.
  4. Post-quantum assumptions — classical protocols do not survive
     a Shor-capable adversary; Ringtail relies on M-LWE / M-SIS;
     hybrid-mode guidance for long-lived custody.
  5. Deployment considerations — share storage, rotation, HSM
     integration (cross-linked to docs/hsm-integration.md), audit
     logging, secure channels, broadcast primitive.
  6. Honest audit status — no external audit yet; upstream primitive
     audits (secp256k1 via dcrd, Paillier via taurushq, Ed25519 via
     filippo, BLAKE3 via lukechampine) documented; responsible
     disclosure process; empty audit log for future entries.

Protocol claims cross-checked against the actual code in
protocols/cmp/, protocols/frost/, protocols/lss/, protocols/doerner/,
and protocols/ringtail/. The existing docs/ files (Threshold.md,
FROST.md, Broadcast.md) are linked where they fill in the details.

This supersedes the lightweight audit.md in PR luxfi#7 with the deeper
structure the issue reporter asked for.
zeekay pushed a commit that referenced this pull request Apr 23, 2026
The `Lint` job has been failing on master with:

    can't load config: the Go language version (go1.24) used to build
    golangci-lint is lower than the targeted Go version (1.26.1)

Root cause: `.github/workflows/ci.yml` used
`golangci/golangci-lint-action@v6` with `version: latest`, which resolves
to `golangci-lint v1.64.8`. That binary is built with Go 1.24, while
`go.mod` targets `go 1.26.1`. golangci-lint refuses to load the config
when the build-time Go version is lower than the `run.go` target it
infers from `go.mod`.

Minimal fix:

- Add `run.go: "1.24"` to `.golangci.yml` so the version check sees a
  target equal to the build version and proceeds.
- Pin `golangci-lint-action` to `version: v1.64.8` explicitly. The v1
  config format we use today is not parsed by golangci-lint v2.x, so
  future drift of `latest` onto v2 would silently break us again.

Non-goals: migrating `.golangci.yml` to the v2 schema. That is a
separate, larger PR once a golangci-lint release built with Go 1.26 is
available.

This unblocks stalled docs PRs: #6, #7, #8 (all UNSTABLE purely because
of this lint failure on master).

— [kcolbchain](https://kcolbchain.com) / [Abhishek Krishna](https://abhishekkrishna.com)
@hanzo-dev hanzo-dev force-pushed the main branch 6 times, most recently from cda4729 to 64b875c Compare May 4, 2026 06:17
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.

docs/audit.md file is missing

3 participants