v0.2.0 reaches Tier B: production library + submission scaffold landed (v0.1 reveal-and-aggregate construction shipped in ref/go/pkg/magnetar/ with KAT vectors). Mechanized refinement + independent audit remain on the roadmap to Tier A. Changes: - README.md: flip status to Tier B. Document the v0.1 reveal-and- aggregate construction, the Class-N1-analog byte-equality claim, and the v0.1 trust caveat. List what v0.2.0 ships and what does NOT ship (formal proofs, ct analysis, KEM-wrapped envelopes, independent review, full 16-doc submission package). - SUBMISSION-STATUS.md: flip to Tier B. Phase 1 (construction selection) + Phase 2 (reference implementation) marked DONE. Phase 3 (proof artifacts, BLK-7), Phase 4 (16-doc submission package, BLK-8), Phase 5 (independent review, BLK-9) remain open. NIST MPTC v0.3 target window held (2027 Q3 internal). - BLOCKERS.md: BLK-1 (construction selection), BLK-2 (academic basis), BLK-3 (spec definition) marked CLOSED with the reveal-and-aggregate selection documented and the citation gap honestly acknowledged. BLK-4 (ref impl) marked PARTIAL — v0.1 shipped, missing pieces (KEM-wrapped envelopes, reshare, MACs, large-committee path) called out. BLK-5 (KAT vectors) CLOSED. BLK-6/7/8/9 (interop, proofs, package, review) remain OPEN with updated status. - SPEC.md (NEW): construction specification for v0.1 reveal-and- aggregate. Covers notation, hash domain separation, DKG protocol (Round 1/2/3), threshold signing (Round 1/2/Combine), Class-N1- analog byte-equality claim with proof sketch, trust model disclosure, identifiable abort taxonomy, parameter sets, honest non-claims. - DEPLOYMENT-RUNBOOK.md (NEW): operator-facing trust-model disclosure mirroring Pulsar's runbook. The v0.1 reveal-and- aggregate aggregator-as-TCB caveat is identical to Pulsar's; same hardening matrix (TEE / mlock / ptrace-off / short-lived aggregator process). Lists what the caveat does NOT cover (Byzantine committee members, Byzantine aggregator forging unsigned messages, passive network observers). Honest non-warranties section: no independent review, no formal proofs, no production Lux deployment yet. DESIGN.md left untouched — it represents the original research- direction sketch and is preserved as a historical record.
12 KiB
Magnetar v0.1 — Construction specification
Threshold FIPS 205 SLH-DSA via reveal-and-aggregate. Mirrors Pulsar's v0.1 reveal-and-aggregate pattern, ported to SLH-DSA's scheme-seed-as-secret model.
Status: v0.1 implementation specification. NOT yet independently reviewed. See
BLOCKERS.mdBLK-7 and BLK-9 for the proof-and-review path to Tier A.
1. Notation
| Symbol | Meaning |
|---|---|
n |
committee size |
t |
reconstruction threshold (1 ≤ t ≤ n ≤ 256) |
q |
Shamir prime, fixed at 257 (smallest prime > 255) |
seed_size |
SLH-DSA scheme-seed length: 96 bytes for SHAKE-192s/192f, 128 bytes for SHAKE-256s |
P_i |
party i, 1 ≤ i ≤ n |
x_i |
Shamir x-coordinate of P_i, 1 ≤ x_i ≤ 256, distinct per party |
c_i |
P_i's contribution to the joint seed, c_i ∈ {0,1}^{8·seed_size} |
S |
joint master seed, S ∈ {0,1}^{8·seed_size} |
share_i |
P_i's Shamir share of the byte-sum used to mix to S |
pk, sk |
FIPS 205 SLH-DSA group public / private keypair derived from S |
2. Hash domain separation
All cSHAKE / KMAC calls use function-name "Magnetar" and one of
the following customisation tags:
| Tag | Purpose |
|---|---|
MAGNETAR-DKG-COMMIT-V1 |
committee-root digest |
MAGNETAR-DKG-TRANSCRIPT-V1 |
DKG transcript digest |
MAGNETAR-SIGN-R1-V1 |
threshold-sign Round-1 commit D_i |
MAGNETAR-SIGN-R1-MAC-V1 |
(reserved for v0.2 MAC envelope) |
MAGNETAR-SIGN-MASK-V1 |
per-attempt mask derivation |
MAGNETAR-SEED-SHARE-V1 |
Shamir coefficient stream + seed mix |
The protocol-wide domain-separation context is the ASCII string
"lux-magnetar-v0.1" (tagDomainSep).
3. DKG protocol
Round 1 (dealer P_i)
- Sample
c_i ←$ {0,1}^{8·seed_size}fromrng. - Sample
seed_size · 2 · (t-1)bytes of coefficient material fromrng(the random Shamir polynomial coefficients). - Run byte-wise Shamir-share-deal over GF(257):
- For each byte position
b ∈ [0, seed_size), define a polynomialf_b(x) = c_i[b] + a_{b,1}·x + ... + a_{b,t-1}·x^{t-1} (mod 257)wherea_{b,j}are derived from the coefficient stream. - For each recipient
P_j, computeshare_{i→j}[b] = f_b(x_j) (mod 257)for every byteb. The result is a 2·seed_size-byte big-endian uint16 vector.
- For each byte position
- Construct one envelope per recipient:
The full
Envelope_{i→j} := (share_{i→j} || c_i)c_iis duplicated into every envelope so that at Round 2 eachP_jcan sum contributions to compute the joint master public key locally. - Broadcast
DKGRound1Msg{NodeID = P_i, Envelopes = { P_j ↦ Envelope_{i→j} }_{j∈[n]}}.
Round 2 (party P_i)
- Receive Round-1 broadcasts from every dealer in committee.
- Validate: every broadcast contains an envelope for every recipient (no omissions); every envelope has the expected wire sizes; sender is in committee.
- Compute the transcript digest binding the entire ordered envelope set:
τ_dkg := lux-magnetar-v0.1 ‖ Mode ‖ t ‖ n ‖ committee_in_order D := cSHAKE256( τ_dkg ‖ for_each_dealer_in_order(for_each_recipient_in_order(share || contribution)), N="Magnetar", S="MAGNETAR-DKG-TRANSCRIPT-V1", 32 bytes ) - Broadcast
DKGRound2Msg{NodeID = P_i, Digest = D}.
Round 3 (party P_i)
- Receive Round-2 digests from every party.
- Verify every received digest equals
D(computed locally). A mismatch is identifiable abort withComplaintKind = ComplaintEquivocation; the conflicting digest pair is the evidence blob. - Sum per-byte Shamir shares received from each dealer:
my_share_sum[b] := Σ_{j∈[n]} share_{j→i}[b] (mod 257) for b ∈ [0, seed_size) - Sum dealer contributions byte-by-byte over GF(257):
master_byteSum[b] := Σ_{j∈[n]} c_j[b] (mod 257) for b ∈ [0, seed_size) - Compute the committee root:
committee_root := cSHAKE256( "MAGNETAR-COMMITTEE-V1" ‖ sorted_committee, N="Magnetar", S="MAGNETAR-DKG-COMMIT-V1", 32 bytes ) - Mix to the master seed:
mix := (master_byteSum encoded as 2·seed_size big-endian uint16) ‖ committee_root S := cSHAKE256( mix, N="Magnetar", S="MAGNETAR-SEED-SHARE-V1", seed_size bytes ) - Derive the group public key via FIPS 205:
Discard
(pk, sk) := slhdsa.Scheme(SLH-DSA-SHAKE-{192s,192f,256s}).DeriveKey(S)sk; publishpkas the joint group public key. (Each party can compute the samepkbecause every party has identicalmaster_byteSumandcommittee_rootinputs.) - Output:
KeyShare{NodeID = P_i, EvalPoint = x_i = i, Share = my_share_sum, Pub = pk}.
DKG correctness
For any quorum Q ⊆ [n] with |Q| ≥ t:
Lagrange-interpolate({(x_i, my_share_sum_i) : i ∈ Q}) = master_byteSum
because my_share_sum_i = Σ_j share_{j→i} = Σ_j f_{j,b}(x_i) and the Lagrange interpolation at x=0 over GF(257) of the polynomial sums Σ_j f_{j,b} recovers Σ_j c_j[b] = master_byteSum[b].
Therefore any quorum's reconstructed seed S is identical to the one computed at Round 3.
4. Threshold signing
Round 1 (signer P_i, i ∈ T ⊆ [n], |T| = t)
- Sample
rngBytes ←$ {0,1}^{8·2·seed_size}fromrng. - Derive per-attempt mask:
maskMix := rngBytes ‖ session_id ‖ attempt(BE 4 bytes) ‖ NodeID r_i := cSHAKE256( maskMix, N="Magnetar", S="MAGNETAR-SIGN-MASK-V1", 2·seed_size bytes ) - Mask the share byte-by-byte XOR:
masked_i[b] := share_i[b] XOR r_i[b] for b ∈ [0, 2·seed_size) - Compute Round-1 transcript binding:
τ_1 := SP800-185-encode( session_id, attempt, quorum, NodeID, pk, message ) - Compute commit:
D_i := cSHAKE256( r_i ‖ masked_i ‖ τ_1, N="Magnetar", S="MAGNETAR-SIGN-R1-V1", 32 bytes ) - Broadcast
Round1Message{NodeID, SessionID, Attempt, Commit = D_i}.
Round 2 (signer P_i)
- Validate Round-1 broadcasts (consistent session/attempt).
- Reveal:
Round2Message{NodeID, SessionID, Attempt, PartialSig = r_i ‖ masked_i}
Combine (aggregator)
- For each Round-2 reveal
(r_i, masked_i): a. RecomputeD'_i = cSHAKE256(r_i ‖ masked_i ‖ τ_1_i, ...)and checkD'_i == Round1Message.Commit. Reject on mismatch. b. Recovershare_i = masked_i XOR r_i. - Collect
tdistinct shares. Pair each with itsKeyShare.EvalPointfrom the directory. - Run Lagrange interpolation over GF(257) at
x=0:wherereconstructed_byteSum[b] := Σ_{i∈Q} λ_i · share_i[b] (mod 257)λ_i = Π_{j≠i} (-x_j) / (x_i - x_j) (mod 257). - Compute committee_root from
allShares(same definition as Round 3 step 5). - Mix to recover the master seed (identical to DKG Round 3 step 6):
S := cSHAKE256( reconstructed_byteSum_BE ‖ committee_root, N="Magnetar", S="MAGNETAR-SEED-SHARE-V1", seed_size bytes ) - Derive the SLH-DSA secret key:
If
(pk_rec, sk_rec) := slhdsa.Scheme(...).DeriveKey(S)pk_rec ≠ groupPubkey: abort withErrPubkeyMismatch. - Sign:
(When
sig := slhdsa.SignDeterministic(sk_rec, message, ctx)randomized=true,SignRandomizedis used with the caller'srng.) - Zeroize
S, sk_rec, mix, reconstructed_byteSum. - Return
Signature{Mode, Bytes = sig}.
5. Verify
Verify is a thin dispatch to slhdsa.Verify(pk, NewMessage(message), sig, ctx). No Magnetar-specific envelope. This is the Class-N1-analog property: any unmodified FIPS 205 verifier accepts Magnetar signatures.
6. Class-N1-analog byte-equality claim
Claim (Magnetar reveal-and-aggregate byte-equality). For any honest threshold-sign session over committee [n] with threshold t, any quorum Q of size t, message m, context ctx, session_id sid, attempt κ:
Combine(...) = slhdsa.SignDeterministic(slhdsa.DeriveKey(S), NewMessage(m), ctx)
where S is the master seed computed at DKG Round 3.
Proof sketch. Combine reconstructs master_byteSum from Q's shares via Lagrange interpolation (correct by Shamir's secret sharing over GF(257) for any quorum of size ≥ t). It then computes committee_root from the same allShares set that fixed it at DKG time, and applies the identical cSHAKE256 mix → produces the identical S. Sign on DeriveKey(S) is byte-deterministic over (S, m, ctx). ∎
Empirical validation. See n1_byte_equality_test.go: TestN1_ByteEquality_ThresholdMatchesCentralized and TestN1_ByteEquality_DifferentQuorumsSameSignature exercise the claim across three configurations and across distinct quorums.
7. Trust model — the v0.1 reveal-and-aggregate caveat
The aggregator process is in the trusted computing base (TCB) for the brief window the master seed is reconstructed in memory.
This is the same trust caveat Pulsar's v0.1 reveal-and-aggregate carries; it is documented honestly in Pulsar's DEPLOYMENT-RUNBOOK.md and is inherited verbatim by Magnetar.
Specifically:
- At step 6 of
Combine(§4), the master SLH-DSA seedSis recomputed in aggregator memory. - At step 7, FIPS 205
SignDeterministicconsumesSto produce the signature. - At step 8, all secret-bearing buffers (
S, sk_rec, mix, reconstructed_byteSum) are explicitly zeroized.
During steps 6–7, an adversary with arbitrary code-execution on the aggregator host can extract S via:
/proc/<pid>/mem- a coredump
- a swap-file or hibernation image
ptrace- a malicious kernel/hypervisor
Operational mitigations are described in DEPLOYMENT-RUNBOOK.md "Aggregator hardening".
What this caveat does NOT cover:
- A passive network observer never sees
S. Round-1 commits and Round-2 reveals collectively carryshare_ivalues (masked + revealed), but reconstruction requires combiningtof them with the matchingEvalPointdirectory. v0.1 v1 envelopes are plaintext (a passive observer can see committee shares); v0.2 will wrap them under ML-KEM-768 to the recipient's long-term identity public key, matching Pulsar's BLOCKERS.md CR-8 pattern. - A single Byzantine committee member cannot forge a signature: forging requires reconstructing
S, which requirestshares. - A single Byzantine aggregator cannot forge a signature for a message it did not receive valid Round-2 reveals on: Combine's commit-bind check (step 1a) rejects tampered reveals.
8. Identifiable abort
The protocol commits to identifiable abort: every detected deviation produces verifiable evidence suitable for slashing.
| Complaint | Detected at | Evidence |
|---|---|---|
ComplaintEquivocation |
DKG Round 3 | Conflicting Digest from accused; honest party's local Digest |
ComplaintBadDelivery |
DKG Round 2 (envelope shape check) | Malformed envelope |
The v0.1 protocol omits the per-pair MAC layer that Pulsar uses (BLOCKERS.md CR-7). This is documented; v0.2 adds MACs once the trust model tightens.
9. Parameter sets
| Mode | NIST PQ Cat | Pub key | Priv key | Signature | Seed |
|---|---|---|---|---|---|
Magnetar-SHAKE-192s |
3 | 48 B | 96 B | 16,224 B | 96 B |
Magnetar-SHAKE-192f |
3 | 48 B | 96 B | 35,664 B | 96 B |
Magnetar-SHAKE-256s |
5 | 64 B | 128 B | 29,792 B | 128 B |
Recommended production target: Magnetar-SHAKE-192s (matches NIST Cat 3, smallest signature in its category).
10. Honest non-claims
Magnetar v0.1 does NOT claim:
- Full MPC threshold signing. v0.1 is reveal-and-aggregate; the aggregator process is TCB.
- Network-observer secrecy of envelopes in v0.1. Plaintext envelopes are visible to a passive observer; v0.2 closes this with ML-KEM-768 wrapping.
- Sub-second signing. SLH-DSA single-party signing on SHAKE-192s is ~10–50ms depending on hardware; race-detector runs are 5–10× slower.
- Formal verification. No EasyCrypt, Lean, or Jasmin artifacts ship in v0.1. See
BLOCKERS.mdBLK-7.
11. References
- FIPS 205: Stateless Hash-Based Digital Signature Standard (2024).
- Shamir, A. How to share a secret. Communications of the ACM, 1979.
- Pulsar v0.1
SPEC.md— reveal-and-aggregate pattern adapted from there. BLOCKERS.md— outstanding Tier B → A path.DEPLOYMENT-RUNBOOK.md— operator-facing trust-model disclosure.
Document metadata
- File:
SPEC.md - Version: v0.1
- Date: 2026-05-18
- Status: implementation specification; not yet independently reviewed (see BLK-9).