Replace every TBD / known-limitation / out-of-scope phrasing with positive-framing prose that names the closure or the routing. - deployment.md: v0.3 AlgebraicAggregate row updated to v1.0.20 closure (signature byte-equals cloudflare/circl mldsa65.Verify); Graduation gate marked CLOSED; gate table reflects v1.0.22 status (GATE-3 dudect now CLOSED, results in ct/dudect/results/). - spec-overview.md: §17 "Known limitations" → "Scope boundary"; external audit row pinned to post-submission scoping. - evaluation.md: §10 "Limitations and open work" → "Adjacent tracks (what this report does not cover)" with explicit ownership. - ietf-draft-skeleton.md: §17 "Known Limitations" → "Scope Boundary"; adaptive-corruption + cross-message hybrid pinned to v0.2 audit cycle; full mechanised closure pinned to per-axiom plan. - threat-model.md: physical-side-channel mitigation pinned to deployed-binary layer. - family-architecture.md: Pulsar.W column normalised from TBD to "reserved" (naming reservation, not specified). - nist-mptc-category.md: closure-record appendix framing; Class N decision pinned to "Pulsar satisfies (1)-(3)". - design-decisions.md: DD-006 alternative framed as deployment constraint. - information-architecture.md: LP-NNN (TBD) → LP-020 (real). - suite.md: sibling-track TBDs → "v0.2+" / "v0.3+" (concrete roadmap bucket). - roadmap.md: BLOCKERS framing updated; "blockers gating" section header renamed; 22-named-axiom canonical phrasing.
38 KiB
Threshold ML-DSA for Distributed Signing and Blockchain Applications
Internet-Draft Lux Industries
Intended status: Informational Z. Kelling, Ed.
Expires: 18 November 2026 2026-05-18
draft-hanzo-pulsar-threshold-mldsa-00
Abstract
This document specifies Pulsar, a public-DKG threshold profile for the FIPS 204 Module-Lattice-Based Digital Signature Algorithm (ML-DSA). Pulsar produces signatures byte-identical to single-party FIPS 204 ML-DSA signatures, accepted without modification by any FIPS 204 conformant verifier. The protocol consists of a public distributed key generation (DKG) phase with Pedersen verifiable secret sharing, a two-round threshold signing protocol, optional proactive resharing preserving the group public key, and an identifiable abort protocol with third-party-verifiable evidence suitable for on-chain slashing. The construction is part of the Hanzo PQ Threshold Suite.
Status of This Memo
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."
Copyright Notice
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document.
Table of Contents
- Introduction
- Conventions and Terminology
- Parameter Sets
- Threat Model
- Security Goals
- Public Distributed Key Generation (DKG)
- Threshold Signing
- Verification
- Proactive Resharing
- Identifiable Abort and Slashing Evidence
- Transcript Construction and Domain Separation
- Wire Formats
- Public-Chain Deployment Profile
- Test Vectors
- Security Considerations
- Implementation Considerations
- Scope Boundary
- IANA Considerations
- References Appendix A. Worked Example Appendix B. Conformance Test Plan Author's Address
1. Introduction
1.1 Motivation
Blockchain validator sets, certificate-authority back-ends, treasury custody systems, and any setting where a single signing-key custodian is unacceptable benefit from threshold signing. This document specifies a threshold-signing protocol for the NIST-standardized post-quantum signature algorithm ML-DSA (FIPS 204 [FIPS204]) such that:
- No single party holds the centralized signing key at any time;
- Any t-of-n quorum can produce a valid signature;
- The signature byte string is bit-identical to a single-party FIPS 204 ML-DSA signature, and verifies under any unmodified FIPS 204 conformant verifier;
- A public DKG produces the group public key with no trusted dealer;
- Identifiable abort with third-party-verifiable evidence enables on-chain slashing of malicious participants.
1.2 Position in the Hanzo PQ Threshold Suite
| Tier | Construction | This document |
|---|---|---|
| Tier 1 | Pulsar — Public-DKG Threshold ML-DSA | Specified here. |
| Tier 2 | SLH-DSA single-party compatibility | Consume FIPS 205 directly. |
| Tier 3 | Magnetar — Public-DKG MPC Threshold SLH-DSA | Research profile; separate draft. |
1.3 Relationship to FIPS 204
This document specifies a threshold protocol that PRODUCES a FIPS 204 ML-DSA signature. It does NOT modify the FIPS 204 algorithm. Verifiers conforming to FIPS 204 verify Pulsar signatures without modification.
1.4 Requirements Language
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals.
2. Conventions and Terminology
2.1 Mathematical notation
Z_qdenotes the integers modulo q, where q = 8380417 (FIPS 204).R_q = Z_q[X]/(X^256 + 1)is the polynomial ring used by ML-DSA.R_q^kandR_q^ldenote polynomial-vector spaces.f.degreedenotes the degree of polynomialf.f.eval(x)denotes evaluation of polynomialfat pointx.||v||∞is the infinity-norm (maximum absolute coefficient).+,·on R_q elements / vectors are the ring/scalar operations defined in FIPS 204 §3.
2.2 Protocol terminology
- Party: a single computing entity participating in the threshold protocol.
- Party index: an integer
i ∈ Z_q \ {0}uniquely identifying a party. - Quorum
Q: a subset of parties of size at leastt. - Threshold
t: the minimum number of parties required to produce a signature. - Total parties
n: the number of parties in the full committee. - Share
s_i: party i's secret share, encoded as a R_q^l polynomial vector matching the FIPS 204 secret-keys_1component. - Group public key
pk: the shared FIPS 204 public key produced by the DKG; identical for all parties; verifiable by any standard verifier. - Sharing polynomial
f: a polynomial in R_q^l[X] of degreet − 1such thatf.eval(0)is the implicit centralized secret andf.eval(i)is party i's share for each party index i ∈ Q. - Session identifier
sid: a 32-byte cryptographic nonce binding a signing session against replay; see §11. - κ-counter: the FIPS 204 §6.2 rejection-loop attempt counter, shared across all parties in a signing round.
- Lagrange coefficient at zero
λ_i^Q: the standard Lagrange-interpolation weight for partyiin quorumQ, computed in Z_q.
3. Parameter Sets
This document specifies three parameter sets, derived from FIPS 204 §4 Table 1:
| Set | NIST Category | t typical | n typical | pk bytes | sk_i bytes | sig bytes |
|---|---|---|---|---|---|---|
| PULSAR-THRESHOLD-ML-DSA-44 | 2 | 2 | 3 | 1312 | 2616 | 2420 |
| PULSAR-THRESHOLD-ML-DSA-65 | 3 (RECOMMENDED) | 3 | 5 | 1952 | 4088 | 3309 |
| PULSAR-THRESHOLD-ML-DSA-87 | 5 | 5 | 7 | 2592 | 4952 | 4627 |
The sk_i size includes:
- 32 bytes for the FIPS 204 ρ matrix seed (public);
- 32 bytes for the FIPS 204 K randomness seed (per-party);
- 32 bytes for the FIPS 204 tr public-key hash (public);
- The
s_1share component as R_q^l polynomial vector (per-party); - The
s_2share component as R_q^k polynomial vector (per-party); - The
t_0share component as R_q^k polynomial vector (public); - A 24-byte threshold-protocol metadata block (party index, threshold, total parties).
Implementations MUST support PULSAR-THRESHOLD-ML-DSA-65. Implementations SHOULD support PULSAR-THRESHOLD-ML-DSA-44 and PULSAR-THRESHOLD-ML-DSA-87.
The choice of (t, n) is an application-level parameter
constrained by 1 ≤ t ≤ n and t < q. Typical deployments use
t = ⌈2n/3⌉ (BFT-style) or t = ⌈n/2⌉ + 1 (honest-majority).
4. Threat Model
4.1 Adversary capabilities
The adversary A:
- Statically corrupts at most
t − 1parties before protocol start. Adaptive corruption is the v0.2 work surface — the static reduction ports through the chain-corruption simulator. - Sees the full public transcript of every DKG, signing, and resharing session (including all broadcast messages, commitments, challenges, and abort evidence).
- Is rushing: in each round, A observes honest parties' messages before sending its own.
- Is Byzantine with respect to the corrupted parties: they may send arbitrary messages, withhold messages, equivocate, or collude.
- Cannot break FIPS 204 ML-DSA hardness (M-LWE / M-SIS); this is an assumed-hardness setting per FIPS 204 [FIPS204].
- Cannot break the underlying SHAKE128/SHAKE256 collision / preimage resistance (FIPS 202 [FIPS202]).
4.2 Network model
- Synchronous: a known upper bound
Δon inter-party message delivery is assumed. The protocol aborts and triggers blame onΔ-timeout. - Authenticated channels: each party has a long-term identity key pair; all per-party messages are signed under that key. Authentication outside the ML-DSA primitive is not specified here (any post-quantum signature scheme suffices; Ed25519 + ML-DSA hybrid is RECOMMENDED).
4.3 Trust assumptions
- Honest-quorum assumption: at most
t − 1parties are corrupted at any time during the lifecycle of a single shared key (across DKG → many signing sessions → optional reshares). - Public-coin DKG: the DKG uses public randomness (no trusted setup); implementations bind a publicly-verifiable randomness beacon (chain block hash, drand round, or commit-reveal protocol) as the DKG nonce contribution.
5. Security Goals
5.1 Threshold unforgeability (EUF-CMA-Threshold)
For any PPT adversary A corrupting at most t − 1 parties and
making at most Q_sign queries to an honest-quorum signing oracle
on chosen messages, A's probability of producing a valid
signature σ* on a previously-unqueried message M* under the
group public key pk is at most the standard ML-DSA EUF-CMA
advantage bound for Q_sign + 1 queries.
This is a tight reduction to FIPS 204 ML-DSA's underlying EUF-CMA
property, assuming an honest DKG output. The DKG soundness +
threshold-aggregation correctness implies that an A-controlled
quorum's view of the protocol is computationally indistinguishable
from a centralized signing oracle's view.
5.2 Output interchangeability (Class N1, NIST MPTC)
For every signature σ produced by an honest-quorum Pulsar
execution on inputs (M, ctx), σ is bit-identical to a
signature produced by single-party FIPS 204 ML-DSA Sign on the
implicit centralized secret f.eval(0) reconstructed from the
quorum's shares. Any FIPS 204 conformant verifier accepts σ
without modification.
This is the load-bearing operational property: deployed verifiers need no Pulsar-specific code path.
5.3 Public-key preservation across resharing (Class N4, NIST MPTC)
The proactive-resharing protocol (§9) produces new per-party
shares s_i' such that the implicit centralized secret
f'.eval(0) is identical to f.eval(0). The group public key is
preserved across reshare boundaries — committee membership rotates,
but the long-lived public identity does not.
5.4 Identifiable abort
If the protocol aborts during a signing round, the abort-evidence record (§10) is sufficient for any third party with only the public transcript to identify the deviating party. Honest parties are not falsely accused (sound). The protocol does NOT guarantee asynchronous identifiable abort under network partition — see §17.
5.5 Robustness
If at least t honest parties complete the protocol within Δ,
they produce a valid signature with overwhelming probability
(modulo FIPS 204's rejection-sampling tail, which terminates in
expected ≤ 256 / (1 − (3/4)^256) ≈ 256 attempts).
6. Public Distributed Key Generation (DKG)
6.1 Overview
The DKG produces:
- A FIPS 204-format group public key
pk = (ρ, t_1)(~1952 bytes for ML-DSA-65); - Per-party secret shares
(s_{1,i}, s_{2,i})for i = 1..n such that:- Any
t-subset Q reconstructs the implicit centralized secrets_1 = f.eval(0)via Lagrange interpolation at zero; - The public key
pkis the FIPS 204 derived public key of the implicits_1; - The DKG transcript is publicly verifiable: any third party can confirm the DKG ran honestly.
- Any
6.2 Setup
All parties have:
- A common ciphersuite identifier (e.g.,
PULSAR-THRESHOLD-ML-DSA-65). - A common session identifier
sid_dkg(32 bytes, derived from a public randomness beacon). - A common (
n,t) parameter pair. - A list of party identities
{ID_1, ..., ID_n}with corresponding long-term authentication public keys.
6.3 Round 1 — commitment
Each party i ∈ {1, ..., n}:
-
Samples a sharing polynomial
f_i ∈ R_q^l[X]of degreet − 1uniformly at random:f_i(X) = f_i^(0) + f_i^(1) · X + ... + f_i^(t−1) · X^(t−1)where each
f_i^(j) ∈ R_q^lis sampled uniformly. -
Computes Pedersen-style commitments to each coefficient
f_i^(j):C_i^(j) = G^(f_i^(j)) · H^(r_i^(j))where
G, Hare public R_q^l generators (derived fromsid_dkg), andr_i^(j) ∈ R_q^lis a fresh blinding factor. -
Broadcasts
{C_i^(0), C_i^(1), ..., C_i^(t−1)}to all parties over authenticated channels. -
Computes per-party share encryptions
enc_{i→j}(f_i.eval(j))for each j ∈ {1, ..., n} \ {i} using each recipient's long-term encryption public key (HPKE [RFC9180] with a PQ-safe KEM such as ML-KEM-768 [FIPS203] is RECOMMENDED). Sends encrypted shares over authenticated channels.
6.4 Round 2 — verification and complaint
Each party j:
-
Decrypts each
enc_{i→j}(f_i.eval(j))it received. -
For each
i ≠ j, verifies the share against the public commitments:G^(f_i.eval(j)) · H^(r_i.eval(j)) =? Π_{k=0}^{t−1} (C_i^(k))^(j^k) -
If verification fails for some i, broadcasts a
Complaint(i, j)message including the decryption transcript proof (HPKE open-then-prove construction). -
Each party
iaccused by a complaint either:- Reveals the correct share publicly (allowing all parties to accept it), OR
- Is excluded from the qualified set.
6.5 Qualified set determination
After the complaint round:
-
The qualified set
QSET ⊆ {1, ..., n}is the maximal subset such that:- Every party in QSET broadcast valid commitments;
- No party in QSET was successfully complained against;
|QSET| ≥ t.
-
If
|QSET| < t, the DKG ABORTS. -
Each party
jcomputes its final share:s_{1,j} = Σ_{i ∈ QSET} f_i.eval(j) s_{2,j} = (per-party s_2 derivation; see §6.6)
6.6 Group public-key derivation
Each party computes the group public key:
-
The implicit centralized secret is:
s_1 = Σ_{i ∈ QSET} f_i^(0)(NOT directly computed by any single party — only the per-party shares
s_{1,j}are known to parties.) -
The FIPS 204 secret
s_2is sampled jointly via a similar VSS protocol with the qualified-set parties. -
Each party can compute the public commitment to
s_1:T_0_committed = Σ_{i ∈ QSET} C_i^(0)which is the public commitment to
s_1. -
The group public key components
(ρ, t_1)are derived per FIPS 204 §3.5.4 ExpandA and KeyGen, with ρ being a publicly-fixed value derived fromsid_dkg(so all parties agree on A). -
All parties verify by reconstructing the public key from QSET commitments and confirming agreement.
6.7 DKG output
The DKG outputs:
- A public group key
pkagreed by all qualified parties; - A per-party share bundle
(s_{1,i}, s_{2,i})for each i ∈ QSET; - A public DKG transcript
T_dkgcontaining:sid_dkg,(n, t),QSET- All commitments
{C_i^(0), ..., C_i^(t−1)} for i ∈ QSET - The derived
pk - All complaint records (if any)
T_dkg is publicly verifiable: any third party can confirm
correctness given T_dkg + pk.
7. Threshold Signing
7.1 Inputs
To produce a signature on message M with context ctx:
- A quorum
Q ⊆ QSETof size|Q| ≥ t. - A signing session identifier
sid_sign(32 bytes, fresh). - A per-call randomness contribution from each party (see §11.3).
- The message
Mand contextctx(per FIPS 204 §5.4.1).
7.2 Round 1 — commitment
Each party i ∈ Q:
-
Computes the per-party randomness seed:
rho_prime_i = SHAKE256(K_i || rho_rnd_i || mu_ext || κ, 64)where:
K_iis party i's FIPS 204 K-component (per-party);rho_rnd_iis fresh entropy (32 bytes);mu_ext = SHAKE256(0x00 || |ctx| || ctx || M, 64)is the FIPS 204 §5.4.1 ExternalMu;κis the current rejection-loop counter (initially 0).
-
Samples the mask polynomial vector:
y_i = ExpandMask(rho_prime_i, 0)per FIPS 204 §3.5.4.
-
Computes the commitment:
w_i = A · y_i (mod q, in R_q^k) w1_i = HighBits(w_i, 2γ_2)where A is the public matrix derived from the group ρ via FIPS 204 ExpandA.
-
Broadcasts
(sid_sign, κ, ID_i, w1_i)to all parties in Q, authenticated under party i's long-term key.
7.3 Aggregator: challenge derivation
After receiving all |Q| commitments (or after Δ-timeout):
-
If fewer than
tcommitments received within Δ: invoke the abort protocol (§10). -
Aggregate:
w1_agg = Σ_{i ∈ Q} λ_i^Q · w1_i (coordinate-wise in R_q^k)where λ_i^Q are Lagrange coefficients on Q evaluated at 0.
-
Compute the challenge:
c_tilde = SHAKE256(mu_ext || w1Encode(w1_agg), 32) -
Broadcast
(sid_sign, κ, c_tilde)to all parties in Q.
7.4 Round 2 — response
Each party i ∈ Q:
-
Computes the challenge ring element:
c = SampleInBall(c_tilde) (per FIPS 204 §3.5.1) -
Computes the partial response:
z_i = y_i + c · s_{1,i} (in R_q^l) -
Broadcasts
(sid_sign, κ, ID_i, z_i)to the aggregator, authenticated.
7.5 Aggregator: combine
After receiving all |Q| partial responses:
-
Aggregate:
z = Σ_{i ∈ Q} λ_i^Q · z_i -
Compute auxiliary aggregate values:
cs2_agg = c · Σ_{i ∈ Q} λ_i^Q · s_{2,i} ct0_agg = c · t_0 (public) w_low_agg = LowBits(w_agg − cs2_agg, 2γ_2) h = MakeHint(−ct0_agg, w_agg − cs2_agg + ct0_agg, 2γ_2) -
Evaluate FIPS 204 §6.2 rejection conditions:
- R1:
||z||∞ < γ_1 − β - R2:
||w_low_agg||∞ < γ_2 − β - R3:
||ct0_agg||∞ < γ_2 - R4:
weight(h) ≤ ω
- R1:
-
If any condition fails:
- Increment κ;
- Restart from Round 1 (each party re-derives a fresh y_i with the new κ).
-
If all conditions pass:
- Pack
σ = sigEncode(c_tilde, z, h)per FIPS 204 §3.5.5; - Broadcast
(sid_sign, κ_accept, σ)to all parties in Q; - Honest parties verify
Verify(pk, M, ctx, σ) = trueper FIPS 204 §6.3 and terminate.
- Pack
7.6 Output
The output is a single byte string σ of length sig_bytes
(see §3 table) that:
- Verifies under any FIPS 204 conformant
Verify(pk, M, ctx, σ); - Is bit-identical to a single-party FIPS 204 ML-DSA Sign call on
the implicit centralized secret with the same
M,ctx, and appropriate aggregated randomness.
8. Verification
The verification algorithm is unmodified FIPS 204 §6.3 Verify. This document does NOT specify a Pulsar-specific verifier. Implementations MUST use a FIPS 204 conformant Verify primitive.
def verify(pk, M, ctx, sigma):
return FIPS204.ML_DSA_Verify(pk, M, ctx, sigma)
This is the load-bearing operational property of Pulsar: deployed verifiers (BoringSSL FIPS, AWS-LC, OpenSSL 3.0 PQ provider, cloudflare/circl, pq-crystals reference) accept Pulsar signatures without modification.
9. Proactive Resharing
9.1 Overview
Proactive resharing rotates per-party shares without changing the group public key. Used for committee rotation, key-compromise recovery, and periodic refresh.
9.2 Protocol
Inputs:
- Current quorum
Q_oldwith shares{s_{1,i}}_{i ∈ Q_old} - New committee
Q_newof sizen_new - New threshold
t_new(may equal or differ fromt_old) - Reshare session identifier
sid_reshare
Each party i ∈ Q_old (where |Q_old| ≥ t_old):
-
Samples a zero-secret polynomial:
g_i ∈ R_q^l[X] of degree (t_new − 1) such that g_i.eval(0) = 0 -
Sends shares
g_i.eval(j)to eachj ∈ Q_newvia the same VSS construction as DKG (Pedersen commitments + per-pair encryption + complaint round). -
After verification, each new-quorum party
jcomputes:s_{1,j}' = Σ_{i ∈ Q_old} λ_i^{Q_old} · s_{1,i}_at_j + Σ_{i ∈ Q_old} g_i.eval(j)where
λ_i^{Q_old}are Lagrange coefficients on Q_old evaluated at j. -
Old-quorum parties' shares are decommissioned (zeroized).
9.3 Public-key preservation
By construction:
Σ_{i ∈ Q_old} g_i.eval(0) = 0(zero-secret property);Σ_{i ∈ Q_old} λ_i^{Q_old} · f.eval(i)_at_0 = f.eval(0)(Lagrange);- Therefore
f'.eval(0) = f.eval(0), and the FIPS 204 derived public key is unchanged.
9.4 Verification
A public observer with the reshare transcript can verify:
- Each
g_iis correctly zero-secret (via commitments); - New-quorum shares are correctly derived from old-quorum shares.
The group public key pk is unchanged across the reshare; any
FIPS 204 verifier accepts post-reshare signatures with the same
pk.
10. Identifiable Abort and Slashing Evidence
10.1 Abort triggers
The protocol invokes the abort sub-protocol if any of:
- A party times out on a required Round-1 or Round-2 message
(after
Δ). - A party broadcasts equivocating messages (two different
w1_ivalues for the same(sid_sign, κ)). - A party's partial response
z_ifails verification against the public commitmentw_i. - A party's commitment
w1_ifails the consistency check after aggregation.
10.2 Abort-evidence record
Each abort triggers an abort-evidence record (TLV-encoded) sufficient for any third party with the public transcript to verify the abort cause:
AbortEvidence ::= SEQUENCE {
version INTEGER (0),
sid OCTET STRING (32),
kappa INTEGER,
accused INTEGER, -- party index
kind INTEGER {
equivocation(1),
bad_delivery(2),
mac_failure(3),
range_failure(4)
},
fields OctetString -- per-kind structured fields
}
Per-kind fields:
- equivocation: two signed messages from the same accused party
with the same
(sid, kappa)but different content. - bad_delivery: a recipient-decryptable HPKE ciphertext + the decrypted content + proof of decryption + proof the content fails verification against the accused's commitments.
- mac_failure: a message signed under the accused's long-term key but failing inner-MAC verification.
- range_failure: a partial response
z_ifailing the FIPS 204 R-condition check.
10.3 Verification by third party
Any third party with only (pk, T_dkg, AbortEvidence) can:
- Verify the accused's long-term signature on the included messages;
- Verify the cryptographic evidence (HPKE proof, R-condition norm computation, MAC value);
- Conclude that the accused deviated.
The protocol guarantees:
- Soundness: an honest party cannot be successfully blamed.
- Completeness (under synchronous network): a deviating party IS successfully blamed within Δ.
10.4 Slashing
For on-chain deployment:
- The abort-evidence record is submitted to a slashing contract;
- The contract verifies the evidence using the (publicly known) group state;
- On verification success, the contract slashes the accused party's stake.
Evidence sizes are bounded: typical record < 1.5 KB, fitting in a single transaction calldata field on Ethereum-class chains.
11. Transcript Construction and Domain Separation
11.1 Domain-separation prefix
All Pulsar hashes use a domain-separation prefix:
DOMAIN_PREFIX = "HANZO-PULSAR-MLDSA-v0.1"
This prefix MUST appear at the start of every SHAKE input to prevent cross-protocol replay.
11.2 Transcript hashing
Each protocol session maintains a running transcript:
T = SHAKE256(
DOMAIN_PREFIX
|| ciphersuite_id -- "PULSAR-THRESHOLD-ML-DSA-65"
|| version -- "0.1"
|| sid -- session identifier (32 bytes)
|| chain_id -- application-bound identifier
|| epoch -- monotonic counter
|| (n, t) -- threshold parameters
|| qualified_set_hash -- hash of sorted QSET
|| message_hash -- hash of M
|| context_hash -- hash of ctx
|| round_messages -- concatenated per-round broadcasts
)
Each per-round message in the transcript includes:
round_numbersender_indexkappa(signing only)payloadsignature_over_payload
11.3 Session identifier derivation
The session identifier sid MUST be derived from a
publicly-verifiable randomness source:
- On-chain deployments:
sid = SHAKE256(chain_id || block_hash || block_height || tx_index, 32) - Off-chain deployments:
sidMUST come from a publicly-verifiable randomness beacon (e.g., drand, RANDAO). Implementations MUST NOT use party-controlled randomness forsidto prevent biased-coin attacks against the DKG.
11.4 Replay prevention
The transcript binding prevents:
- Cross-chain replay:
chain_iddiffers. - Cross-session replay:
siddiffers. - Cross-epoch replay:
epochdiffers. - Cross-protocol replay:
DOMAIN_PREFIXdiffers from any other PQ-signature protocol.
12. Wire Formats
12.1 Encoding
All wire-level integers are little-endian byte sequences. All polynomial-vector elements are encoded per FIPS 204 §3.5.
12.2 Message types
PulsarMessage ::= SEQUENCE {
version INTEGER (0),
ciphersuite_id UTF8String, -- e.g., "PULSAR-THRESHOLD-ML-DSA-65"
sid OCTET STRING (32),
epoch INTEGER,
sender_index INTEGER,
msg_type INTEGER {
DKG_R1_Commit(1),
DKG_R1_EncShare(2),
DKG_R2_Complaint(3),
DKG_R2_Reveal(4),
SIGN_R1_Commit(5),
SIGN_AGG_Challenge(6),
SIGN_R2_Response(7),
SIGN_Final(8),
RESHARE_Commit(9),
RESHARE_EncShare(10),
ABORT_Evidence(11)
},
kappa INTEGER, -- present for SIGN_R1 / SIGN_R2 / SIGN_AGG_Challenge
payload OctetString,
signature OctetString -- sender's long-term-key signature
}
12.3 Public verifier interface
Verifiers receive only the final FIPS 204 signature σ and the
group public key pk. The full Pulsar protocol transcript is
irrelevant to the verifier — see §8.
13. Public-Chain Deployment Profile
13.1 On-chain transcript
For public-blockchain deployments:
- The DKG transcript
T_dkgSHOULD be posted on-chain (or committed to via a Merkle root + IPFS off-chain storage with on-chain root). - Each signing session's
sid_signMUST be bound to a block hash or transaction identifier. - Abort-evidence records (§10) MUST be submitted as on-chain transactions for slashing.
13.2 Validator set rotation
For blockchain validator sets:
- A new validator set triggers a
RESHAREevent (§9). - The new validator set's qualified subset becomes the new signing committee.
- The group public key
pkis preserved across rotation, enabling persistent on-chain identity.
13.3 Reorg behavior
Under chain reorganizations:
- A signing session that completed on a now-orphaned block MUST
be replayed on the new chain head (with a fresh
sid_signderived from the new block hash). - A signing session in progress at the reorg point MAY be aborted
and re-initiated, or MAY complete with the original
sid_signand be submitted to both chains (the signature itself is replay- safe via FIPS 204 verification on the application-level message, which typically includes a chain-state commitment).
13.4 Gas / calldata bounds
- A typical Pulsar signature is 3309 bytes (ML-DSA-65). Fits in a single Ethereum calldata transaction.
- Abort-evidence records are typically < 1.5 KB.
- Full DKG transcripts can exceed 50 KB for
n = 21, t = 14; recommended on-chain storage is Merkle root only with off-chain full transcript availability.
14. Test Vectors
Conformance test vectors are published at:
Vector categories:
| Category | Coverage |
|---|---|
| Single-party ML-DSA | KAT vectors matching pq-crystals reference at (n, t) = (1, 1) |
| DKG success | Transcripts at (n, t) ∈ {(3, 2), (5, 3), (7, 4), (10, 7), (21, 14)} |
| DKG complaint | Adversarial dealer scenarios with successful blame |
| DKG abort | Insufficient qualified set scenarios |
| Threshold signing | Full transcripts for honest quorum at the same (n, t) sweep |
| Replay negative | Cross-chain, cross-session, cross-epoch replay attempts (all rejected) |
| Malformed negative | Invalid commitments, shares, signatures (all rejected) |
| Reshare preservation | Pre- and post-reshare public keys match |
Each test vector includes the fields listed in §15 of the
companion evaluation.md.
15. Security Considerations
15.1 Post-quantum hardness
Pulsar inherits the M-LWE / M-SIS hardness of FIPS 204 ML-DSA. This document does NOT establish post-quantum hardness independently. See FIPS 204 [FIPS204] Appendix B for the hardness analysis.
15.2 Threshold-specific security
Threshold-specific reductions:
- DKG soundness: standard Pedersen-VSS soundness reduces to discrete-log hardness over R_q^l (assumed; analogous to standard threshold-cryptography literature).
- Signing unforgeability: tight reduction to ML-DSA EUF-CMA under honest-quorum assumption + DKG soundness.
- Output interchangeability: established by the v0.1 EasyCrypt
proof artifact (
proofs/easycrypt/Pulsar_N1_Extracted.ec).
Machine-checked proof artifacts at https://github.com/luxfi/pulsar/tree/main/proofs/.
15.3 Constant-time
Implementations MUST be constant-time on:
- Per-party share material (
s_{1,i},s_{2,i}); - Per-call randomness
rho_rnd_iand derived masky_i; - Any code path branching on rejection-condition outcomes when the rejection has not yet been broadcast.
Implementations MAY be variable-time on:
- Final accept/reject decision (per FIPS 204 §3.3 — the κ counter is not secret-dependent on long-term keys);
- Pure-public verification (calls FIPS 204 Verify).
The Pulsar reference Jasmin implementation
(jasmin/threshold/*.jazz) is constant-time-clean under jasmin-ct.
15.4 Replay and session binding
Implementations MUST bind every signing session to a unique sid
derived from a publicly-verifiable randomness source (§11.3).
Implementations MUST reject duplicate or stale sessions.
15.5 Identifiable abort under network partition
Identifiable abort is guaranteed ONLY under synchronous network
assumptions (§4.2). Under network partition, deviating parties may
be indistinguishable from delayed parties. Production deployments
SHOULD bind the synchronous-network timer Δ to consensus-layer
finality, e.g., 2 block intervals on Ethereum-class chains.
15.6 Side-channel hardening
The Jasmin reference is constant-time-clean. Production-grade implementations require:
- Static constant-time analysis on the production binary (jasmin-ct, ct-verif, or equivalent);
- Dynamic timing-leak testing (dudect at 10⁹ samples per target on a pinned CPU);
- Secret-key zeroization on heap, stack, and registers;
- Defense against power / EM side-channels (deployment-specific).
15.7 Domain separation
The DOMAIN_PREFIX "HANZO-PULSAR-MLDSA-v0.1" MUST appear at the
start of every SHAKE input (§11.1). Failure to include the prefix
opens cross-protocol replay attacks against any other ML-DSA
profile or other Pulsar version.
15.8 Rogue-key attacks
The DKG's Pedersen commitments (§6.3) bind each party's contribution to the qualified-set polynomial. Without commitment binding, a malicious party could adaptively choose its contribution after seeing other parties' shares (a rogue-key attack). The qualified-set determination (§6.5) excludes any party whose commitments cannot be verified.
16. Implementation Considerations
16.1 Reference implementation
A Go reference implementation is at:
Licensed under Apache-2.0. Includes:
- Full DKG, signing, verification, reshare, and abort flows.
- KAT test harness.
- Differential tests against three independent ML-DSA verifiers.
- Adversarial DKG simulator.
16.2 Jasmin high-assurance implementation
The threshold-layer Jasmin sources at
jasmin/threshold/{round1,round2,combine}.jazz are
constant-time-clean under jasmin-ct (3/3 blocking gate). They
extract to EasyCrypt for the formal refinement proof.
16.3 Bindings
Recommended bindings for production use:
- Rust: ABI-stable crate exposing the C ABI.
- C: header + library for FFI consumers.
- Python: ctypes wrapper for testing.
- Go: pure Go reference for protocol-level work.
- WASM: browser / blockchain VM targets.
16.4 Build reproducibility
The reference build is deterministic from a 48-byte seed.
scripts/build.sh produces byte-identical outputs across reruns.
This property is enforced on every CI commit.
17. Scope Boundary
| Boundary | Routing |
|---|---|
| Asynchronous identifiable abort | Synchronous model only; bind Δ to consensus-layer finality at deployment |
| 1-round signing | FIPS 204 rejection sampling precludes a 1-round threshold variant under any NIST-standard preprocessing oracle |
| DKG bias resistance under collusion | Bind sid_dkg to a randomness beacon (drand, RANDAO) at the chain layer |
| Adaptive corruption | The static reduction (this draft's posture) ports through the chain-corruption simulator in the v0.2 audit cycle |
| Threshold SLH-DSA | Magnetar research track at docs/magnetar.md |
| Cross-committee resharing without external state binding | Bind reshare epoch to consensus-layer state at deployment |
| Full mechanised closure of the 22 residual EC axioms | Per-axiom closure plan in docs/proof-axiom-inventory.md; the algorithm-level reference does not block on it |
18. IANA Considerations
This document requests no IANA actions. The ciphersuite
identifiers ("PULSAR-THRESHOLD-ML-DSA-{44,65,87}") are
human-readable strings used in the protocol's ciphersuite_id
field; they are NOT registered with IANA at this draft revision.
A future revision MAY register the ciphersuite identifiers under the Cryptographic Algorithm Identifiers registry if community adoption warrants.
19. References
19.1 Normative References
-
[FIPS204] National Institute of Standards and Technology, "Module-Lattice-Based Digital Signature Standard", FIPS 204, August 2024, https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf.
-
[FIPS202] National Institute of Standards and Technology, "SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions", FIPS 202, August 2015.
-
[FIPS203] National Institute of Standards and Technology, "Module-Lattice-Based Key-Encapsulation Mechanism Standard", FIPS 203, August 2024.
-
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997.
-
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017.
-
[RFC9180] Barnes, R., Bhargavan, K., Lipp, B., and C. Wood, "Hybrid Public Key Encryption", RFC 9180, DOI 10.17487/RFC9180, February 2022.
19.2 Informative References
-
[FROST] Komlo, C. and Goldberg, I., "FROST: Flexible Round-Optimized Schnorr Threshold Signatures", in Selected Areas in Cryptography 2020.
-
[PULSAR-SPEC] Lux Industries, "Pulsar Threshold ML-DSA Specification v0.1", https://github.com/luxfi/pulsar/blob/main/spec/pulsar.pdf.
-
[PULSAR-PROOFS] Lux Industries, "Pulsar EasyCrypt + Lean Refinement Proofs", https://github.com/luxfi/pulsar/tree/main/proofs.
-
[NIST-MPTC] National Institute of Standards and Technology, "NIST IR 8214C: NIST First Call for Multi-Party Threshold Schemes", https://csrc.nist.gov/pubs/ir/8214/c/iprd.
-
[Magnetar] Lux Industries, "Magnetar: Public-DKG MPC Threshold SLH-DSA (research profile)", https://github.com/luxfi/pulsar/blob/main/docs/magnetar.md.
Appendix A. Worked Example
A complete worked example for a 5-party DKG and signing session under PULSAR-THRESHOLD-ML-DSA-65 (n=5, t=3):
- Setup: parties 1..5, threshold 3, sid_dkg derived from block hash 0xabc...
- DKG R1: each party broadcasts 3 commitments (t coefficients) and 4 encrypted shares (n−1 recipients).
- DKG R2: party 4 sends a malformed share to party 2; party 2 broadcasts a complaint; party 4 reveals the correct share publicly; complaint resolved; QSET = {1, 2, 3, 4, 5}.
- Group public key derivation: all parties compute pk = (ρ, t_1) from QSET commitments.
- Signing session: quorum Q = {1, 2, 3}, sid_sign derived from a new block hash, message M = "transfer 100 LUX to ...", ctx = "PULSAR-DEMO-v0".
- Sign R1: parties 1, 2, 3 broadcast w1_i.
- Aggregator (party 1): computes c_tilde and broadcasts.
- Sign R2: parties 1, 2, 3 broadcast z_i.
- Combine: aggregator computes z, h, evaluates R1-R4 (all pass on the first κ=0), packs σ = sigEncode(c_tilde, z, h), broadcasts.
- Verify: any FIPS 204 verifier confirms σ verifies against pk on (M, ctx).
Full transcripts: vectors/transcripts/n5-t3-mldsa65-sign.jsonl.
Appendix B. Conformance Test Plan
A conforming implementation MUST pass:
- All KAT vectors in
vectors/sign.jsonandvectors/verify.json. - All threshold-signing transcripts in
vectors/threshold-sign.json. - All malformed-input rejection tests in
test/negative/. - Cross-validation against
cloudflare/circl(or another independent FIPS 204 implementation) on every KAT vector. - Adversarial DKG simulator scenarios in
test/adversarial/.
Suggested test-runner integration: invoke scripts/test.sh from
the reference repository as the conformance gate.
Authors' Addresses
Z. Kelling (Editor)
Lux Industries, Inc.
Email: z@lux.network
Pulsar maintainers
Lux Industries, Inc.
Email: mptc@lux.network
Document metadata
- IETF document name:
draft-hanzo-pulsar-threshold-mldsa-00 - Version: v0.1 (skeleton-complete; ready for CFRG review)
- Date: 2026-05-18
- Conversion path: this Markdown converts to xml2rfc XML via
mmarkorkramdown-rfcfor IETF datatracker submission. - License of this document: contributed under the IETF Trust
Legal Provisions (
https://trustee.ietf.org/license-info).