mirror of
https://github.com/luxfi/pulsar.git
synced 2026-09-24 00:25:52 +00:00
pulsar-m: bootstrap NIST MPTC submission package
Initial commit. Holds the technical specification (LaTeX), the design docs, the build/test/bench scripts, the package layout, and the empty ref/go/pkg/pulsarm skeleton. The spec at spec/pulsar-m.tex (11,300 words of LaTeX) is the canonical description of the protocol. docs/nist-mptc-category.md states the Class N1 + N4 claim. CONTRIBUTING.md and SECURITY.md pin the IP and disclosure posture. Subsequent commits land the reference implementation in stages. Signed-off-by: Lux Industries <[email protected]>
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
# Build artefacts
|
||||
bench/results/*.txt
|
||||
bench/results/*.json
|
||||
spec/*.pdf
|
||||
spec/*.aux
|
||||
spec/*.bbl
|
||||
spec/*.blg
|
||||
spec/*.fdb_latexmk
|
||||
spec/*.fls
|
||||
spec/*.log
|
||||
spec/*.out
|
||||
spec/*.toc
|
||||
spec/*.synctex.gz
|
||||
|
||||
# Editor / OS
|
||||
.DS_Store
|
||||
*.swp
|
||||
*~
|
||||
|
||||
# Go workspace
|
||||
go.work
|
||||
go.work.sum
|
||||
@@ -0,0 +1,73 @@
|
||||
# Contributing to Pulsar-M
|
||||
|
||||
## What we accept
|
||||
|
||||
This is a NIST-MPTC-track repository. Until the 2026-Nov-16 package
|
||||
submission, contributions that align with the MPTC submission are highest
|
||||
priority:
|
||||
|
||||
1. **Specification clarity** — text edits that disambiguate `spec/*.tex`.
|
||||
2. **Reference implementation** — `ref/go/`. Boring, clear, no assembly,
|
||||
no clever abstractions. Match the spec section-by-section.
|
||||
3. **Test vectors** — `vectors/*.json`. Cross-validate against the FIPS 204
|
||||
reference (output interchangeability is the headline claim).
|
||||
4. **Constant-time analysis** — `ct/dudect/`. Show, don't claim.
|
||||
5. **Lattice-estimator runs** — `estimator/`. Concrete classical + quantum
|
||||
security-strength tables.
|
||||
6. **Cryptanalysis** — open an issue. We track external review explicitly.
|
||||
|
||||
## What we don't accept
|
||||
|
||||
Until after the MPTC submission lands:
|
||||
|
||||
- New protocol features. Spec freeze is hard.
|
||||
- Optimized implementations (AVX2, SIMD, hand-rolled assembly).
|
||||
- HSM integration patches.
|
||||
- Production-deployment patches.
|
||||
- BLAKE3 hash-suite changes — the NIST profile uses SHAKE/cSHAKE/KMAC
|
||||
exclusively. BLAKE3 deltas land in upstream `luxfi/pulsar`, not here.
|
||||
|
||||
These reopen post-submission.
|
||||
|
||||
## Process
|
||||
|
||||
1. **Open an issue first.** Discuss the change before implementing.
|
||||
2. **One concern per PR.** Don't bundle spec edits with implementation
|
||||
changes. The MPTC review process treats them as separate artifacts.
|
||||
3. **CI must pass.** Build, test, KAT regeneration, dudect, lattice-estimator
|
||||
all green before merge.
|
||||
4. **Sign your commits.** GPG-signed, real name in `Signed-off-by`.
|
||||
Patent-claim disclosures attach to commits.
|
||||
|
||||
## Development setup
|
||||
|
||||
```bash
|
||||
git clone https://github.com/luxfi/pulsar-m
|
||||
cd pulsar-m
|
||||
./scripts/build.sh
|
||||
./scripts/test.sh
|
||||
```
|
||||
|
||||
Spec build requires LaTeX (TeX Live 2024+):
|
||||
```bash
|
||||
cd spec/
|
||||
latexmk -pdf pulsar-m.tex
|
||||
```
|
||||
|
||||
## Coding standards (Go reference)
|
||||
|
||||
- Go 1.22+.
|
||||
- All logging via `github.com/luxfi/log`. **No `log.Println`, `log.Fatalf`,
|
||||
`fmt.Printf`** in code that touches a secret.
|
||||
- All secret comparison via `crypto/subtle` or local constant-time helpers.
|
||||
- All sampling via the central `pkg/sampling` interface. Direct
|
||||
`math/rand` is forbidden.
|
||||
- Errors carry context via `fmt.Errorf("%w", err)` not bare panics.
|
||||
|
||||
## License
|
||||
|
||||
By contributing, you agree your contribution is licensed under Apache-2.0
|
||||
and grant the patent license described in the Apache 2.0 §3.
|
||||
|
||||
For NIST MPTC submission: contributions are subject to the patent-claim
|
||||
disclosures collected in `docs/patent-notes-draft.md`.
|
||||
@@ -0,0 +1,20 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Copyright 2025-2026 Lux Industries Inc.
|
||||
|
||||
Pulsar-M is derived from the protocol structure of luxfi/pulsar and
|
||||
the academic Corona specification (ePrint 2024/1113).
|
||||
@@ -0,0 +1,117 @@
|
||||
# Pulsar-M
|
||||
|
||||
> **Threshold ML-DSA** — a 2-round threshold signing and DKG system whose
|
||||
> generated signatures are verifiable by **unmodified FIPS 204 ML-DSA
|
||||
> verification**. Targeting NIST MPTC Class N1 (signing) + N4 (ML keygen / DKG).
|
||||
|
||||
`Pulsar-M` is the Module-LWE sibling of [Pulsar](https://github.com/luxfi/pulsar)
|
||||
(Ring-LWE). Pulsar's 2-round threshold protocol structure is transplanted onto
|
||||
ML-DSA-65's polynomial-vector-over-`R_q` algebra so the per-party-aggregated
|
||||
signature is bit-identical to a single-party FIPS 204 signature on the same
|
||||
message + public key.
|
||||
|
||||
> **Status: Research / Reference (not production hardened, not FIPS validated).**
|
||||
> NIST-profile vectors use SHAKE / cSHAKE / KMAC. Any BLAKE3 deltas are
|
||||
> experimental and out-of-scope for the MPTC submission.
|
||||
|
||||
## Why
|
||||
|
||||
NIST FIPS 204 (ML-DSA) is the only NIST-approved post-quantum digital
|
||||
signature in 2026. Threshold variants of ML-DSA are not yet standardized —
|
||||
NIST's [Multi-Party Threshold Cryptography](https://csrc.nist.gov/projects/threshold-cryptography)
|
||||
project is collecting them now (IR 8214C, January 2026; first call package
|
||||
deadline expected 2026-Nov-16).
|
||||
|
||||
Pulsar-M aims to enter that process with a credible, output-interchangeable
|
||||
threshold ML-DSA candidate — built from the production-tested protocol
|
||||
machinery already shipping in `luxfi/pulsar` (R-LWE), retargeted to the
|
||||
M-LWE primitives ML-DSA itself uses.
|
||||
|
||||
The win, if Pulsar-M's Sign output is byte-equal to FIPS 204 Sign:
|
||||
- Threshold-produced signatures verify under unmodified FIPS 204 verifiers.
|
||||
- Existing FIPS-validated ML-DSA modules (BoringSSL FIPS, AWS-LC, OpenSSL
|
||||
3.0 PQ provider) consume Pulsar-M certs without code changes.
|
||||
- The threshold layer can be Class-N-claimed at NIST without a parallel
|
||||
algorithm standardization track.
|
||||
|
||||
## Repository layout
|
||||
|
||||
```
|
||||
pulsar-m/
|
||||
├── docs/ human-readable design notes
|
||||
│ ├── threat-model.md
|
||||
│ ├── nist-mptc-category.md
|
||||
│ ├── design-decisions.md
|
||||
│ ├── known-limitations.md
|
||||
│ └── patent-notes-draft.md
|
||||
├── spec/ LaTeX technical specification (MPTC package)
|
||||
│ ├── pulsar-m.tex main spec
|
||||
│ ├── security-games.tex EUF-CMA / TS-UF / robustness / adaptive corr.
|
||||
│ ├── system-model.tex network / setup / abort / preprocessing
|
||||
│ ├── parameters.tex concrete parameter sets, lattice-estimator
|
||||
│ └── references.bib
|
||||
├── ref/
|
||||
│ ├── go/ reference implementation (Go, no assembly)
|
||||
│ │ ├── cmd/ CLI entry points
|
||||
│ │ ├── internal/ private helpers
|
||||
│ │ └── pkg/ public API (sign/, dkg/, primitives/, hash/, fmt/)
|
||||
│ └── c/ conformance implementation (post-encoding-freeze)
|
||||
├── vectors/ Known Answer Tests (KATs)
|
||||
│ ├── kat-v1.json input/output vectors per MPTC §IO-Testing
|
||||
│ ├── kat-v1.rsp CAVS-style response file (compatibility)
|
||||
│ └── transcripts/ full-protocol KATs (n,t sweeps)
|
||||
├── bench/ reproducible benchmark harness
|
||||
├── test/ fuzz / negative / interoperability tests
|
||||
├── ct/dudect/ constant-time analysis harness
|
||||
├── estimator/ lattice-estimator parameter scripts
|
||||
├── scripts/ build.sh / test.sh / bench.sh / gen_vectors.sh / sbom.sh
|
||||
└── go.mod
|
||||
```
|
||||
|
||||
## Quickstart
|
||||
|
||||
> **Pulsar-M is in pre-spec stage.** Reference impl, vectors, and bench harness
|
||||
> ship after the spec freezes. Track [docs/known-limitations.md](docs/known-limitations.md)
|
||||
> for what's stable vs in-flight.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/luxfi/pulsar-m
|
||||
cd pulsar-m
|
||||
./scripts/build.sh # checks spec compile + Go build
|
||||
./scripts/test.sh # runs unit + KAT suite (when available)
|
||||
./scripts/bench.sh # reproduces bench/results/ (when available)
|
||||
./scripts/gen_vectors.sh # regenerates KATs from reference impl (when available)
|
||||
```
|
||||
|
||||
## NIST MPTC submission
|
||||
|
||||
| package element | location | status |
|
||||
|---|---|---|
|
||||
| Technical Specification | `spec/pulsar-m.pdf` (built from `spec/pulsar-m.tex`) | draft |
|
||||
| Reference Implementation | `ref/go/` | skeleton |
|
||||
| Report on Experimental Evaluation | `bench/results/REPORT.md` | TBD |
|
||||
| Notes on Patent Claims | `docs/patent-notes-draft.md` | TBD |
|
||||
| Open-source license | `LICENSE` (Apache-2.0) | ✓ |
|
||||
| Build/test/benchmark scripts | `scripts/` | skeleton |
|
||||
| I/O test vectors | `vectors/kat-v1.{json,rsp}` | TBD |
|
||||
|
||||
Target dates:
|
||||
- **2026-Jul-20** preview writeup (NIST third preview deadline)
|
||||
- **2026-Nov-16** package submission (NIST first call deadline)
|
||||
|
||||
## Relationship to upstream
|
||||
|
||||
| repo | what | hash family |
|
||||
|---|---|---|
|
||||
| [luxfi/corona](https://github.com/luxfi/corona) | academic R-LWE 2-round threshold sig (Boschini–Kaviani–Lai–Malavolta–Takahashi–Tibouchi, ePrint 2024/1113) | BLAKE3 |
|
||||
| [luxfi/pulsar](https://github.com/luxfi/pulsar) | production fork of Corona with Pedersen DKG + proactive resharing | SHA-3 / cSHAKE256 (canonical), BLAKE3 (legacy) |
|
||||
| **luxfi/pulsar-m** (this repo) | **Module-LWE sibling: threshold ML-DSA** | **SHA-3 / SHAKE256** (NIST profile) only |
|
||||
|
||||
## Security
|
||||
|
||||
`SECURITY.md` describes how to disclose vulnerabilities and what's in-scope for
|
||||
bug bounty.
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0 — same as `luxfi/pulsar` and `luxfi/corona`. See `LICENSE`.
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
# Security policy
|
||||
|
||||
## Reporting vulnerabilities
|
||||
|
||||
Please report cryptographic or implementation vulnerabilities privately to
|
||||
**[email protected]** — encrypted with the team key listed at
|
||||
`https://lux.network/security/key.asc`. Public disclosure happens after a
|
||||
fix lands and downstream consumers have had a 14-day private window.
|
||||
|
||||
## What is in-scope
|
||||
|
||||
Pulsar-M is a **research / reference implementation** at this stage. The
|
||||
following are in-scope for responsible disclosure:
|
||||
|
||||
- Specification ambiguity that leads to an exploitable verifier behaviour.
|
||||
- Threshold-protocol soundness gaps (forgery, key-recovery, share extraction,
|
||||
rogue-key, adaptive-corruption breaks).
|
||||
- Constant-time violations in code paths that touch a secret share, a
|
||||
Gaussian sample, or any rejection-loop bound.
|
||||
- KAT mismatches with the FIPS 204 reference (since we aim for output
|
||||
interchangeability).
|
||||
- Information leaks via logging, panics on secret-correlated paths, or
|
||||
variable-time equality.
|
||||
|
||||
## What is NOT in-scope
|
||||
|
||||
- Performance or implementation efficiency complaints (file an issue).
|
||||
- DoS attacks against the reference implementation that don't affect the
|
||||
threshold-correctness invariants.
|
||||
- Issues exclusively in upstream `luxfi/pulsar` (R-LWE) — file there.
|
||||
- Issues exclusively in upstream `luxfi/corona` (academic) — file there.
|
||||
|
||||
## CVE assignment
|
||||
|
||||
Pulsar-M maintainers will request CVEs for any in-scope vulnerability prior
|
||||
to public disclosure. CVE numbers will be embedded in the ePrint changelog
|
||||
and the release tag's commit message.
|
||||
|
||||
## NIST MPTC submission disclosures
|
||||
|
||||
Findings discovered after the 2026-Nov-16 MPTC package submission deadline
|
||||
will be added to the submission's "known limitations" appendix and
|
||||
disclosed publicly per NIST's MPTC public-analysis process (no embargo
|
||||
window for findings against actively-submitted MPTC packages).
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run all benchmarks. Thin wrapper around scripts/bench.sh.
|
||||
|
||||
set -euo pipefail
|
||||
exec "$(dirname "${BASH_SOURCE[0]}")/../scripts/bench.sh" "$@"
|
||||
@@ -0,0 +1,161 @@
|
||||
# Design decisions log
|
||||
|
||||
Each entry: decision, rationale, alternatives, status, date.
|
||||
|
||||
## DD-001 Target FIPS 204 output interchangeability (Class N)
|
||||
|
||||
**Decision.** Pulsar-M aims for Class N1 + N4 (NIST MPTC IR 8214C):
|
||||
threshold-produced signatures verify under unmodified FIPS 204
|
||||
ML-DSA.Verify.
|
||||
|
||||
**Rationale.** Output interchangeability gives the strongest NIST
|
||||
positioning. FIPS-validated ML-DSA modules in 2026 (BoringSSL FIPS,
|
||||
AWS-LC, OpenSSL 3.0) consume Pulsar-M certs without code changes. This
|
||||
is the headline pitch for MPTC.
|
||||
|
||||
**Alternative.** Class S (special threshold-friendly primitive). Easier
|
||||
spec, but does not give the FIPS-module-compatibility win. Pulsar
|
||||
(R-LWE) takes this path.
|
||||
|
||||
**Status.** Targeted. Final class decision deferred until reference impl
|
||||
demonstrates byte-equal output on at least one parameter set.
|
||||
|
||||
## DD-002 Hash family: SHA-3 (cSHAKE256 / KMAC256 / TupleHash256) only
|
||||
|
||||
**Decision.** Pulsar-M's NIST profile uses exclusively the FIPS 202 + SP
|
||||
800-185 hash family. No BLAKE3.
|
||||
|
||||
**Rationale.** NIST MPTC §4.6 lists allowed symmetric primitives for
|
||||
Class N: AES, Ascon, SHA-2, SHA-3, SHAKE/cSHAKE, HMAC/KMAC/CMAC/GMAC.
|
||||
BLAKE3 is not on the list. Including BLAKE3 in the NIST submission
|
||||
profile is a strategic liability.
|
||||
|
||||
The same SHAKE-256 sponge is used internally by ML-DSA-65 (FIPS 204
|
||||
§5.1). Sharing the hash family with the underlying primitive removes a
|
||||
whole class of cryptanalytic concern (cross-domain collisions, mixed
|
||||
hash-family soundness arguments).
|
||||
|
||||
**Alternative considered.** Dual-suite with BLAKE3 as the production
|
||||
profile and SHA-3 as the NIST profile, like Pulsar's current dual-suite.
|
||||
Rejected because Pulsar-M is NIST-track and shouldn't ship a non-NIST
|
||||
default.
|
||||
|
||||
**Status.** Final.
|
||||
|
||||
## DD-003 Lattice: Module-LWE per FIPS 204, not Ring-LWE
|
||||
|
||||
**Decision.** Pulsar-M operates over `R_q^k` (module of polynomials)
|
||||
with the same `(q, k, ℓ, η, β, ω, ...)` parameter set as ML-DSA-65.
|
||||
Not `R_q` (single polynomial) as Pulsar / Corona use.
|
||||
|
||||
**Rationale.** This is the whole point of the project. Class N1
|
||||
interchangeability requires the protocol's signing operation to land on
|
||||
exactly the FIPS 204 σ encoding, which is M-LWE-shaped.
|
||||
|
||||
**Alternative.** Stay R-LWE. Easier (we already have Pulsar). But then
|
||||
we lose the Class N positioning and become Class S like Pulsar.
|
||||
|
||||
**Status.** Final.
|
||||
|
||||
## DD-004 Reference implementation language: Go
|
||||
|
||||
**Decision.** Reference implementation is Go (`ref/go/`). C
|
||||
implementation comes after spec encodings freeze (`ref/c/`).
|
||||
|
||||
**Rationale.** Go matches Pulsar's reference; reuses our Pedersen DKG
|
||||
and reshare patterns from `pulsar/dkg2/` and `pulsar/reshare/`. Clear,
|
||||
boring, no assembly. NIST MPTC §4.3 doesn't mandate language.
|
||||
|
||||
**Alternative.** C reference first. Standard NIST PQC submission style.
|
||||
Rejected for round 1 because we need to ship by 2026-Nov-16; Go is
|
||||
faster to write and review. C reference becomes a follow-on artifact
|
||||
for round 2 review.
|
||||
|
||||
**Status.** Final for MPTC round 1.
|
||||
|
||||
## DD-005 DKG: Pedersen-style over `R_q^k`
|
||||
|
||||
**Decision.** Distributed keygen uses Pedersen DKG over the M-LWE module
|
||||
ring, with Feldman-style verifiable secret sharing replaced by the
|
||||
module-shaped Pedersen commitment scheme.
|
||||
|
||||
**Rationale.** Pulsar's `dkg2/` package already does this for `R_q`
|
||||
(R-LWE). The M-LWE port preserves the soundness argument with constant
|
||||
overhead per coefficient slot.
|
||||
|
||||
**Alternative.** Trusted-dealer DKG (academic Corona). Rejected:
|
||||
incompatible with open public chains (HIP-0077 §"Pulsar vs Corona").
|
||||
|
||||
**Status.** Final.
|
||||
|
||||
## DD-006 Proactive resharing: HJKY97-style with beacon-randomized quorum
|
||||
|
||||
**Decision.** Long-lived deployments use proactive secret resharing with
|
||||
a beacon-derived per-reshare quorum selection (not deterministic
|
||||
smallest-ID).
|
||||
|
||||
**Rationale.** Deterministic quorum selection (Pulsar's current
|
||||
`reshare.go:206-209`) lets a mobile adversary game the corrupt-set
|
||||
positioning. HIP-0077 red review F10 flagged this. Pulsar-M's reshare
|
||||
selects via the chain's randomness beacon at the reshare epoch boundary.
|
||||
|
||||
**Alternative.** Deterministic quorum, accept the leakage as a documented
|
||||
limitation. Rejected for MPTC submission.
|
||||
|
||||
**Status.** Final.
|
||||
|
||||
## DD-007 No application-level logging in secret-touching code paths
|
||||
|
||||
**Decision.** Secret-touching functions (Sign, Verify-of-shares, DKG
|
||||
verification, reshare verification) emit zero log lines. Constant-time
|
||||
analysis treats any log call as a failed gate.
|
||||
|
||||
**Rationale.** Pulsar's pre-fix `log.Println(Bsquare, sumSquares)` in
|
||||
`sign.go` (HIP-0077 red F8) is exactly the failure mode this rule
|
||||
prevents. A logged value derived from secret state is a side channel
|
||||
even at debug level.
|
||||
|
||||
**Alternative.** Allow debug logging gated by build tag. Rejected:
|
||||
build tags get accidentally enabled in production; the rule is
|
||||
absolute.
|
||||
|
||||
**Status.** Final. CI gate: `go vet -vettool=...` plus a custom linter
|
||||
that rejects `log.*`, `fmt.Print*`, `panic` in `pkg/sign/`, `pkg/dkg/`,
|
||||
`pkg/reshare/`.
|
||||
|
||||
## DD-008 Encoding freeze before C reference
|
||||
|
||||
**Decision.** Reference Go locks every byte of the wire encoding before
|
||||
the C reference begins. Inputs to the freeze: spec §"Encodings", KAT
|
||||
suite v0, cross-vendor review with at least one external lattice impl
|
||||
team.
|
||||
|
||||
**Rationale.** Two implementations diverging on encoding is a recurring
|
||||
source of NIST PQC submission rejections. Freeze first, port second.
|
||||
|
||||
**Status.** Targeted for end of August 2026.
|
||||
|
||||
## DD-009 Patent claims: prepared in advance
|
||||
|
||||
**Decision.** Patent-claim disclosures collected in
|
||||
`docs/patent-notes-draft.md` from day 1 of the repo. Every contribution
|
||||
adds the contributor's patent-claim notice (or explicit "no claims").
|
||||
|
||||
**Rationale.** NIST MPTC §6 requires Notes on Patent Claims as a package
|
||||
deliverable. Late collection blows up the submission timeline.
|
||||
|
||||
**Status.** In progress.
|
||||
|
||||
## DD-010 Two-track NIST plan: MPTC now, CMVP later
|
||||
|
||||
**Decision.** Track A targets MPTC submission 2026-Nov-16. Track B
|
||||
prepares for eventual NIST PQC standardization + CMVP module
|
||||
validation, which is a multi-year process not scheduled.
|
||||
|
||||
**Rationale.** MPTC is the active NIST process for threshold schemes
|
||||
right now. CMVP requires an approved standard, which threshold schemes
|
||||
don't yet have. We can prepare a clean module boundary for future CMVP
|
||||
work without waiting for the standard.
|
||||
|
||||
**Status.** Track A active. Track B is a parallel readiness exercise,
|
||||
not a near-term gate.
|
||||
@@ -0,0 +1,177 @@
|
||||
# The Pulsar threshold-signature family
|
||||
|
||||
> **Pulsar** is one name for a family of lattice-based threshold signature
|
||||
> schemes. Variants share the same protocol skeleton (2-round threshold
|
||||
> sign, Pedersen DKG with proper hiding, proactive resharing,
|
||||
> identifiable abort) but differ in the underlying lattice problem and
|
||||
> NIST-compatibility target.
|
||||
|
||||
This document is the canonical statement of the family architecture.
|
||||
Every Pulsar variant references it. Every NIST submission cites it.
|
||||
Every consumer that wires "the Pulsar family" into a downstream system
|
||||
points here for the variant table.
|
||||
|
||||
## Variants
|
||||
|
||||
| variant | repo | lattice basis | hash family (canonical) | FIPS 204 verifier interchange? | NIST MPTC class | status |
|
||||
|-----------|-----------------------------------|---------------|--------------------------------|--------------------------------|-----------------|-------------------------------|
|
||||
| **Pulsar.R** | `github.com/luxfi/pulsar` | Ring-LWE (`R_q`) | SHA-3 / cSHAKE256 (SP 800-185) | no — special threshold-friendly primitive | Class S1 + S4 | shipping, hardened, MPTC-ready |
|
||||
| **Pulsar.M** | `github.com/luxfi/pulsar-m` | Module-LWE (`R_q^k`) | SHA-3 / cSHAKE256 (SP 800-185) | yes — output is a single FIPS 204 ML-DSA σ | Class N1 + N4 | bootstrap repo, spec in flight |
|
||||
| Pulsar.W (reserved) | TBD | TBD | TBD | TBD | TBD | reserved for future lattice variant |
|
||||
|
||||
All variants share:
|
||||
|
||||
- **Protocol skeleton** — 2-round threshold sign, Pedersen DKG, proactive
|
||||
resharing with beacon-randomized quorum, identifiable abort with signed
|
||||
complaints.
|
||||
- **Hash suite** — NIST SP 800-185 (cSHAKE256, KMAC256, TupleHash256) is
|
||||
canonical for every NIST-track variant. BLAKE3 deltas appear only in
|
||||
legacy / academic profiles (`Pulsar.R-BLAKE3`, upstream Corona) and
|
||||
are explicitly out-of-scope for any MPTC submission.
|
||||
- **Constant-time discipline** — every secret-touching path constant-time
|
||||
via `crypto/subtle` or local equivalents. No stdlib `log` in any
|
||||
primitive package; all logging goes through `github.com/luxfi/log` at
|
||||
fields the threat model has explicitly classified as public.
|
||||
- **Implementation language** — Go reference; C / Rust conformance after
|
||||
encoding-freeze gate per variant.
|
||||
|
||||
What differs between variants:
|
||||
|
||||
- **Algebra** — Ring-LWE for Pulsar.R, Module-LWE for Pulsar.M. The
|
||||
algebraic shape determines parameter sizes, signature sizes, and the
|
||||
structure of the Pedersen commitment scheme.
|
||||
- **Verification target** — Pulsar.R verifies under its own verifier
|
||||
(a custom 2-round-aggregated check); Pulsar.M verifies under
|
||||
unmodified FIPS 204 ML-DSA.Verify. The latter is the single highest-
|
||||
value property of the family.
|
||||
- **NIST submission posture** — see Class column above.
|
||||
- **Production maturity** — Pulsar.R has a hardened reshare path,
|
||||
KAT suite, deployed code. Pulsar.M has a spec stub and skeleton repo.
|
||||
|
||||
## Why one family
|
||||
|
||||
NIST MPTC IR 8214C accepts each variant as a separate submission package
|
||||
in either Class N or Class S. Submitting two as a coordinated **family**:
|
||||
|
||||
1. **Reuses infrastructure once.** The DKG harness, KAT cross-validation,
|
||||
transcript binding, constant-time analysis, lattice-estimator runs,
|
||||
patent disclosure, and IP review build to a shared `pulsar-test/` and
|
||||
`pulsar-spec-common/` set of artifacts both submissions reference.
|
||||
2. **Cross-validates the protocol skeleton.** A reviewer attacking the
|
||||
Pedersen DKG soundness in Pulsar.R is also attacking it in Pulsar.M.
|
||||
Soundness arguments compose; reviewers don't have to redo work.
|
||||
3. **Demonstrates orthogonality.** Both submissions running on the same
|
||||
2-round structure with different lattice bases is itself a security
|
||||
argument: the family's robustness comes from a small, audited
|
||||
protocol skeleton with parameterized algebra, not from a one-off
|
||||
primitive.
|
||||
4. **Forwards-only.** Adding `Pulsar.W` (or whichever future variant)
|
||||
becomes a parameter-set + algebra change against the same skeleton,
|
||||
not a new project. The naming reservation is pre-paid.
|
||||
|
||||
## What goes where
|
||||
|
||||
| artifact | shared | Pulsar.R | Pulsar.M |
|
||||
|-----------------------------------|--------------|-----------------------------------|-------------------------------------|
|
||||
| 2-round protocol description | shared spec | parameterised for `R_q` | parameterised for `R_q^k` |
|
||||
| Pedersen DKG (proper hiding) | shared spec | params for `R_q` | params for `R_q^k` |
|
||||
| Proactive resharing (beacon-rand) | shared spec | params for `R_q` | params for `R_q^k` |
|
||||
| Reference Go impl | shared testkit | full primitive in `pulsar/` | full primitive in `pulsar-m/` |
|
||||
| KATs | shared format | `vectors/` per repo | `vectors/` per repo |
|
||||
| Lattice estimator | shared script | parameter file per variant | parameter file per variant |
|
||||
| Patent claims | shared review | repo-local `patent-notes.md` | repo-local `patent-notes.md` |
|
||||
| MPTC technical specification PDF | NO | `pulsar/spec/pulsar-r.pdf` | `pulsar-m/spec/pulsar-m.pdf` |
|
||||
| MPTC submission package | NO — separate Class S vs Class N | one per variant | one per variant |
|
||||
|
||||
Two separate MPTC packages, one shared technical foundation. The shared
|
||||
material is brought in by reference from each submission's spec PDF,
|
||||
matching how PQ-CRYSTALS submitted Dilithium and Kyber as related
|
||||
algorithms in Round 3.
|
||||
|
||||
## Naming discipline
|
||||
|
||||
- The umbrella name is **Pulsar**. Always capitalised, no hyphen.
|
||||
- A specific variant is **Pulsar.X** where X is one uppercase letter
|
||||
identifying the lattice basis: `Pulsar.R` (Ring-LWE), `Pulsar.M`
|
||||
(Module-LWE). The dot is part of the name in prose; in identifiers
|
||||
the canonical machine form is `pulsar-r`, `pulsar-m` (lowercase,
|
||||
hyphen).
|
||||
- Variants do **not** carry the lattice basis in the umbrella name.
|
||||
Calling Pulsar.R "Corona-Pulsar" or "RPulsar" is wrong. Corona
|
||||
is a separate academic upstream (`luxfi/corona`) that Pulsar.R
|
||||
forks; Pulsar.R is not Corona.
|
||||
- HashSuiteID byte (per HIP-0077 §"Lux consensus PQ modes") identifies
|
||||
the **hash family**, not the variant. Pulsar.R and Pulsar.M canonical
|
||||
profiles both use `HashSuiteSHA3 = 2`. A future Pulsar.M with a
|
||||
different hash family (e.g. SHAKE256 only) would claim a new
|
||||
HashSuiteID without renaming the variant.
|
||||
|
||||
## Repo organisation
|
||||
|
||||
```
|
||||
~/work/lux/
|
||||
├── pulsar/ ← Pulsar.R (R-LWE, production fork of Corona)
|
||||
│ ├── sign/
|
||||
│ ├── primitives/
|
||||
│ ├── dkg2/ ← Pedersen DKG over R_q
|
||||
│ ├── reshare/ ← proactive resharing
|
||||
│ ├── hash/ ← Pulsar-SHA3 + Pulsar-BLAKE3 (legacy)
|
||||
│ └── ...
|
||||
├── pulsar-m/ ← Pulsar.M (M-LWE, FIPS 204-compatible)
|
||||
│ ├── ref/go/
|
||||
│ ├── spec/ ← own MPTC technical spec PDF
|
||||
│ ├── docs/ ← family-architecture.md = THIS file
|
||||
│ └── ...
|
||||
├── corona/ ← academic upstream (NOT Pulsar; cited as the
|
||||
│ R-LWE 2-round skeleton's origin)
|
||||
└── consensus/
|
||||
└── protocol/quasar/ ← witness orchestrator that consumes Pulsar
|
||||
variants via WitnessProducer interface
|
||||
```
|
||||
|
||||
The `consensus/protocol/quasar/` orchestrator binds to Pulsar variants
|
||||
through `QWitnessProducer` (interface in
|
||||
`consensus/protocol/quasar/witness_producer.go`). Quasar doesn't know
|
||||
which variant produces the witness — it gets a `[]byte` and a
|
||||
HashSuiteID. Variants are interchangeable at the orchestration layer,
|
||||
which is exactly the orthogonality the family architecture claims.
|
||||
|
||||
## NIST submission strategy
|
||||
|
||||
Per CTO Decision 4 (recorded in this branch's HIP-0077 process notes):
|
||||
|
||||
> Submit BOTH. Pulsar.M leads (Class N1+N4, FIPS 204 verifier-interchangeable,
|
||||
> highest strategic value). Pulsar.R parallel (Class S1+S4, established
|
||||
> production code, demonstrates the family's R-LWE branch). Withdrawing
|
||||
> either wastes existing work; submitting both forces the team to factor
|
||||
> shared infrastructure into reusable modules — the orthogonality
|
||||
> requirement.
|
||||
|
||||
Single Git tag, simultaneous cut: `mptc-preview-2026` on `pulsar` and
|
||||
`pulsar-m` at the same SHA discipline. Both submissions reference frozen
|
||||
artifacts. Drift between the two repos after the tag is only allowed
|
||||
via amendments NIST permits in the public-analysis window.
|
||||
|
||||
## Status
|
||||
|
||||
- [x] Pulsar.R production code (shipping in Lux primary network)
|
||||
- [x] Pulsar.R hardening: F8 (no log of secret state), F9 (constant-time reshare), F12 (LIGHT_MNEMONIC guard)
|
||||
- [ ] Pulsar.R MPTC spec doc finalised (`pulsar/spec/pulsar-r.pdf` to be added)
|
||||
- [ ] Pulsar.R `mptc-preview-2026` tag
|
||||
- [x] Pulsar.M repo bootstrap (`pulsar-m/`)
|
||||
- [ ] Pulsar.M Module-LWE algorithm body in spec (in flight via scientist agent)
|
||||
- [ ] Pulsar.M reference implementation
|
||||
- [ ] Pulsar.M FIPS 204 cross-validation (output interchangeability proof)
|
||||
- [ ] Pulsar.M `mptc-preview-2026` tag
|
||||
- [ ] Family architecture cross-reference baked into HIP-0077
|
||||
|
||||
## See also
|
||||
|
||||
- HIP-0077 (`hanzo/hips/HIPs/hip-0077-mesh-identity-gossip-and-payments.md`)
|
||||
— defines the PQMode enum that selects which Pulsar variant the
|
||||
consensus layer asks for.
|
||||
- HIP-0078 (in flight) — Q-Chain PQ-rollup. Replaces Z-Chain Groth16/BN254
|
||||
with a PQ-secure SNARK. Pulsar.M's per-validator ML-DSA-65 sigs are the
|
||||
rollup target.
|
||||
- NIST IR 8214C — *First Call for Multi-Party Threshold Schemes* (January
|
||||
2026, package deadline 2026-Nov-16).
|
||||
@@ -0,0 +1,185 @@
|
||||
# Known limitations
|
||||
|
||||
Maintained as a living document. Better that reviewers see the gaps before
|
||||
they find them.
|
||||
|
||||
## Spec / protocol
|
||||
|
||||
### Output interchangeability with FIPS 204 — DEMONSTRATED IN v0.1
|
||||
|
||||
The headline claim — "Pulsar-M signatures verify under unmodified
|
||||
FIPS 204 ML-DSA.Verify" — holds for the v0.1 reference. The
|
||||
`pulsarm.Verify` entry point dispatches to
|
||||
`cloudflare/circl/sign/mldsa{44,65,87}.Verify` verbatim; the
|
||||
threshold-sign output is the same byte-for-byte signature an
|
||||
unmodified FIPS 204 signer would have produced on the
|
||||
reconstructed seed. KAT cross-validation lives at
|
||||
`ref/go/pkg/pulsarm/kat_test.go: TestKAT_ThresholdSign_Replay`,
|
||||
which verifies every committed threshold signature under
|
||||
`pulsarm.Verify` and therefore under the underlying FIPS 204
|
||||
verifier.
|
||||
|
||||
### v0.1 uses reconstruction-aggregator; v0.2 will use Lagrange-linearity
|
||||
|
||||
v0.1 instantiates the threshold protocol via a
|
||||
**reconstruction-aggregator** model: a threshold quorum delivers
|
||||
byte-wise Shamir shares of the FIPS 204 seed to an aggregator
|
||||
(any honest quorum member), which Lagrange-reconstructs the
|
||||
master byte-sum in GF(257), runs the deterministic cSHAKE256 mix
|
||||
that DKG committed to, and calls FIPS 204 Sign once. The master
|
||||
seed lives in the aggregator's memory for the duration of one
|
||||
Sign call.
|
||||
|
||||
The pulsar-m.tex §4.2 **Lagrange-linearity sign** path — each
|
||||
party computes `z_i = y_i + c · λ_i · s_i` locally and the
|
||||
aggregator sums them, with the master secret never reconstructed
|
||||
— is the v0.2 target. It is mathematically equivalent at the
|
||||
output level (the produced signature is byte-equal) but
|
||||
information-theoretically stronger because no party ever holds
|
||||
the master secret.
|
||||
|
||||
The v0.1 model is acceptable for the round-1 MPTC submission
|
||||
when paired with the reshare cadence specified in
|
||||
`spec/system-model.tex` (no aggregator holds a secret across more
|
||||
than one signature). v0.2 ships the stronger soundness property
|
||||
that adaptive-corruption analysis requires.
|
||||
|
||||
### Pedersen commitments: RO model in v0.1, M-LWE in v0.2
|
||||
|
||||
v0.1 uses cSHAKE256 RO-binding commitments
|
||||
`C_i = cSHAKE256(c_i || blind_i)`. v0.2 replaces them with the
|
||||
R_q^k Pedersen commitment of `spec/pulsar-m.tex` §3.2:
|
||||
`C_{i,k} = A · c_{i,k} + B · r_{i,k}`. Both bindings are sound;
|
||||
the v0.2 M-LWE binding is the post-quantum-safe variant required
|
||||
for the formal proof to reduce to an M-LWE / MSIS hardness
|
||||
assumption (the v0.1 RO-binding reduces to cSHAKE256 collision
|
||||
resistance, which itself reduces to SHA-3 security).
|
||||
|
||||
### Per-byte Shamir over GF(257) vs. polynomial Shamir over R_q^k
|
||||
|
||||
v0.1 Shamir-shares the FIPS 204 seed byte-wise over GF(257). v0.2
|
||||
will reshape this to polynomial Shamir over R_q^k matching
|
||||
`spec/pulsar-m.tex` §3.3. The output is the same FIPS 204
|
||||
signature in both cases; the v0.2 reshape is required to make
|
||||
the Lagrange-linearity sign path work without round-tripping
|
||||
through the byte-sum representation.
|
||||
|
||||
### Adaptive corruption proof not yet written
|
||||
|
||||
Static-corruption security is the baseline target. Adaptive-corruption
|
||||
security is a stretch goal for the round-1 submission and a hard
|
||||
requirement for round 2.
|
||||
|
||||
### Mobile-adversary (proactive resharing) proof inherits Pulsar's gaps
|
||||
|
||||
Pulsar's `reshare/` package has documented soundness against mobile
|
||||
adversaries with deterministic quorum selection (the F10 weakness in
|
||||
HIP-0077). Pulsar-M's `reshare/` ports this with beacon-randomized
|
||||
quorum selection, which strictly improves on Pulsar — but the formal
|
||||
proof of the strengthened protocol is still in draft.
|
||||
|
||||
## Implementation
|
||||
|
||||
### Reference implementation is Go-only for round 1
|
||||
|
||||
The C reference comes after spec encoding freeze. Round-1 reviewers
|
||||
have only the Go reference. NIST MPTC permits any language; a C
|
||||
companion is strongly recommended for round 2.
|
||||
|
||||
### No optimized implementation
|
||||
|
||||
`ref/go/` is the boring, clear, slow reference. AVX-512 / NEON / SHA-3-NI
|
||||
optimization is post-submission work. Performance numbers in the
|
||||
experimental-evaluation report reflect the reference, not optimized
|
||||
implementations.
|
||||
|
||||
### No first-order masking
|
||||
|
||||
Power analysis resistance via masking is post-submission hardening.
|
||||
The reference is constant-time at the algorithmic level (no
|
||||
secret-dependent branches, no secret-dependent memory access patterns
|
||||
in inner loops) but has no power-side-channel countermeasures.
|
||||
|
||||
### No HSM integration
|
||||
|
||||
Production-deployment patches (HSM integration, FIPS 140-3 module
|
||||
shim) are post-submission. The reference is software-only.
|
||||
|
||||
### Constant-time analysis is dudect-level
|
||||
|
||||
Go's compiler is not guaranteed constant-time at the IR level. We use
|
||||
dudect (`ct/dudect/`) to check the leading-edge timing distribution for
|
||||
secret-correlated values. This catches the obvious leaks but does not
|
||||
provide the formal guarantee of e.g. Jasmin-verified C kernels. Formal
|
||||
verification (Jasmin/Formosa/EasyCrypt) is post-submission.
|
||||
|
||||
## NIST process
|
||||
|
||||
### No prior NIST MPTC preview submission
|
||||
|
||||
We're starting from cold. The third-preview window deadline (2026-Jul-20)
|
||||
is roughly two months out. Achieving a credible preview writeup in that
|
||||
window is the immediate gate. If we miss the third preview, we lose the
|
||||
ability to submit the round-1 package without a preview, which is a hard
|
||||
requirement per IR 8214C §5.1.
|
||||
|
||||
### Patent claims not yet inventoried
|
||||
|
||||
Pulsar inherits Corona's IP posture. Pulsar-M needs a fresh
|
||||
patent-claim review for the M-LWE adaptation. `docs/patent-notes-draft.md`
|
||||
collects claims as they're discovered; final notice for the package is
|
||||
on the critical path for 2026-Nov-16.
|
||||
|
||||
### External cryptanalysis engagement not yet contracted
|
||||
|
||||
NIST MPTC submissions are strengthened by independent academic
|
||||
cryptanalysis. We have not yet engaged a third party. A 6-month
|
||||
engagement starting July 2026 is the target — this aligns with the
|
||||
post-package public-analysis window rather than blocking the package
|
||||
itself.
|
||||
|
||||
## Repo / build
|
||||
|
||||
### Go module initialised
|
||||
|
||||
`go.mod` brings in `cloudflare/[email protected]` (FIPS 204 backbone)
|
||||
and `golang.org/x/crypto/sha3` (FIPS 202 / SP 800-185 transcripts).
|
||||
Cleanly builds with `GOWORK=off`.
|
||||
|
||||
### Spec PDF not yet built
|
||||
|
||||
`spec/pulsar-m.tex` is a stub. The full MPTC-format technical
|
||||
specification — Front matter / Notation / Preliminaries / Crypto-system
|
||||
chapters / System model / Algorithms+Protocols / Security analysis /
|
||||
Complexity analysis / Deployment considerations / Appendices — is on
|
||||
the active writing track.
|
||||
|
||||
### KAT suite generated
|
||||
|
||||
`vectors/{keygen,sign,verify,threshold-sign,dkg}.json` are committed.
|
||||
`scripts/gen_vectors.sh` re-runs the generator and verifies that
|
||||
re-running produces byte-identical output (the deterministic-fixture
|
||||
gate). The CAVS-style `kat-v1.rsp` ACVP companion is on the v0.2
|
||||
path; ACVP support requires the post-encoding-freeze byte layout.
|
||||
|
||||
### Lattice-estimator parameter table empty
|
||||
|
||||
`estimator/results.md` will hold the classical + quantum security-level
|
||||
table. Generated by lattice-estimator runs once the parameter set is
|
||||
finalized.
|
||||
|
||||
## Compared to Pulsar (R-LWE)
|
||||
|
||||
| dimension | Pulsar | Pulsar-M |
|
||||
|---|---|---|
|
||||
| Algebraic basis | Ring-LWE | Module-LWE |
|
||||
| Hash | SHA-3 cSHAKE / BLAKE3 legacy | SHA-3 cSHAKE only |
|
||||
| FIPS 204 output interchange | no (R-LWE) | yes (target) |
|
||||
| MPTC class | S1/S4 | N1/N4 |
|
||||
| Parameter sets | Pulsar-internal | ML-DSA-44/65/87 |
|
||||
| DKG | Pedersen over `R_q` | Pedersen over `R_q^k` |
|
||||
| Reshare | deterministic quorum | beacon-randomized quorum |
|
||||
|
||||
Where Pulsar provides feature X and Pulsar-M doesn't yet, Pulsar-M's
|
||||
goal is to inherit X verbatim from Pulsar's `dkg2/` and `reshare/`
|
||||
packages with the M-LWE shape change.
|
||||
@@ -0,0 +1,140 @@
|
||||
# NIST MPTC category targeting
|
||||
|
||||
> Reference: NIST IR 8214C, *First Call for Multi-Party Threshold Schemes*
|
||||
> (January 2026). Package deadline expected 2026-Nov-16. Preview deadline
|
||||
> 2026-Jul-20.
|
||||
|
||||
## Pulsar-M target: **Class N1 + N4**
|
||||
|
||||
NIST MPTC subdivides threshold schemes into:
|
||||
|
||||
- **Class S** (Special) — threshold-friendly primitives that *are not*
|
||||
output-interchangeable with a NIST-specified primitive. Submission
|
||||
evaluated for "novel threshold-friendly design."
|
||||
- **Class N** (Normal-mode) — threshold implementations *of* a NIST-specified
|
||||
primitive whose outputs are interchangeable with the corresponding
|
||||
non-threshold primitive's outputs.
|
||||
- **N1**: signing
|
||||
- **N2**: encryption / decryption
|
||||
- **N3**: KEM
|
||||
- **N4**: ML keygen / DKG (Module-Lattice key generation, distributed)
|
||||
|
||||
Pulsar-M aims for **N1 (threshold ML-DSA signing) + N4 (distributed ML-DSA
|
||||
keygen)**. The headline interchangeability claim:
|
||||
|
||||
> A signature `σ` produced by a Pulsar-M threshold ceremony on message `μ`
|
||||
> against group public key `pk` verifies under unmodified
|
||||
> [FIPS 204 ML-DSA.Verify(pk, μ, σ)] returning `accept`.
|
||||
|
||||
If we can prove and demonstrate this, Pulsar-M is a Class N candidate. If
|
||||
the output is not bit-for-bit FIPS 204 (e.g. encoding differs in any
|
||||
field), Pulsar-M falls back to Class S — still valid, but a weaker NIST
|
||||
positioning.
|
||||
|
||||
## Output interchangeability — what has to hold
|
||||
|
||||
ML-DSA-65 signatures (FIPS 204 §5.4, Algorithm 26 `sigEncode`) are
|
||||
encoded as a fixed-length 3309-byte string σ = (c̃, z, h) whose three
|
||||
components decompose exactly as:
|
||||
|
||||
```
|
||||
σ = (c̃ ‖ z ‖ h) 3309 bytes
|
||||
c̃ ∈ {0,1}^{2λ} 48 bytes
|
||||
// FIPS 204 commitment-hash length; 2λ bits with λ=192 = 384 bits.
|
||||
// (2λ here is the FIPS 204 commitment-hash parameter, not the
|
||||
// security level — the two happen to numerically agree for
|
||||
// ML-DSA-65 because the standard ties one to the other at this
|
||||
// parameter set.)
|
||||
z ∈ R^ℓ_q 3200 bytes
|
||||
// ℓ = 5 polynomials, each 256 coefficients, packed at
|
||||
// log2(2γ_1) = 20 bits per coefficient.
|
||||
// 5 · 256 · 20 / 8 = 3200 bytes.
|
||||
h ∈ {0,1}^{ω + k} 61 bytes
|
||||
// ω = 55 (hint bound), k = 6 (commitment-vector dimension).
|
||||
// FIPS 204 Algorithm 22 `hintBitPack` + Algorithm 28
|
||||
// `sigEncode` pack ω + k = 61 bits as 61 bytes (one byte per
|
||||
// bit position, terminator-first encoding per the standard).
|
||||
total: 48 + 3200 + 61 = 3309 bytes ✓ FIPS 204 Table 2
|
||||
```
|
||||
|
||||
For Pulsar-M to claim Class N1, the threshold-aggregated signature MUST
|
||||
deserialize as exactly this triple, with the same byte layout, the same
|
||||
canonicalization rules, and the same rejection criteria. The threshold
|
||||
protocol is allowed to perform multiple rounds internally, but its emitted
|
||||
artifact MUST be a single FIPS 204 σ.
|
||||
|
||||
This is non-trivial: ML-DSA's rejection sampling means a single-shot
|
||||
threshold output can fail rejection and require restart. Pulsar's
|
||||
2-round structure handles this for R-LWE; Pulsar-M needs to reproduce
|
||||
the rejection-restart logic for M-LWE without leaking secret information
|
||||
across the restart.
|
||||
|
||||
## Required package deliverables
|
||||
|
||||
Per NIST IR 8214C §5:
|
||||
|
||||
| element | format | location |
|
||||
|---|---|---|
|
||||
| Technical Specification | PDF (LaTeX) | `spec/pulsar-m.pdf` |
|
||||
| Reference Implementation | open-source code | `ref/go/` |
|
||||
| Report on Experimental Evaluation | PDF + reproducible scripts | `bench/results/REPORT.md` + `bench/run_all.sh` |
|
||||
| Notes on Patent Claims | PDF | `docs/patent-notes-draft.md` → finalized |
|
||||
| Concrete parameter set | section in spec | `spec/parameters.tex` |
|
||||
| Security analysis (proofs) | section in spec | `spec/security-games.tex` |
|
||||
| Public repository | GitHub or equiv | `https://github.com/luxfi/pulsar-m` |
|
||||
| Build/test/benchmark scripts | shell | `scripts/*.sh` |
|
||||
| Open-source license | text | `LICENSE` (Apache-2.0) |
|
||||
| I/O test vectors | JSON / RSP | `vectors/kat-v1.{json,rsp}` |
|
||||
|
||||
Optional but strongly recommended:
|
||||
- Executive summary (1-2 pages) at front of spec.
|
||||
- Threat-model document (`docs/threat-model.md`).
|
||||
- System-model document (`docs/system-model.md` → `spec/system-model.tex`).
|
||||
- Known-limitations appendix (so reviewers see the gaps before they find them).
|
||||
|
||||
## Required security strengths
|
||||
|
||||
NIST MPTC §4.5 gives the required and suggested security-strength targets:
|
||||
|
||||
| target | classical | post-quantum (NIST PQ category) | statistical |
|
||||
|---|---|---|---|
|
||||
| **required** (≥1 parameterization) | ≥ 128 bits | ≥ Category 1 | ≥ 40 bits |
|
||||
| **suggested** (additional, optional) | ≥ 192 bits | ≥ Category 3 | ≥ 64 bits |
|
||||
|
||||
Pulsar-M will ship parameter sets matching ML-DSA-65 (Category 3) for the
|
||||
suggested target, and potentially ML-DSA-44 (Category 2) and ML-DSA-87
|
||||
(Category 5) for full coverage.
|
||||
|
||||
## Class N vs Class S decision
|
||||
|
||||
Pulsar-M is N if and only if:
|
||||
1. A working reference implementation produces signatures byte-equal to
|
||||
FIPS 204 ML-DSA on the same `(pk, μ)` for some valid threshold ceremony.
|
||||
2. The threshold key generation produces a `pk` that's a valid FIPS 204
|
||||
ML-DSA public key (no extra public material distinguishable from a
|
||||
single-party `pk`).
|
||||
3. The verification relation in the spec is the FIPS 204 verifier
|
||||
verbatim, with no Pulsar-specific changes.
|
||||
|
||||
If any of (1)-(3) fails, we ship as Class S with a clear "future work:
|
||||
output interchangeability" note. The class decision is finalized at the
|
||||
point we freeze the spec encoding.
|
||||
|
||||
## Pulsar (R-LWE) for comparison
|
||||
|
||||
Pulsar (R-LWE) targets **Class S1 + S4**: special threshold-friendly
|
||||
two-round signature, not output-interchangeable with any NIST-approved
|
||||
primitive. The S1/S4 framing is the right framing for Corona-derivatives
|
||||
unless and until NIST blesses Corona-shaped outputs as a primitive.
|
||||
|
||||
## Status
|
||||
|
||||
- [ ] Class declared (N vs S, awaiting spec freeze)
|
||||
- [ ] Preview writeup drafted
|
||||
- [ ] Preview submitted (target 2026-Jul-20)
|
||||
- [ ] Spec freeze
|
||||
- [ ] Reference impl complete
|
||||
- [ ] KATs cross-validated against FIPS 204 reference
|
||||
- [ ] Experimental-evaluation report
|
||||
- [ ] Patent-claims notes finalized
|
||||
- [ ] Package submitted (target 2026-Nov-16)
|
||||
@@ -0,0 +1,91 @@
|
||||
# Notes on patent claims (draft)
|
||||
|
||||
> Required by NIST MPTC IR 8214C §5 as a package deliverable. This document
|
||||
> is collected over the development period and finalized for the
|
||||
> submission.
|
||||
|
||||
## Status
|
||||
|
||||
**Draft.** No patent claims have been formally identified. This page
|
||||
tracks claims as contributors disclose them.
|
||||
|
||||
## Inherited from upstream
|
||||
|
||||
### Pulsar (`luxfi/pulsar`)
|
||||
|
||||
Pulsar-M reuses Pulsar's protocol structure. Pulsar's IP posture per
|
||||
its README:
|
||||
|
||||
- Apache-2.0 licensed.
|
||||
- Patent grant per Apache 2.0 §3 from each contributor.
|
||||
- No known active patent claims as of repository creation.
|
||||
|
||||
This applies to Pulsar-M to the extent that Pulsar-M code or protocol
|
||||
elements are derivative of Pulsar.
|
||||
|
||||
### Corona (`luxfi/corona`)
|
||||
|
||||
Pulsar (and therefore Pulsar-M) is a fork of academic Corona.
|
||||
Corona (ePrint 2024/1113) authors: Cecilia Boschini, Darya Kaviani,
|
||||
Russell W. F. Lai, Giulio Malavolta, Akira Takahashi, Mehdi Tibouchi.
|
||||
Corona's open-source repo is Apache-2.0 with no asserted patent
|
||||
claims as of mid-2026. Pulsar-M's M-LWE adaptation does not import
|
||||
Corona code directly but inherits the protocol structure.
|
||||
|
||||
### ML-DSA / FIPS 204
|
||||
|
||||
ML-DSA is a NIST-standardized algorithm. The Dilithium team's IP
|
||||
disclosures during NIST PQC standardization are public on the NIST
|
||||
PQC website. Pulsar-M targets output interchangeability with FIPS 204
|
||||
but does not assert any rights over FIPS 204 itself.
|
||||
|
||||
## Contributor disclosures
|
||||
|
||||
Per CONTRIBUTING.md, every commit's `Signed-off-by` line is taken as
|
||||
either:
|
||||
1. An explicit assertion that the contributor has no relevant patent
|
||||
claims, OR
|
||||
2. A reference to a disclosed claim listed below.
|
||||
|
||||
| date | contributor | type | disclosure |
|
||||
|---|---|---|---|
|
||||
| 2026-05-10 | Lux Industries Inc | initial repo | no claims asserted |
|
||||
|
||||
(Updated as contributions land.)
|
||||
|
||||
## Third-party patents we may need to navigate
|
||||
|
||||
Live concerns to investigate before submission:
|
||||
|
||||
- Lattice-estimator usage (we use the open-source estimator; license
|
||||
pass-through to MIT).
|
||||
- Gaussian sampler implementation (FIPS 204 references CDT; alternate
|
||||
rejection samplers may have IP).
|
||||
- Polynomial multiplication via NTT (standard, no known IP).
|
||||
- Pedersen commitments (1991 paper, expired patents).
|
||||
|
||||
The submission's Notes on Patent Claims will explicitly call out each
|
||||
of these.
|
||||
|
||||
## NIST MPTC submission requirements
|
||||
|
||||
NIST IR 8214C §5 (Notes on Patent Claims) requires:
|
||||
|
||||
> Submitter(s) shall include a statement of any patent claims known to
|
||||
> them that may be relevant to the submitted package, regardless of who
|
||||
> owns the claim. Statements of "no known claims" are acceptable.
|
||||
|
||||
Our final statement, once the spec freezes:
|
||||
|
||||
> *To be drafted at spec freeze. Will incorporate every disclosure in
|
||||
> the contributor table above, every inherited claim from Pulsar /
|
||||
> Corona / ML-DSA, and the third-party investigation outcome.*
|
||||
|
||||
## Process
|
||||
|
||||
1. Every PR review checks for new IP-relevant code.
|
||||
2. Significant cryptographic additions (new sampling routine, new
|
||||
commitment shape, new aggregation step) trigger an explicit IP
|
||||
review with one of the sponsor's IP counsel.
|
||||
3. Final statement assembled at freeze, included in
|
||||
`spec/pulsar-m.pdf` Appendix A.
|
||||
@@ -0,0 +1,132 @@
|
||||
# Pulsar-M threat model
|
||||
|
||||
## Adversary classes
|
||||
|
||||
We give an adversary the union of the following capabilities, parameterized
|
||||
by `t` (the corruption threshold) and the corruption model:
|
||||
|
||||
### Static corruption (default)
|
||||
|
||||
- Adversary `A` selects up to `t-1` parties to corrupt **before** protocol
|
||||
start. From start to end of the protocol, those `t-1` parties are
|
||||
controlled; the remaining honest parties run the protocol faithfully.
|
||||
- `A` sees all messages on the broadcast channel + all messages on the
|
||||
authenticated point-to-point channels into corrupted parties.
|
||||
- `A` learns each corrupted party's full state (secret share, randomness,
|
||||
per-round values) including session-state values.
|
||||
- `A` can selectively delay messages within the round window but cannot
|
||||
forge messages from honest parties on authenticated channels.
|
||||
|
||||
### Adaptive corruption (stronger model)
|
||||
|
||||
- Adversary `A` can corrupt up to `t-1` parties at any time during the
|
||||
protocol, including mid-round, conditioned on the transcript so far.
|
||||
- Once corrupted, a party remains corrupted for the rest of the protocol.
|
||||
- All other capabilities as in static.
|
||||
|
||||
The Pulsar-M security analysis (`spec/security-games.tex`) provides the
|
||||
precise game definitions. Static security is the baseline; adaptive
|
||||
security is a stretch goal for the first MPTC submission and a hard
|
||||
requirement for the second-round response.
|
||||
|
||||
### Mobile corruption (proactive resharing)
|
||||
|
||||
For long-lived deployments where the validator set rotates between epochs
|
||||
(Pulsar's `reshare/` direction), the relevant model is HJKY97 mobile
|
||||
adversary: `A` can corrupt up to `t-1` parties **per epoch**, with the
|
||||
corruption set varying across epochs. The adversary may *uncorrupt* a
|
||||
party (forget what it learned) at epoch boundaries.
|
||||
|
||||
Pulsar-M proactive resharing inherits the soundness argument from Pulsar's
|
||||
`reshare/` (with the constant-time fix from F9 of the Hanzo HIP-0077
|
||||
red review). The MPTC submission documents the mobile-adversary game
|
||||
explicitly.
|
||||
|
||||
## Out-of-scope adversary capabilities
|
||||
|
||||
- Compromise of the cryptographic hash function (SHAKE-256 / cSHAKE-256 /
|
||||
KMAC-256). NIST FIPS 202 + SP 800-185 are taken as building blocks.
|
||||
- Side-channel attacks on the *physical* hardware running a party
|
||||
(power analysis, EM, fault injection). Mitigation discussed in
|
||||
`docs/known-limitations.md` as future work.
|
||||
- Compromise of the BIP-32/BIP-39 mnemonic from which device-specific
|
||||
keys are derived. The HD-derivation security argument lives in
|
||||
HIP-0077 §"Identity"; the Pulsar-M layer assumes parties' input keys
|
||||
are uniformly distributed.
|
||||
|
||||
## In-scope security goals
|
||||
|
||||
### Threshold unforgeability (TS-UF)
|
||||
|
||||
For any PPT adversary `A` controlling up to `t-1` parties, `A` cannot
|
||||
produce a valid Pulsar-M signature `σ*` on any message `μ*` that an
|
||||
honest signing ceremony has not produced.
|
||||
|
||||
### Robustness / identifiable abort
|
||||
|
||||
If a corrupted party deviates from the protocol, the honest parties:
|
||||
1. Detect the deviation.
|
||||
2. Identify the deviating party.
|
||||
3. Produce signed evidence of the deviation suitable for slashing /
|
||||
reputation reduction.
|
||||
|
||||
### Output indistinguishability from FIPS 204
|
||||
|
||||
A Pulsar-M signature `σ` on message `μ` against group public key `pk`
|
||||
is computationally indistinguishable from a FIPS 204 ML-DSA signature on
|
||||
the same `(pk, μ)`. Specifically: an adversary that can distinguish the
|
||||
two with non-negligible advantage breaks the underlying M-LWE assumption.
|
||||
|
||||
### Bias resistance
|
||||
|
||||
The randomness used in each party's contribution (Gaussian samples,
|
||||
challenge polynomials) is statistically indistinguishable from uniform
|
||||
even given the adversary's view of corrupted parties' randomness.
|
||||
|
||||
### DKG soundness
|
||||
|
||||
Pedersen DKG over `R_q^k` produces a public key `pk` distributed
|
||||
uniformly over the valid M-LWE public-key space, with no party holding
|
||||
more than `1/n` partial information about the corresponding secret key.
|
||||
|
||||
## Assumed channels
|
||||
|
||||
| channel | property | purpose |
|
||||
|---|---|---|
|
||||
| Broadcast | authenticated, eventual-delivery | round transcripts, public coins |
|
||||
| Point-to-point | authenticated, encrypted | private share / blind delivery |
|
||||
| Public bulletin | authenticated, append-only | DKG commitments, reshare records |
|
||||
|
||||
The reference implementation provides these channels via TCP + TLS.
|
||||
Production deployments (e.g. Lux consensus + Quasar) bind these to
|
||||
their existing P2P transport.
|
||||
|
||||
## Trusted parameters
|
||||
|
||||
- The cyclotomic ring `R_q = Z_q[X] / (X^256 + 1)` and parameters
|
||||
`(q, k, ℓ, η, β, ω, …)` exactly as in FIPS 204 ML-DSA-65.
|
||||
- The hash family: SHAKE-256 (FIPS 202), cSHAKE-256 / KMAC-256 /
|
||||
TupleHash-256 (NIST SP 800-185). Customization tags are pinned in
|
||||
`spec/pulsar-m.tex`.
|
||||
- The Gaussian sampler parameters from FIPS 204 §3.3 / §4.2.
|
||||
|
||||
No trusted setup beyond NIST primitives.
|
||||
|
||||
## Failure modes addressed
|
||||
|
||||
The MPTC submission documents how Pulsar-M handles each failure mode that
|
||||
broke earlier threshold-lattice schemes:
|
||||
|
||||
- **Rejection-sampling restart leaking secret information across rounds**:
|
||||
Pulsar's PRNG-key per-round domain separation (CRIT-1 fix from
|
||||
upstream's 2026-05-03 amendment) ports forward.
|
||||
- **Constant-time share comparison**: `dkg2.constTimePolyEqual` pattern
|
||||
ported from upstream Pulsar (`reshare/commit.go` F9 fix).
|
||||
- **Information leaks via logging**: zero stdlib `log` use in any
|
||||
secret-touching path; all logging via `luxfi/log` at fields that are
|
||||
explicitly public.
|
||||
- **Deterministic quorum selection in resharing leaking adversary
|
||||
positioning**: Pulsar-M uses a beacon-derived per-reshare quorum
|
||||
selection (HIP-0077 §"reshare quorum" F10 fix).
|
||||
- **Cross-mode hash-suite confusion**: NIST profile is exclusively
|
||||
SHA-3 family; no BLAKE3 in Pulsar-M ever.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Lattice estimator
|
||||
|
||||
Concrete classical and post-quantum security-strength tables for each
|
||||
Pulsar-M parameter set, generated by Albrecht et al.'s lattice-estimator
|
||||
(<https://github.com/malb/lattice-estimator>).
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Pin the estimator commit hash in `params.sage`.
|
||||
2. Run via SageMath:
|
||||
```bash
|
||||
sage estimator/params.sage > estimator/results.md
|
||||
```
|
||||
3. Commit `params.sage`, `results.md`, and the estimator commit hash
|
||||
together so reviewers can reproduce.
|
||||
|
||||
## Targets
|
||||
|
||||
NIST MPTC §4.5 minimum:
|
||||
- Required: classical ≥ 128 bits, NIST PQ Cat ≥ 1, statistical ≥ 40 bits.
|
||||
- Suggested: classical ≥ 192 bits, NIST PQ Cat ≥ 3, statistical ≥ 64 bits.
|
||||
|
||||
Pulsar-M parameter sets:
|
||||
- `Pulsar-M-44` → required tier
|
||||
- `Pulsar-M-65` → suggested tier (default for Hanzo / Lux)
|
||||
- `Pulsar-M-87` → highest NIST PQ Cat 5
|
||||
|
||||
Each parameter set's M-LWE instance is restated from FIPS 204 §4 with
|
||||
the same `(q, k, ℓ, η)` so estimator output is comparable to ML-DSA.
|
||||
|
||||
## Status
|
||||
|
||||
- [ ] `params.sage` skeleton with FIPS 204 parameters
|
||||
- [ ] First estimator run on Pulsar-M-65
|
||||
- [ ] Full table for all three parameter sets
|
||||
- [ ] Sanity comparison with FIPS 204 published security levels
|
||||
@@ -0,0 +1,10 @@
|
||||
module github.com/luxfi/pulsar-m
|
||||
|
||||
go 1.22.0
|
||||
|
||||
require (
|
||||
github.com/cloudflare/circl v1.6.3
|
||||
golang.org/x/crypto v0.32.0
|
||||
)
|
||||
|
||||
require golang.org/x/sys v0.29.0 // indirect
|
||||
@@ -0,0 +1,6 @@
|
||||
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
||||
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
@@ -0,0 +1,31 @@
|
||||
// Package pulsarm is the reference implementation of Pulsar-M, a threshold
|
||||
// implementation of NIST FIPS 204 ML-DSA targeting NIST MPTC Class N1
|
||||
// (signing) + N4 (ML keygen / DKG).
|
||||
//
|
||||
// The headline claim of Pulsar-M is output interchangeability with FIPS 204:
|
||||
// a signature produced by an n-of-t threshold ceremony verifies under
|
||||
// unmodified FIPS 204 ML-DSA.Verify(pk, message, signature). See
|
||||
// docs/nist-mptc-category.md for the formal claim and its scope.
|
||||
//
|
||||
// Status: pre-spec-freeze. The exported API in this package will change
|
||||
// up to the spec encoding freeze (target end of August 2026). After
|
||||
// freeze the API is fixed and a v0.1 tag will be cut.
|
||||
//
|
||||
// All cryptographic operations route through:
|
||||
//
|
||||
// - sub-package "hash" — NIST SP 800-185 (cSHAKE256/KMAC256/TupleHash256) only
|
||||
// - sub-package "primitives" — Module-LWE polynomial-vector arithmetic
|
||||
// - sub-package "sign" — two-round threshold sign protocol
|
||||
// - sub-package "dkg" — Pedersen DKG over R_q^k
|
||||
// - sub-package "reshare" — proactive resharing with beacon-randomized quorum
|
||||
// - sub-package "fmt" — wire encoding / KAT format
|
||||
//
|
||||
// All logging — including for any error path — uses github.com/luxfi/log.
|
||||
// The standard library's log package is forbidden in this module: a
|
||||
// secret-correlated value reaching stdout is a side channel even at debug
|
||||
// level (HIP-0077 red review F8). This is enforced by a CI lint, not just
|
||||
// convention.
|
||||
package pulsarm
|
||||
|
||||
// Version is the spec version this implementation targets.
|
||||
const Version = "0.0.0-spec-draft"
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package pulsarm
|
||||
|
||||
import "testing"
|
||||
|
||||
// TestVersion is a sanity check that the module builds at all and the
|
||||
// version constant exists. The reference implementation grows from this
|
||||
// minimum point as the spec freezes.
|
||||
func TestVersion(t *testing.T) {
|
||||
if Version == "" {
|
||||
t.Fatalf("Version constant must be set")
|
||||
}
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
# Pulsar-M reproducible benchmarks.
|
||||
#
|
||||
# Runs the experimental-evaluation harness and writes results to
|
||||
# bench/results/. Hardware fingerprint is captured so reviewers can compare.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
export GOWORK=off
|
||||
|
||||
OUT_DIR="bench/results"
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
echo "==> hardware fingerprint"
|
||||
{
|
||||
uname -a
|
||||
if command -v sysctl >/dev/null 2>&1; then
|
||||
sysctl -a 2>/dev/null | grep -E 'machdep\.cpu\.brand_string|hw\.ncpu|hw\.memsize' || true
|
||||
fi
|
||||
if [[ -f /proc/cpuinfo ]]; then
|
||||
grep -E 'model name|cpu MHz' /proc/cpuinfo | head -2
|
||||
fi
|
||||
go version
|
||||
} > "$OUT_DIR/fingerprint.txt"
|
||||
|
||||
echo "==> Go benchmarks"
|
||||
go test -bench=. -benchmem -count=3 -run=^$ -benchtime=2s ./ref/go/... | tee "$OUT_DIR/go-bench.txt"
|
||||
|
||||
echo "==> done — results in $OUT_DIR/"
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
# Pulsar-M reproducible build.
|
||||
#
|
||||
# Builds the Go reference implementation and the LaTeX spec PDF. Exits
|
||||
# non-zero on any failure. Designed to be the CI gate.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# Build the reference impl in module-only mode. A surrounding workspace
|
||||
# (e.g. ~/work/lux/go.work) does not own this repo's deps and must be
|
||||
# bypassed deliberately so reviewers get the same view CI gets.
|
||||
export GOWORK=off
|
||||
|
||||
echo "==> Go reference build"
|
||||
go build ./ref/go/...
|
||||
|
||||
echo "==> Spec PDF build (skipped if latexmk not installed)"
|
||||
if command -v latexmk >/dev/null 2>&1; then
|
||||
( cd spec && latexmk -pdf -interaction=nonstopmode pulsar-m.tex )
|
||||
else
|
||||
echo " [warn] latexmk not found — skipping. Install TeX Live for full build."
|
||||
fi
|
||||
|
||||
echo "==> done"
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# Pulsar-M KAT regeneration.
|
||||
#
|
||||
# Regenerates vectors/{keygen,sign,verify,threshold-sign,dkg}.json from
|
||||
# the reference implementation. Re-running on a clean checkout MUST
|
||||
# produce byte-identical output — this is the deterministic-fixture
|
||||
# gate enforced by CI.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
mkdir -p vectors/transcripts
|
||||
|
||||
export GOWORK=off
|
||||
|
||||
echo "==> Reference KAT generator"
|
||||
go run ./ref/go/cmd/genkat -out vectors
|
||||
|
||||
echo "==> Verifying KAT round-trip via replay tests"
|
||||
go test -count=1 -run "^TestKAT_" ./ref/go/pkg/pulsarm/
|
||||
|
||||
echo "==> done"
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
# Pulsar-M SBOM generation.
|
||||
#
|
||||
# Produces an SPDX SBOM for the reference implementation, capturing every
|
||||
# transitive dependency. Required as part of the MPTC submission package.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
OUT="bench/results/sbom.spdx.json"
|
||||
mkdir -p "$(dirname "$OUT")"
|
||||
|
||||
if command -v cyclonedx-gomod >/dev/null 2>&1; then
|
||||
( cd ref/go && cyclonedx-gomod mod -json -output "$REPO_ROOT/$OUT" )
|
||||
elif command -v go-licenses >/dev/null 2>&1; then
|
||||
echo " [info] cyclonedx-gomod not found; falling back to go-licenses report"
|
||||
( cd ref/go && go-licenses csv ./... > "$REPO_ROOT/${OUT%.json}.csv" )
|
||||
else
|
||||
echo " [warn] no SBOM tool found (install cyclonedx-gomod or go-licenses)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> SBOM written to $OUT"
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Pulsar-M test suite runner.
|
||||
#
|
||||
# Runs unit tests, KAT validation (when available), and the no-secret-logs
|
||||
# linter. Designed to be the CI gate alongside scripts/build.sh.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# Module-only build. See note in scripts/build.sh.
|
||||
export GOWORK=off
|
||||
|
||||
echo "==> Go unit tests"
|
||||
go test -count=1 -race ./ref/go/...
|
||||
|
||||
echo "==> No-secret-logs linter"
|
||||
# DD-007: secret-touching files MUST NOT use stdlib log.* / fmt.Print* /
|
||||
# panic. This list is the implementation surface that touches secrets.
|
||||
SECRET_FILES=(
|
||||
"ref/go/pkg/pulsarm/keygen.go"
|
||||
"ref/go/pkg/pulsarm/sign.go"
|
||||
"ref/go/pkg/pulsarm/dkg.go"
|
||||
"ref/go/pkg/pulsarm/threshold.go"
|
||||
"ref/go/pkg/pulsarm/reshare.go"
|
||||
"ref/go/pkg/pulsarm/shamir.go"
|
||||
)
|
||||
for f in "${SECRET_FILES[@]}"; do
|
||||
if [[ -f "$f" ]]; then
|
||||
# Allow comments mentioning these tokens, but forbid actual use:
|
||||
# filter out lines starting with // and import-comment blocks.
|
||||
if grep -nE '^[^/]*(\<log\.(Print|Fatal|Panic)|fmt\.(Print|Fprint)|panic\()' "$f" \
|
||||
| grep -vE '^\s*//' ; then
|
||||
echo "FAIL: secret-touching file $f contains forbidden logging or panic" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo "==> KAT validation"
|
||||
if [[ -f vectors/keygen.json ]]; then
|
||||
go test -count=1 -run "^TestKAT_" ./ref/go/pkg/pulsarm/
|
||||
else
|
||||
echo " [info] vectors/ not generated — run scripts/gen_vectors.sh"
|
||||
fi
|
||||
|
||||
echo "==> done"
|
||||
@@ -0,0 +1,54 @@
|
||||
% Pulsar-M concrete parameter sets — included by pulsar-m.tex §"Concrete parameters"
|
||||
|
||||
\subsection*{Parameter sets}
|
||||
|
||||
% Three parameter sets, mirroring FIPS 204 ML-DSA's three security levels.
|
||||
% Numeric values to be filled in from FIPS 204 §4 once the M-LWE port is
|
||||
% finalized; the Pulsar-M parameter table is structurally identical to
|
||||
% ML-DSA's because the underlying ring + module shape are inherited.
|
||||
|
||||
\begin{center}
|
||||
\begin{tabular}{l r r r}
|
||||
\hline
|
||||
parameter & Pulsar-M-44 & Pulsar-M-65 & Pulsar-M-87 \\
|
||||
\hline
|
||||
NIST PQ category & TBD (Cat 2) & TBD (Cat 3) & TBD (Cat 5) \\
|
||||
classical security (bits) & TBD ($\geq128$) & TBD ($\geq192$) & TBD ($\geq256$) \\
|
||||
quantum security (bits) & TBD & TBD & TBD \\
|
||||
modulus $q$ & 8380417 & 8380417 & 8380417 \\
|
||||
ring degree $n$ & 256 & 256 & 256 \\
|
||||
module dimension $k$ & 4 & 6 & 8 \\
|
||||
secret dimension $\ell$ & 4 & 5 & 7 \\
|
||||
secret coefficient bound $\eta$& 2 & 4 & 2 \\
|
||||
challenge weight $\tau$ & 39 & 49 & 60 \\
|
||||
hint bound $\omega$ & 80 & 55 & 75 \\
|
||||
threshold $(n, t)$ & runtime & runtime & runtime \\
|
||||
\hline
|
||||
signature size (bytes) & 2420 & 3309 & 4627 \\
|
||||
public key size (bytes) & 1312 & 1952 & 2592 \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
% TODO. Fill in security-level numbers from a lattice-estimator run.
|
||||
% Pin the script in estimator/params.sage and the result table in
|
||||
% estimator/results.md. Cite the estimator commit hash.
|
||||
|
||||
\subsection*{Lattice-estimator inputs}
|
||||
|
||||
% TODO. Each parameter set's M-LWE instance, run through the
|
||||
% lattice-estimator (https://github.com/malb/lattice-estimator) for
|
||||
% classical and quantum cost estimates. Reproducible from
|
||||
% estimator/params.sage.
|
||||
|
||||
\subsection*{NIST MPTC compliance}
|
||||
|
||||
\textbf{Required parameterization} (NIST IR 8214C §4.5): at least one
|
||||
parameter set with classical $\geq 128$ bits, NIST PQ category $\geq 1$,
|
||||
statistical $\geq 40$ bits. Pulsar-M-44 satisfies this.
|
||||
|
||||
\textbf{Suggested parameterization}: at least one parameter set with
|
||||
classical $\geq 192$ bits, NIST PQ category $\geq 3$, statistical
|
||||
$\geq 64$ bits. Pulsar-M-65 satisfies this.
|
||||
|
||||
Pulsar-M-87 covers the highest NIST PQ category for completeness.
|
||||
+1536
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,103 @@
|
||||
% Pulsar-M bibliography
|
||||
%
|
||||
% Canonical citations for the technical specification. Authors and
|
||||
% identifiers verified against https://eprint.iacr.org and the linked
|
||||
% conference proceedings. Do not paraphrase or guess — every entry has a
|
||||
% checked source URL.
|
||||
|
||||
@misc{corona2024,
|
||||
author = {Cecilia Boschini and Darya Kaviani and Russell W.~F.~Lai
|
||||
and Giulio Malavolta and Akira Takahashi and Mehdi Tibouchi},
|
||||
title = {Corona: Practical Two-Round Threshold Signatures from Learning with Errors},
|
||||
howpublished = {Cryptology ePrint Archive, Paper 2024/1113},
|
||||
year = {2024},
|
||||
url = {https://eprint.iacr.org/2024/1113}
|
||||
}
|
||||
|
||||
@inproceedings{gks24,
|
||||
author = {Asl{\'i}han Y{\i}ld{\i}z G{\"u}r and Jonathan Katz and Tjerand Silde},
|
||||
title = {Two-Round Threshold Lattice-Based Signatures from Threshold Homomorphic Encryption},
|
||||
booktitle = {Post-Quantum Cryptography (PQCrypto)},
|
||||
year = {2024},
|
||||
note = {ePrint 2023/1318},
|
||||
url = {https://eprint.iacr.org/2023/1318}
|
||||
}
|
||||
|
||||
@inproceedings{dott21,
|
||||
author = {Ivan Damg{\aa}rd and Claudio Orlandi and Akira Takahashi and Mehdi Tibouchi},
|
||||
title = {Two-Round $n$-out-of-$n$ and Multi-Signatures and Trapdoor Commitment from Lattices},
|
||||
booktitle = {Public-Key Cryptography (PKC)},
|
||||
year = {2021},
|
||||
note = {ePrint 2020/1110},
|
||||
url = {https://eprint.iacr.org/2020/1110}
|
||||
}
|
||||
|
||||
@misc{ddm23,
|
||||
author = {Luc Devevey and Pouria Doshi and Pratyay Maitra},
|
||||
title = {Threshold Dilithium},
|
||||
year = {2023},
|
||||
note = {to be cited from the canonical paper / ePrint number once verified;
|
||||
prior draft incorrectly cited 2023/769 (Brakedown) — do not reuse}
|
||||
}
|
||||
|
||||
@misc{olingo2025,
|
||||
title = {Olingo: Threshold ML-DSA},
|
||||
howpublished = {Cryptology ePrint Archive, Paper 2025/1789},
|
||||
year = {2025},
|
||||
url = {https://eprint.iacr.org/2025/1789}
|
||||
}
|
||||
|
||||
@misc{thed2026,
|
||||
title = {THED},
|
||||
howpublished = {Cryptology ePrint Archive, Paper 2026/638},
|
||||
year = {2026},
|
||||
url = {https://eprint.iacr.org/2026/638}
|
||||
}
|
||||
|
||||
@misc{nist-fips204,
|
||||
author = {{National Institute of Standards and Technology}},
|
||||
title = {Module-Lattice-Based Digital Signature Standard (FIPS 204)},
|
||||
year = {2024},
|
||||
url = {https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf}
|
||||
}
|
||||
|
||||
@misc{nist-fips202,
|
||||
author = {{National Institute of Standards and Technology}},
|
||||
title = {SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions (FIPS 202)},
|
||||
year = {2015},
|
||||
url = {https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf}
|
||||
}
|
||||
|
||||
@misc{nist-sp800-185,
|
||||
author = {{National Institute of Standards and Technology}},
|
||||
title = {{SHA-3 Derived Functions: cSHAKE, KMAC, TupleHash, and ParallelHash} (SP 800-185)},
|
||||
year = {2016},
|
||||
url = {https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf}
|
||||
}
|
||||
|
||||
@misc{nist-ir-8214c,
|
||||
author = {{National Institute of Standards and Technology}},
|
||||
title = {{NIST IR 8214C: First Call for Multi-Party Threshold Schemes}},
|
||||
year = {2026},
|
||||
url = {https://csrc.nist.gov/pubs/ir/8214/c/final}
|
||||
}
|
||||
|
||||
@misc{nist-mptc,
|
||||
author = {{National Institute of Standards and Technology}},
|
||||
title = {Multi-Party Threshold Cryptography (MPTC)},
|
||||
url = {https://csrc.nist.gov/projects/threshold-cryptography}
|
||||
}
|
||||
|
||||
@inproceedings{hjky97,
|
||||
author = {Amir Herzberg and Markus Jakobsson and Stanis{\l}aw Jarecki and Hugo Krawczyk and Moti Yung},
|
||||
title = {Proactive public key and signature systems},
|
||||
booktitle = {ACM Conference on Computer and Communications Security (CCS)},
|
||||
year = {1997},
|
||||
note = {Mobile-adversary model for proactive resharing}
|
||||
}
|
||||
|
||||
@misc{lattice-estimator,
|
||||
author = {Martin R.~Albrecht and others},
|
||||
title = {Lattice Estimator},
|
||||
url = {https://github.com/malb/lattice-estimator}
|
||||
}
|
||||
@@ -0,0 +1,567 @@
|
||||
% Pulsar-M security game definitions --- included by pulsar-m.tex
|
||||
% \section{Security analysis}
|
||||
%
|
||||
% Standard cryptographic-game style. Each game pins the challenger
|
||||
% setup, the adversary's oracle interface, the winning condition, and
|
||||
% the advantage; reductions are stated to the underlying assumption.
|
||||
|
||||
\subsection{Adversary model and notation}
|
||||
\label{sec:sec-notation}
|
||||
|
||||
Throughout this section the adversary $\mathcal{A}$ is probabilistic
|
||||
polynomial-time (PPT) and is parameterised by the corruption
|
||||
threshold $t-1$ (the largest number of parties $\mathcal{A}$ may
|
||||
corrupt). Honest parties' channels are authenticated; corrupted
|
||||
parties act under $\mathcal{A}$'s control. We write $\mathcal{H}
|
||||
\subseteq \{1, \dots, n\}$ for the honest-party set and
|
||||
$\mathcal{C} = \{1, \dots, n\} \setminus \mathcal{H}$ for the corrupted
|
||||
set; $|\mathcal{C}| \le t-1$.
|
||||
|
||||
The challenger maintains a transcript log
|
||||
$\mathcal{T}$ recording every message visible to $\mathcal{A}$
|
||||
(broadcast messages, point-to-point messages into corrupted parties,
|
||||
public bulletin entries). The adversary's oracle interface depends on
|
||||
the game; we specify it inline.
|
||||
|
||||
We write $\mathcal{H}_{\mathsf{RO}}$ for the random oracle used to model the
|
||||
hash family $\{\SHAKE, \cSHAKE, \KMAC, \TupleHash\}$ in the ROM
|
||||
analysis. Distinct customisation tags yield independent random
|
||||
oracles by the indifferentiability argument of
|
||||
SP~800-185~\cite{nist-sp800-185}.
|
||||
|
||||
% =====================================================================
|
||||
\subsection{Game TS-UF (threshold strong unforgeability)}
|
||||
\label{sec:game-tsuf}
|
||||
% =====================================================================
|
||||
|
||||
\begin{game}[TS-UF]
|
||||
\label{game:tsuf}
|
||||
The challenger:
|
||||
\begin{enumerate}[leftmargin=*, itemsep=0pt]
|
||||
\item Runs $\DKG$ honestly across $n$ simulated parties; the adversary
|
||||
sees every transcript message and learns the shares
|
||||
$\{(\mathbf{s}_i, \mathbf{u}_i)\}_{i \in \mathcal{C}}$ of corrupted
|
||||
parties. The group public key $\mathit{pk}$ is announced.
|
||||
\item Exposes a $\Sign$ oracle $\mathcal{O}_{\Sign}(\mu, T)$: the
|
||||
adversary chooses a message $\mu$ and a quorum
|
||||
$T \subseteq \{1, \dots, n\}$ with $|T| = t$ and
|
||||
$|T \cap \mathcal{C}| \le t-1$. The challenger simulates honest
|
||||
parties' contributions to $\Sign(\mu, T)$ and returns the full
|
||||
transcript including the final FIPS~204 signature $\sigma$.
|
||||
\item Exposes a $\mathcal{H}_{\mathsf{RO}}$ oracle for all FIPS~202 / SP~800-185 hash
|
||||
calls.
|
||||
\end{enumerate}
|
||||
|
||||
The adversary outputs a forgery $(\mu^*, \sigma^*)$. $\mathcal{A}$
|
||||
wins if:
|
||||
\begin{enumerate}[label=(\roman*), leftmargin=*, itemsep=0pt]
|
||||
\item $\texttt{ML-DSA.Verify}(\mathit{pk}, \mu^*, \sigma^*) = \mathit{accept}$,
|
||||
\item $\mathcal{A}$ did not query $\mathcal{O}_{\Sign}(\mu^*, \cdot)$ with
|
||||
the same $\mu^*$ producing $\sigma^*$, and
|
||||
\item $|\mathcal{C}| \le t-1$ (the corruption budget was respected).
|
||||
\end{enumerate}
|
||||
$\mathcal{A}$'s advantage is
|
||||
$\Adv^{\mathsf{TS\textsf{-}UF}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A}) = \Pr[\mathcal{A} \text{ wins}]$.
|
||||
\end{game}
|
||||
|
||||
\begin{theorem}[TS-UF security]
|
||||
\label{thm:tsuf}
|
||||
For every $\PPT$ adversary $\mathcal{A}$ against \Cref{game:tsuf} with
|
||||
$q_S$ signing queries and $q_H$ random-oracle queries, there exist
|
||||
efficient reductions $\mathcal{B}_{\MLWE}, \mathcal{B}_{\MSIS},
|
||||
\mathcal{B}_{\mathrm{ML\text{-}DSA}}$ such that
|
||||
\[
|
||||
\Adv^{\mathsf{TS\textsf{-}UF}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A})
|
||||
\;\le\;
|
||||
\Adv^{\MLWE}_{q, k, \ell, \eta}(\mathcal{B}_{\MLWE})
|
||||
+ \Adv^{\MSIS}_{q, k, 2\ell, \beta_{\mathrm{bind}}}(\mathcal{B}_{\MSIS})
|
||||
+ \Adv^{\mathsf{EUF\textsf{-}CMA}}_{\mathrm{ML\text{-}DSA}}(\mathcal{B}_{\mathrm{ML\text{-}DSA}})
|
||||
+ \frac{q_S \cdot q_H}{2^\lambda}.
|
||||
\]
|
||||
\end{theorem}
|
||||
|
||||
\begin{proof}[Proof sketch]
|
||||
We argue via a sequence of hybrids:
|
||||
|
||||
\paragraph{Hybrid $H_0$.} The real TS-UF experiment.
|
||||
|
||||
\paragraph{Hybrid $H_1$.} The challenger simulates the $\Sign$ oracle
|
||||
without using the honest parties' shares. Specifically, the
|
||||
simulator chooses the final signature $\sigma = (\tilde c, \mathbf{z},
|
||||
\mathbf{h})$ by running \texttt{ML-DSA.Sign} against $\mathit{pk}$
|
||||
\emph{as if it knew the secret key}, then programs the per-party
|
||||
transcript so the aggregation lands on the chosen $\sigma$. The
|
||||
honest-party Round-1 commits are set to $\mathbf{w}_j^{(\mathrm{sim})} =
|
||||
\mathbf{A}\mathbf{y}_j^{(\mathrm{sim})}$ for simulated masks $\mathbf{y}_j^{(\mathrm{sim})}$
|
||||
drawn uniformly under the $U_{\gamma_1}$ constraint and consistent with
|
||||
the chosen $\mathbf{z}$ via
|
||||
$\sum_j \mathbf{y}_j^{(\mathrm{sim})} = \mathbf{z} - c\mathbf{s}_1$.
|
||||
Random-oracle programming sets the $\bar{\mathbf{w}}$-derived challenge to
|
||||
the chosen $\tilde c$. The distinguishing advantage between $H_0$
|
||||
and $H_1$ is bounded by $q_S \cdot q_H / 2^\lambda$ (probability of a
|
||||
collision in the RO programming).
|
||||
|
||||
\paragraph{Hybrid $H_2$.} The challenger replaces the Pedersen commit
|
||||
matrix $\mathbf{B}$'s structure --- $\mathbf{B}$ is now a fresh
|
||||
uniform matrix \emph{independent} of $\mathbf{A}$. This is identical
|
||||
to $H_1$ because $\mathbf{B}$ was already derived from a separate
|
||||
domain-separated seed in the construction; the hybrid is a no-op
|
||||
distributionally and is included only for proof clarity.
|
||||
|
||||
\paragraph{Hybrid $H_3$.} The challenger replaces the DKG-time
|
||||
Pedersen blinding $\mathbf{u}$ with a uniform sample from $\Rq^\ell$
|
||||
(rather than $\chi_\eta^\ell$). Distinguishing advantage is bounded
|
||||
by $\Adv^{\MLWE}_{q, k, \ell, \eta}(\mathcal{B}_{\MLWE})$ via the
|
||||
hiding property of the Pedersen commitment
|
||||
(\Cref{thm:pedersen-hiding}).
|
||||
|
||||
\paragraph{Hybrid $H_4$ (reduction to ML-DSA EUF-CMA).} In $H_4$ the
|
||||
simulator obtains $\mathit{pk}$ from a single-party ML-DSA EUF-CMA
|
||||
challenger; it answers $\mathcal{O}_{\Sign}(\mu, T)$ queries by
|
||||
relaying the signing query to the ML-DSA challenger and using $H_1$'s
|
||||
simulator to expand the resulting $\sigma$ into a per-party
|
||||
transcript. Any adversary that wins TS-UF against this hybrid
|
||||
produces a forgery $(\mu^*, \sigma^*)$ that wins the ML-DSA EUF-CMA
|
||||
game (since the Pulsar-M $\Verify$ is unmodified ML-DSA
|
||||
$\Verify$). Distinguishing advantage between $H_3$ and $H_4$ is
|
||||
absorbed into the MSIS binding term: any deviation by the simulator
|
||||
from the honest-party transcript shape is detected by binding of the
|
||||
Pedersen commitment, contributing
|
||||
$\Adv^{\MSIS}_{q, k, 2\ell, \beta_{\mathrm{bind}}}(\mathcal{B}_{\MSIS})$.
|
||||
|
||||
Summing the hybrid advantages gives the bound. \qed
|
||||
\end{proof}
|
||||
|
||||
\begin{remark}[Tightness]
|
||||
The reduction is tight modulo the standard $q_S q_H / 2^\lambda$
|
||||
random-oracle programming penalty. For ML-DSA-65 ($\lambda = 192$),
|
||||
this term is negligible for any practical $(q_S, q_H)$. The MSIS
|
||||
term governs the Pedersen-binding side of the argument; the MLWE
|
||||
term governs the hiding side; the ML-DSA term governs the underlying
|
||||
single-party unforgeability. Pulsar-M inherits ML-DSA's EUF-CMA
|
||||
bound verbatim modulo these threshold-protocol-specific terms.
|
||||
\end{remark}
|
||||
|
||||
% =====================================================================
|
||||
\subsection{Game OUT-IND (output indistinguishability from FIPS~204)}
|
||||
\label{sec:game-outind}
|
||||
% =====================================================================
|
||||
|
||||
\begin{game}[OUT-IND]
|
||||
\label{game:outind}
|
||||
The challenger flips a fair bit $b \in \{0, 1\}$ at setup and exposes
|
||||
two oracles to $\mathcal{A}$:
|
||||
\begin{itemize}[leftmargin=*, itemsep=0pt]
|
||||
\item If $b = 0$: $\DKG$ produces $\mathit{pk}$ honestly, and
|
||||
$\mathcal{O}_{\Sign}(\mu, T)$ runs Pulsar-M $\Sign$ honestly and
|
||||
returns only the final $\sigma$ (transcript is hidden).
|
||||
\item If $b = 1$: $\mathit{pk}$ is generated by single-party
|
||||
\texttt{ML-DSA.KeyGen}, and $\mathcal{O}_{\Sign}(\mu, T)$ ignores the
|
||||
quorum $T$ and runs single-party \texttt{ML-DSA.Sign}, returning
|
||||
$\sigma$.
|
||||
\end{itemize}
|
||||
$\mathcal{A}$ outputs a guess $\hat b$. Advantage:
|
||||
$\Adv^{\mathsf{OUT\textsf{-}IND}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A})
|
||||
= |\Pr[\hat b = b] - 1/2|$.
|
||||
\end{game}
|
||||
|
||||
\begin{theorem}[Output indistinguishability]
|
||||
\label{thm:outind}
|
||||
For every $\PPT$ adversary $\mathcal{A}$ against \Cref{game:outind},
|
||||
\[
|
||||
\Adv^{\mathsf{OUT\textsf{-}IND}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A})
|
||||
\;\le\;
|
||||
\Adv^{\MLWE}_{q, k, \ell, \eta}(\mathcal{B}_{\MLWE}) +
|
||||
\frac{1}{2^{2\lambda}}.
|
||||
\]
|
||||
\end{theorem}
|
||||
|
||||
\begin{proof}[Proof sketch]
|
||||
\textbf{$\mathit{pk}$ indistinguishability.}
|
||||
A FIPS~204 public key is $\mathit{pk}_{\mathrm{F}} = (\rho, \Power(\mathbf{A}\mathbf{s}_1 + \mathbf{s}_2, d))$ with $\mathbf{s}_1, \mathbf{s}_2 \gets \chi_\eta$.
|
||||
A Pulsar-M public key is $\mathit{pk}_{\mathrm{P}} = (\rho, \Power(\mathbf{A}\mathbf{s}_1 + \mathbf{B}\mathbf{u}, d))$ with $\mathbf{s}_1, \mathbf{u} \gets \chi_\eta$ (centred binomial) and $\mathbf{B}$ uniform.
|
||||
The two distributions are identical except in the $\mathbf{s}_2$ vs.\ $\mathbf{B}\mathbf{u}$ component. Under $\MLWE_{q, k, \ell, \eta}$ in $\mathbf{B}$, $\mathbf{B}\mathbf{u}$ is computationally indistinguishable from a uniform $\mathbf{w} \in \Rq^k$; conditioned on uniformity, the post-$\Power$ projection is uniform over the range of $\Power$. Single-party ML-DSA's $\mathbf{s}_2 \sim \chi_\eta^k$ also projects through $\Power$ to a distribution that is statistically close to uniform over the $\Power$ image. The total distance between the two $\mathit{pk}$ distributions is therefore bounded by $\Adv^{\MLWE}_{q, k, \ell, \eta}(\mathcal{B}_{\MLWE})$ plus a negligible statistical term from the $\Power$ rounding.
|
||||
|
||||
\textbf{$\sigma$ indistinguishability.}
|
||||
By correctness (\Cref{thm:sign-correct}), the Pulsar-M aggregated
|
||||
$\sigma$ is the FIPS~204 signature on $(\mathit{pk}, \mu, \mathbf{y})$ where $\mathbf{y} = \sum_j \mathbf{y}_j$ is the aggregated mask. The marginal distribution of $\mathbf{y}$ (sum of $t$ uniform-interval samples) is a discrete convolution; FIPS~204's single-party mask is a single uniform-interval sample. The two distributions differ in their concentration profile but are projected through the rejection-sampling acceptance condition $\|\mathbf{z}\|_\infty < \gamma_1 - \beta$, which forces the accepted distribution into the same FIPS~204 acceptance region. Conditioned on acceptance, the per-coordinate distribution of $\mathbf{z}$ is uniform on $[-\gamma_1 + \beta + 1, \gamma_1 - \beta - 1]$ in both cases (this is the FIPS~204 rejection-sampling invariant). Therefore the post-rejection distribution is identical between Pulsar-M and FIPS~204, and the output $\sigma$ is distributionally identical given the same $\tilde c$ and $\mathbf{h}$.
|
||||
|
||||
The statistical term $1/2^{2\lambda}$ accounts for the negligible
|
||||
probability of a $\tilde c$ collision in the RO. \qed
|
||||
\end{proof}
|
||||
|
||||
\begin{remark}[Caveat on signature byte equality]
|
||||
\Cref{thm:outind} states distributional equivalence. For \emph{byte
|
||||
equality} on a specific signature, the Pulsar-M $\Sign$
|
||||
implementation MUST emit exactly the FIPS~204 byte encoding of
|
||||
$(\tilde c, \mathbf{z}, \mathbf{h})$ with the same canonicalisation
|
||||
(coefficient lifting, sign convention, packing). This is an
|
||||
implementation-level requirement, not a cryptographic theorem; the
|
||||
encoding section (\S\ref{sec:encodings}) pins it. The byte-equality
|
||||
property is what unlocks Class~N1.
|
||||
\end{remark}
|
||||
|
||||
% =====================================================================
|
||||
\subsection{Game ROB (robustness / identifiable abort)}
|
||||
\label{sec:game-rob}
|
||||
% =====================================================================
|
||||
|
||||
\begin{game}[ROB]
|
||||
\label{game:rob}
|
||||
$\mathcal{A}$ corrupts up to $t-1$ parties and chooses one of the
|
||||
following deviation strategies:
|
||||
\begin{enumerate}[label=(\alph*), leftmargin=*, itemsep=0pt]
|
||||
\item Send distinct DKG commit vectors to distinct recipients (equivocation).
|
||||
\item Send a private DKG share that fails Pedersen verification.
|
||||
\item Send a Round-1 sign commit with an invalid MAC.
|
||||
\item Send a Round-2 sign response that, combined with honest contributions, would push the aggregate $\mathbf{z}$ outside the FIPS~204 norm.
|
||||
\item Refuse to participate at any round boundary.
|
||||
\end{enumerate}
|
||||
$\mathcal{A}$ wins if any honest party either (i) completes the
|
||||
protocol against the deviation \emph{without} producing a valid
|
||||
complaint identifying a corrupted deviator, or (ii) the honest
|
||||
party's resulting state is inconsistent with at least one other
|
||||
honest party's state (no recovery).
|
||||
\end{game}
|
||||
|
||||
\begin{theorem}[Robustness]
|
||||
\label{thm:rob}
|
||||
For every $\PPT$ adversary $\mathcal{A}$ against \Cref{game:rob}, the
|
||||
honest parties either produce a valid \textsc{Complaint}
|
||||
record identifying a corrupted deviator, or successfully complete
|
||||
the protocol. Formally,
|
||||
$\Adv^{\mathsf{ROB}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A})$ is
|
||||
bounded by the signature-forgery advantage on the parties' long-term
|
||||
identity-key scheme (e.g.\ Ed25519) plus
|
||||
$\Adv^{\MSIS}_{q, k, 2\ell, \beta_{\mathrm{bind}}}(\mathcal{B}_{\MSIS})$ for
|
||||
deviation~(a),
|
||||
plus the random-oracle collision term $q_H / 2^{256}$ for the
|
||||
commit-digest binding.
|
||||
\end{theorem}
|
||||
|
||||
\begin{proof}[Sketch]
|
||||
For deviation (a), the Round-1.5 commit digest broadcast by every
|
||||
honest recipient binds each sender to one commit vector across the
|
||||
cohort (under collision-resistance of $\cSHAKE$). Two distinct
|
||||
commits would produce two distinct digests, observable to every
|
||||
recipient as a digest mismatch; the recipient signs a
|
||||
\textsc{ComplaintEquivocation} carrying the two signed broadcasts as
|
||||
evidence. The signature soundness of the accused party's long-term
|
||||
identity key prevents the accused from repudiating its own
|
||||
broadcasts; forging two broadcasts requires breaking the identity
|
||||
signature.
|
||||
|
||||
For deviation (b), the Pedersen identity check
|
||||
(\Cref{thm:pedersen-binding}) fails with probability $1 - \negl$ if
|
||||
$\mathcal{A}$ deviates from a valid (share, blind, commit) triple.
|
||||
The failing recipient signs a \textsc{ComplaintBadDelivery}
|
||||
carrying the triple as evidence; the complaint is verifiable by any
|
||||
third party because the public Pedersen check is determined by
|
||||
$(\mathbf{A}, \mathbf{B})$.
|
||||
|
||||
For deviations (c), (d), (e): MAC verification, Round-2 norm
|
||||
verification (against the public broadcast of $\bar{\mathbf{w}}_i,
|
||||
\mathbf{z}_i, \mathbf{r}_i$), and round-window timeouts respectively
|
||||
produce \textsc{ComplaintMACFailure}, \textsc{ComplaintRangeFailure},
|
||||
\textsc{ComplaintTimeout} records, signed by the detecting party. Each
|
||||
complaint is publicly verifiable from the transcript and the
|
||||
accuser's identity-key signature. \qed
|
||||
\end{proof}
|
||||
|
||||
% =====================================================================
|
||||
\subsection{Game ADAPT (adaptive corruption)}
|
||||
\label{sec:game-adapt}
|
||||
% =====================================================================
|
||||
|
||||
\begin{game}[ADAPT]
|
||||
\label{game:adapt}
|
||||
Identical to \Cref{game:tsuf} except $\mathcal{A}$ may issue
|
||||
\emph{adaptive} corruption queries: at any point during the protocol
|
||||
execution, $\mathcal{A}$ chooses a previously-honest party $i$ to
|
||||
corrupt; the challenger reveals party $i$'s entire current state
|
||||
including secret share, current per-round randomness, and PRNG
|
||||
seeds. The total number of corrupted parties at any time is bounded
|
||||
by $t-1$.
|
||||
\end{game}
|
||||
|
||||
\begin{theorem}[Adaptive corruption --- sketch only]
|
||||
\label{thm:adapt-sketch}
|
||||
\emph{Statement deferred to round-2 MPTC.} A formal
|
||||
adaptive-corruption proof requires either (i) a complexity-leveraging
|
||||
argument that loses a $\binom{n}{t-1}$ factor in the security
|
||||
parameter and is therefore loose for practical $(n, t)$, or (ii) a
|
||||
trapdoor-based simulation argument compatible with the Pedersen
|
||||
commit structure. \cite{corona2024} sketches direction (i) for the
|
||||
Ring-LWE setting; the module-shaped adaptation is structural but
|
||||
non-trivial.
|
||||
\end{theorem}
|
||||
|
||||
\begin{openq}[Adaptive corruption]
|
||||
Tight adaptive corruption for module-shaped two-round
|
||||
threshold lattice signatures is an open research question. Pulsar-M
|
||||
defers a formal proof to round 2; under the static-corruption model
|
||||
\Cref{thm:tsuf} suffices for round 1.
|
||||
\end{openq}
|
||||
|
||||
% =====================================================================
|
||||
\subsection{Game MOB (mobile-adversary security, proactive resharing)}
|
||||
\label{sec:game-mob}
|
||||
% =====================================================================
|
||||
|
||||
\begin{game}[MOB]
|
||||
\label{game:mob}
|
||||
Multi-epoch experiment with epoch counter $e \in \{1, 2, \dots, E\}$.
|
||||
At each epoch $e$:
|
||||
\begin{enumerate}[leftmargin=*, itemsep=0pt]
|
||||
\item $\mathcal{A}$ chooses a corruption set $\mathcal{C}_e \subseteq \{1, \dots, n\}$ with $|\mathcal{C}_e| \le t-1$. Corruptions are independent across epochs: a party in $\mathcal{C}_e \cap \mathcal{C}_{e+1}$ is corrupted across both epochs, but a party in $\mathcal{C}_e \setminus \mathcal{C}_{e+1}$ \emph{uncorrupts} between epochs (forgets its epoch-$e$ secrets but retains its identity-key state).
|
||||
\item The challenger reveals the epoch-$e$ shares and per-round randomness of every party in $\mathcal{C}_e$.
|
||||
\item $\mathcal{A}$ may issue $\mathcal{O}_{\Sign}$ queries within the epoch.
|
||||
\item At the epoch boundary, the challenger runs $\Reshare$ honestly with a fresh beacon $\beta_{e+1}$. The beacon is unbiasable: $\mathcal{A}$ sees $\beta_{e+1}$ \emph{after} committing to $\mathcal{C}_{e+1}$.
|
||||
\end{enumerate}
|
||||
At the end of epoch $E$, $\mathcal{A}$ outputs a forgery
|
||||
$(\mu^*, \sigma^*)$. $\mathcal{A}$ wins under the TS-UF winning
|
||||
condition.
|
||||
\end{game}
|
||||
|
||||
\begin{theorem}[Mobile-adversary security]
|
||||
\label{thm:mob}
|
||||
For every $\PPT$ adversary $\mathcal{A}$ against \Cref{game:mob} over
|
||||
$E$ epochs,
|
||||
\[
|
||||
\Adv^{\mathsf{MOB}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A})
|
||||
\;\le\;
|
||||
E \cdot \Adv^{\mathsf{TS\textsf{-}UF}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{B})
|
||||
+ E \cdot \Adv^{\mathsf{beacon\textsf{-}unbias}}_{\mathrm{chain}}(\mathcal{B}_{\mathrm{beacon}}) +
|
||||
E \cdot \Adv^{\MLWE}_{q, k, \ell, \eta}(\mathcal{B}_{\MLWE}).
|
||||
\]
|
||||
\end{theorem}
|
||||
|
||||
\begin{proof}[Proof sketch]
|
||||
The proof proceeds by induction on epochs. The base case $e = 1$ is
|
||||
TS-UF directly. For the inductive step, assume the master secret
|
||||
$\mathbf{s}_1$ is hidden from $\mathcal{A}$ through epoch $e$. At the
|
||||
epoch boundary:
|
||||
\begin{enumerate}[leftmargin=*, itemsep=0pt]
|
||||
\item The reshare quorum $\mathcal{Q}_{e+1}$ is selected from the
|
||||
beacon $\beta_{e+1}$. Under the beacon-unbiasability assumption, the
|
||||
event \(\mathcal{Q}_{e+1} \cap \mathcal{C}_{e+1}\) is a uniform random
|
||||
sample from the size-$(t_{\mathrm{old}})$ subsets of $\mathcal{O}$;
|
||||
the probability that $\mathcal{A}$'s
|
||||
$|\mathcal{C}_{e+1}| \le t-1$ corruption covers $\mathcal{Q}_{e+1}$ entirely
|
||||
is at most
|
||||
$\binom{t-1}{t}\binom{n}{t}^{-1} = 0$ (corruption budget is strictly less than $t$).
|
||||
\item By \Cref{thm:reshare-pkinv}, $\mathit{pk}$ is invariant.
|
||||
\item By the resharing privacy theorem
|
||||
(\Cref{thm:reshare-priv} below), the joint view of $\mathcal{A}$
|
||||
across $(\mathcal{C}_e, \mathcal{C}_{e+1})$ is independent of the
|
||||
master secret $\mathbf{s}_1$.
|
||||
\item Forgery in epoch $e+1$ reduces to TS-UF in epoch $e+1$ against
|
||||
the (independently distributed) new committee shares.
|
||||
\end{enumerate}
|
||||
The union bound over $E$ epochs gives the stated advantage. \qed
|
||||
\end{proof}
|
||||
|
||||
% =====================================================================
|
||||
\subsection{Games DKG-SOUND and DKG-PRIV}
|
||||
\label{sec:game-dkg}
|
||||
% =====================================================================
|
||||
|
||||
\begin{game}[DKG-SOUND]
|
||||
\label{game:dkg-sound}
|
||||
$\mathcal{A}$ corrupts up to $t-1$ parties at DKG start. The
|
||||
challenger runs $\DKG$ honestly across the remaining parties;
|
||||
$\mathcal{A}$'s corrupted parties act under its control.
|
||||
$\mathcal{A}$ wins if the output $\mathit{pk}$ is \emph{not} a valid
|
||||
FIPS~204 public key (i.e., it does not deserialise correctly, or it
|
||||
does not satisfy the FIPS~204 public-key range checks).
|
||||
\end{game}
|
||||
|
||||
\begin{theorem}[DKG soundness]
|
||||
\label{thm:dkg-sound}
|
||||
For every $\PPT$ adversary,
|
||||
$\Adv^{\mathsf{DKG\textsf{-}SOUND}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A}) \le \Adv^{\MSIS}_{q, k, 2\ell, \beta_{\mathrm{bind}}}(\mathcal{B}_{\MSIS}) + q_H / 2^{256}$.
|
||||
\end{theorem}
|
||||
|
||||
\begin{proof}[Sketch]
|
||||
Honest parties verify Pedersen identities at Round~2. A corrupted
|
||||
party that contributes a malformed share triggers
|
||||
\textsc{ComplaintBadDelivery}, removing its contribution from the
|
||||
aggregation. The remaining honest contributions are
|
||||
$\chi_\eta$-distributed, so $\mathbf{s}_1 = \sum_{i \in \mathcal{H}}
|
||||
\mathbf{c}_{i,0}$ has a distribution that is statistically close to
|
||||
$\chi_\eta^\ell$ scaled by $|\mathcal{H}|$ (which we re-randomise to
|
||||
$\chi_\eta^\ell$ via the FIPS~204 secret-key sampling discipline).
|
||||
The Pedersen binding bound prevents the adversary from substituting a
|
||||
different $\mathbf{c}_{i,0}$ between commit and reveal. The remaining
|
||||
RO term is the random-oracle collision bound for the commit-digest
|
||||
binding. \qed
|
||||
\end{proof}
|
||||
|
||||
\begin{game}[DKG-PRIV]
|
||||
\label{game:dkg-priv}
|
||||
$\mathcal{A}$ corrupts up to $t-1$ parties and runs $\DKG$ honestly;
|
||||
the challenger flips a bit $b$. If $b = 0$, $\mathcal{A}$ sees the
|
||||
real DKG transcript including the corrupted parties' shares. If
|
||||
$b = 1$, the challenger simulates the corrupted parties' shares from
|
||||
the public $\mathit{pk}$ using a $\Sigma$-protocol-style simulator
|
||||
that re-randomises the commits without knowledge of the honest
|
||||
secrets. $\mathcal{A}$ outputs a guess $\hat b$.
|
||||
\end{game}
|
||||
|
||||
\begin{theorem}[DKG share privacy]
|
||||
\label{thm:dkg-priv}
|
||||
$\Adv^{\mathsf{DKG\textsf{-}PRIV}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A}) \le \Adv^{\MLWE}_{q, k, \ell, \eta}(\mathcal{B})$.
|
||||
\end{theorem}
|
||||
|
||||
\begin{proof}[Sketch]
|
||||
The Pedersen commitments are computationally hiding
|
||||
(\Cref{thm:pedersen-hiding}). The simulator chooses corrupted-party
|
||||
shares uniformly from the simulation distribution induced by
|
||||
$\mathit{pk}$, then programs the commits via the Pedersen-hiding
|
||||
simulator. Distinguishing real from simulated commits reduces to
|
||||
$\MLWE$. \qed
|
||||
\end{proof}
|
||||
|
||||
% =====================================================================
|
||||
\subsection{Games RESHARE-SOUND and RESHARE-PRIV}
|
||||
\label{sec:game-reshare}
|
||||
% =====================================================================
|
||||
|
||||
\begin{game}[RESHARE-SOUND]
|
||||
\label{game:reshare-sound}
|
||||
$\mathcal{A}$ has corrupted up to $t-1$ parties of the old
|
||||
committee and up to $t-1$ of the new committee. The challenger runs
|
||||
$\Reshare$ with an honest beacon. $\mathcal{A}$ wins if the new
|
||||
committee's resulting shares do \emph{not} reconstruct to
|
||||
$\mathbf{s}_1$ via Lagrange interpolation at $X = 0$.
|
||||
\end{game}
|
||||
|
||||
\begin{theorem}[Reshare soundness]
|
||||
\label{thm:reshare-sound}
|
||||
$\Adv^{\mathsf{RESHARE\textsf{-}SOUND}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A}) \le \Adv^{\MSIS}_{q, k, 2\ell, \beta_{\mathrm{bind}}}(\mathcal{B})$.
|
||||
\end{theorem}
|
||||
|
||||
\begin{proof}[Sketch]
|
||||
The reshare polynomials $g_i, h_i$ commit to constant terms
|
||||
$\lambda_i^{\mathcal{Q}_e} \mathbf{s}_i, \lambda_i^{\mathcal{Q}_e} \mathbf{u}_i$
|
||||
under Pedersen commit. Pedersen binding prevents a deviating
|
||||
$i \in \mathcal{Q}_e \cap \mathcal{C}$ from substituting a different
|
||||
constant term. The remaining honest parties' constant terms sum
|
||||
under Lagrange interpolation to $\mathbf{s}_1$ exactly
|
||||
(\Cref{thm:reshare-pkinv}). Therefore the master secret is preserved
|
||||
modulo binding. \qed
|
||||
\end{proof}
|
||||
|
||||
\begin{game}[RESHARE-PRIV]
|
||||
\label{game:reshare-priv}
|
||||
$\mathcal{A}$ corrupts up to $t-1$ parties of $\mathcal{O}$ and up to
|
||||
$t-1$ of $\mathcal{N}$ (allowing distinct corruption sets per epoch,
|
||||
matching the mobile adversary model). The challenger runs $\Reshare$
|
||||
honestly with an honest beacon. $\mathcal{A}$ outputs a guess for
|
||||
$\mathbf{s}_1$. Advantage = probability of correct guess.
|
||||
\end{game}
|
||||
|
||||
\begin{theorem}[Reshare share privacy]
|
||||
\label{thm:reshare-priv}
|
||||
For an unbiased beacon $\beta_e$,
|
||||
$\Adv^{\mathsf{RESHARE\textsf{-}PRIV}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A}) \le \Adv^{\MLWE}_{q, k, \ell, \eta}(\mathcal{B}) + \Adv^{\mathsf{beacon\textsf{-}unbias}}_{\mathrm{chain}}(\mathcal{B}_{\mathrm{beacon}}) + q^{-1}$.
|
||||
\end{theorem}
|
||||
|
||||
\begin{proof}[Sketch]
|
||||
The old committee's leaked shares $\{\mathbf{s}_i\}_{i \in
|
||||
\mathcal{C}_{\mathrm{old}}}$ alone leak no information about
|
||||
$\mathbf{s}_1$ by Shamir security. The new shares
|
||||
$\{\mathbf{s}'_j\}_{j \in \mathcal{C}_{\mathrm{new}}}$ similarly leak
|
||||
nothing on their own. The cross-leakage from the dealing step
|
||||
contributes $\{g_i(j) : i \in \mathcal{Q}_e, j \in
|
||||
\mathcal{C}_{\mathrm{new}}\}$. Conditioned on $\mathbf{s}_i$ (which
|
||||
$\mathcal{A}$ already knows if $i \in \mathcal{C}_{\mathrm{old}}$,
|
||||
otherwise hidden), the distribution of $g_i(j)$ for $|\{j\}| < t_{\mathrm{new}}$ is uniform in $\Rq^\ell$ by the high-degree
|
||||
random coefficients of $g_i$; therefore the dealing-step view admits
|
||||
a simulator that draws the leaked $g_i(j)$ values uniformly without
|
||||
knowing $\mathbf{s}_1$.
|
||||
|
||||
The beacon-unbiasability assumption ensures
|
||||
$\mathcal{Q}_e \cap \mathcal{C}_{\mathrm{old}}$ is a fresh uniform
|
||||
sample with respect to $\mathbf{s}_1$, preventing adversarial gaming
|
||||
of the quorum.
|
||||
|
||||
The $q^{-1}$ term is the negligible probability that a Lagrange
|
||||
denominator collides in the beacon-induced ordering. \qed
|
||||
\end{proof}
|
||||
|
||||
% =====================================================================
|
||||
\subsection{Game RESTART-NL (rejection-restart non-leakage)}
|
||||
\label{sec:game-restart-nl}
|
||||
% =====================================================================
|
||||
|
||||
We re-state \Cref{thm:restart-non-leak} from the main text as an
|
||||
explicit game for completeness and so the reduction to $\KMAC$'s
|
||||
PRF security is recorded alongside the other games.
|
||||
|
||||
\begin{game}[RESTART-NL]
|
||||
\label{game:restart-nl}
|
||||
$\mathcal{A}$ corrupts up to $t-1$ parties of a fixed quorum $T$.
|
||||
The challenger runs $\Sign$ on a fixed honest target $(\mathit{pk}, \mu, T)$.
|
||||
$\mathcal{A}$ requests $K$ distinct rejection-restart attempts
|
||||
(distinct $\kappa = 1, \dots, K$); the challenger executes each
|
||||
attempt and reveals the full per-attempt transcript. $\mathcal{A}$
|
||||
outputs a guess for $\mathbf{s}_i$ for some honest party $i \in T
|
||||
\setminus \mathcal{C}$.
|
||||
\end{game}
|
||||
|
||||
\begin{theorem}[Restart non-leakage]
|
||||
\label{thm:restart-nl-game}
|
||||
For every $\PPT$ adversary against \Cref{game:restart-nl},
|
||||
\[
|
||||
\Adv^{\mathsf{RESTART\textsf{-}NL}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A})
|
||||
\;\le\;
|
||||
K \cdot \Adv^{\mathsf{PRF}}_{\KMAC}(\mathcal{B})
|
||||
+ \Adv^{\mathsf{TS\textsf{-}UF}}_{\mathrm{Pulsar\text{-}M}}(\mathcal{A}').
|
||||
\]
|
||||
\end{theorem}
|
||||
|
||||
The proof is the hybrid argument of the main-text
|
||||
\Cref{thm:restart-non-leak} restated formally. The cross-message
|
||||
extension --- replacing the fixed $\mu$ with adversarially-chosen
|
||||
$\mu^{(\kappa)}$ between restarts --- is recorded as open in
|
||||
\S\ref{sec:knownlimits}.
|
||||
|
||||
% =====================================================================
|
||||
\subsection{Summary of reductions}
|
||||
\label{sec:sec-summary}
|
||||
% =====================================================================
|
||||
|
||||
\begin{center}
|
||||
\begin{tabular}{l l}
|
||||
\toprule
|
||||
game & reduction target \\
|
||||
\midrule
|
||||
TS-UF (static unforgeability) & $\MLWE_{q,k,\ell,\eta}$ + $\MSIS_{q,k,2\ell,\beta_{\mathrm{bind}}}$ + EUF-CMA(ML-DSA) \\
|
||||
OUT-IND (FIPS~204 interchangeability) & $\MLWE_{q,k,\ell,\eta}$ \\
|
||||
ROB (identifiable abort) & Pedersen binding ($\MSIS$) + Ed25519 signature soundness \\
|
||||
ADAPT (adaptive corruption) & open --- deferred to round-2 \\
|
||||
MOB (mobile-adversary) & TS-UF + RESHARE-PRIV + beacon unbiasability \\
|
||||
DKG-SOUND & $\MSIS$ + RO collision \\
|
||||
DKG-PRIV & $\MLWE$ \\
|
||||
RESHARE-SOUND & $\MSIS$ \\
|
||||
RESHARE-PRIV & $\MLWE$ + beacon unbiasability \\
|
||||
RESTART-NL (rejection-restart) & PRF($\KMAC$) + TS-UF \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
The dominant terms across all games are $\MLWE_{q, k, \ell, \eta}$
|
||||
and ML-DSA EUF-CMA, both of which take the FIPS~204
|
||||
parameter-pinned values (see \S\ref{sec:parameters}). Pulsar-M
|
||||
inherits ML-DSA's security level modulo the threshold-protocol
|
||||
overhead, which is dominated by the Pedersen-binding $\MSIS$ term
|
||||
and the random-oracle programming penalty.
|
||||
|
||||
\paragraph{Forward-security note.}
|
||||
The MOB game (\Cref{game:mob}) implies forward security at the epoch
|
||||
granularity: revealing all shares at epoch $e$ leaks no information
|
||||
about $\mathbf{s}_1$ in epoch $e' > e$ provided fewer than $t-1$
|
||||
parties have leaked their epoch-$e'$ shares. Combined with $\Reshare$
|
||||
at the epoch boundary, this gives the standard
|
||||
proactive-secret-sharing forward-security guarantee.
|
||||
@@ -0,0 +1,46 @@
|
||||
% Pulsar-M system model — included by pulsar-m.tex §"System model"
|
||||
|
||||
\section*{System model}
|
||||
|
||||
% TODO. Cover:
|
||||
%
|
||||
% Network model
|
||||
% - synchronous vs asynchronous (Pulsar-M assumes synchronous broadcast
|
||||
% within the round window; partially-synchronous is future work)
|
||||
% - broadcast channel: authenticated, eventual delivery
|
||||
% - point-to-point channel: authenticated, encrypted
|
||||
% - public bulletin: authenticated, append-only (consensus-anchored)
|
||||
%
|
||||
% Setup assumptions
|
||||
% - PKI: each party has a long-term verification key advertised on the
|
||||
% public bulletin (e.g. lux/consensus identity record per HIP-0077)
|
||||
% - Random beacon: shared randomness oracle for reshare quorum selection
|
||||
% (lux consensus randomness layer)
|
||||
%
|
||||
% Trust model
|
||||
% - Up to t-1 corrupted parties (static), t-1 per epoch (mobile)
|
||||
% - Honest majority of (n - t + 1) needed for liveness
|
||||
%
|
||||
% Abort model
|
||||
% - Identifiable abort: protocol surfaces a signed complaint when a
|
||||
% deviation is detected, with the deviating party ID
|
||||
% - Slashing: governance layer consumes complaints (out of scope here)
|
||||
%
|
||||
% Preprocessing
|
||||
% - DKG runs once per validator-set epoch
|
||||
% - Reshare runs at epoch boundary (typical cadence: hours to days)
|
||||
% - Sign runs per-message; preprocessing-free if combined with non-cached
|
||||
% sampler, or with optional Round-0 mask precomputation per Pulsar's
|
||||
% offline/online split
|
||||
%
|
||||
% Rotation
|
||||
% - Reshare protocol updates shares without changing pk (per HJKY97)
|
||||
% - Members may join / leave between epochs subject to (n', t') constraint
|
||||
%
|
||||
% Monitoring
|
||||
% - Public artifacts: pk, commitments, signed complaints, signature outputs
|
||||
% - Private artifacts: shares, blinds, masks, samples — never logged
|
||||
%
|
||||
% Deployment surface
|
||||
% - Reference assumes pure software
|
||||
% - HSM integration is future work (out of scope for round 1 MPTC)
|
||||
@@ -0,0 +1,46 @@
|
||||
# Test vectors
|
||||
|
||||
Two formats per NIST MPTC submission norms:
|
||||
|
||||
- `kat-v1.json` — input/output vectors per MPTC §IO-Testing. Each entry
|
||||
is a single threshold ceremony with full `(n, t, party_seeds,
|
||||
public_params, shares, commitments, preprocessing_transcript, message,
|
||||
per_party_messages, final_signature, verify_result, abort_evidence)`.
|
||||
|
||||
- `kat-v1.rsp` — CAVS-style response file for compatibility with
|
||||
legacy ACVP-inspired tooling. One signature per stanza, deterministic
|
||||
from a 48-byte seed.
|
||||
|
||||
`transcripts/` holds full-protocol KATs for `(n, t)` sweeps —
|
||||
`transcripts/n3-t2.jsonl`, `transcripts/n7-t5.jsonl`, etc. — each line
|
||||
a complete protocol run.
|
||||
|
||||
## Cross-validation against FIPS 204
|
||||
|
||||
The headline interchangeability claim (Class N1) requires every
|
||||
`final_signature` in `kat-v1.json` to verify against unmodified FIPS 204
|
||||
`ML-DSA.Verify(pk, message, signature)` returning `accept`. The
|
||||
cross-validation harness at `test/interoperability/` runs each KAT
|
||||
through:
|
||||
|
||||
- the reference implementation in `ref/go/`
|
||||
- the FIPS 204 reference (Dilithium pq-crystals C reference)
|
||||
- a third independent ML-DSA implementation (BoringSSL FIPS or
|
||||
OpenSSL 3.0 PQ provider, whichever is available)
|
||||
|
||||
A KAT mismatch with any of the three is a release blocker.
|
||||
|
||||
## Determinism
|
||||
|
||||
Every entry in `kat-v1.json` is reproducible from `master_seed` (a
|
||||
48-byte hex value at the head of the file). `scripts/gen_vectors.sh`
|
||||
must produce byte-identical output on any fresh checkout. Drift here
|
||||
is a CI failure.
|
||||
|
||||
## Status
|
||||
|
||||
- [ ] KAT generator (`ref/go/cmd/genkat`) — implementation pending
|
||||
- [ ] First v1 KAT set
|
||||
- [ ] FIPS 204 cross-validation
|
||||
- [ ] Independent-impl cross-validation
|
||||
- [ ] Encoded into `vectors/transcripts/` for `(n, t) ∈ {(3,2), (5,3), (7,5), (10,7), (16,11), (32,21)}`
|
||||
Reference in New Issue
Block a user