mirror of
https://github.com/lux-apps/papers.git
synced 2026-10-30 18:15:21 +00:00
Resolves high-severity review findings: anachronistic dates aligned to citation floors; arithmetic corrected to match formulas; internal contradictions collapsed to the body-supported value; LP self-references aligned to filenames; liquidity-surface repo paths scrubbed; AI-slop trimmed. PDFs rebuilt separately.
306 lines
15 KiB
TeX
306 lines
15 KiB
TeX
\section{Implementation}
|
|
\label{sec:implementation}
|
|
|
|
The Magnetar reference implementation is the Go canonical at
|
|
\texttt{github.com/luxfi/magnetar} \cite{magnetar}, tag
|
|
\texttt{v1.0.0}. The artefact ships both the per-validator standalone
|
|
primary primitive
|
|
(\texttt{ref/go/pkg/magnetar/standalone.go} and \texttt{wire.go})
|
|
and the THBS-SE permissionless threshold companion
|
|
(\texttt{ref/go/pkg/magnetar/thbsse.go} and
|
|
\texttt{thbsse\_field.go}). This section maps the
|
|
per-validator standalone construction of \S\ref{sec:construction}
|
|
and the THBS-SE public-combiner Combine path of \S\ref{sec:thbsse} to
|
|
the source layout.
|
|
|
|
\subsection{Public-combiner Combine path}
|
|
\label{sec:impl:combine-path}
|
|
|
|
The THBS-SE Combine path in v1.0 is implemented at
|
|
\texttt{ref/go/pkg/magnetar/thbsse.go::Combine}, backed by the
|
|
byte-wise $\mathrm{GF}(257)$ Shamir arithmetic in
|
|
\texttt{thbsse\_field.go} (\texttt{thbsseReconstructGF},
|
|
\texttt{thbsseModInvSmall}, \texttt{lagrangeBasisAtZero}). The
|
|
public combiner Lagrange-reconstructs the SLH-DSA scheme seed in
|
|
its own transient memory, dispatches to
|
|
\texttt{cloudflare/circl/sign/slhdsa.SignDeterministic}, and
|
|
zeroizes the seed and every working buffer before return
|
|
(\S\ref{sec:thbsse:combine}).
|
|
|
|
This is the v1.0 honest open item: the reconstructed seed exists in
|
|
the combiner's address space for the duration of one
|
|
\texttt{SignDeterministic} call (sub-second wall-clock at
|
|
SHAKE-192s). The combiner role is public --- any peer can run it ---
|
|
and no host is in the TCB by policy (\S\ref{sec:security:thbsse-tcb}).
|
|
|
|
The strict ``no transient seed at any moment'' refinement is the
|
|
planned v1.1 lift (\texttt{MAGNETAR-STRICT-ATOM-V11}): a
|
|
Magnetar-internal FIPS 205 \S5--\S8 walk that assembles the
|
|
signature directly from per-atom reconstructions of the
|
|
message-selected FORS leaves and WOTS+ chain bases, bypassing
|
|
\texttt{slh\_sign\_internal} so the master seed is never
|
|
materialised under a named \texttt{seed} / \texttt{SK.seed} /
|
|
\texttt{SK.prf} variable in the public combiner's scope. Closing
|
|
the residual gap entirely (no master-expansion bytes transient at
|
|
any moment) requires either full MPC over the SHAKE-256 hash tree
|
|
(open research) or a TEE-attested host in the TCB (sibling
|
|
primitive at \texttt{luxfi/threshold/protocols/slhdsa-tee}). The
|
|
wire format, share format, slot-guard state, and protocol round
|
|
structure are all forward-compatible with the lift; only Combine's
|
|
internals change.
|
|
|
|
\subsection{File layout (standalone primary)}
|
|
\label{sec:impl:layout}
|
|
|
|
\begin{table}[H]
|
|
\centering
|
|
\caption{Magnetar v1.0.0 file layout. The per-validator standalone
|
|
primary path lives in \texttt{standalone.go}; the THBS-SE
|
|
permissionless threshold companion lives in \texttt{thbsse.go} and
|
|
\texttt{thbsse\_field.go}, and is documented in
|
|
\S\ref{sec:thbsse} and \S\ref{sec:impl:combine-path}.}
|
|
\label{tab:magnetar-files-standalone}
|
|
\begin{tabular}{lp{8cm}}
|
|
\toprule
|
|
File & Role \\
|
|
\midrule
|
|
\multicolumn{2}{l}{\emph{Shared core}} \\
|
|
\midrule
|
|
\texttt{doc.go} & Package doc + v1.0 dual-primitive summary \\
|
|
\texttt{params.go} & FIPS 205 parameter table; Mode dispatch \\
|
|
\texttt{types.go} & Wire types ($\mathsf{NodeID}$, \texttt{Signature}, \texttt{PublicKey}, \texttt{PrivateKey}) \\
|
|
\texttt{keygen.go} & Single-party FIPS 205 KeyGen / DeriveKey passthrough \\
|
|
\texttt{sign.go} & Single-party FIPS 205 SignDeterministic / SignRandomized dispatch \\
|
|
\texttt{verify.go} & FIPS 205 Verify passthrough (no Magnetar envelope) \\
|
|
\texttt{wire.go} & Canonical MAGS / MAGG envelope codec; stateless \texttt{VerifyBytes} dispatcher \\
|
|
\texttt{transcript.go} & cSHAKE256 helper; THBS-SE share-deal customisation tag \\
|
|
\texttt{zeroize.go} & Constant-time wipes for bytes, uint16 slices, PrivateKeys \\
|
|
\texttt{dispatch.go} & ValidatorBatchTier provenance; ctEqualBytes \\
|
|
\midrule
|
|
\multicolumn{2}{l}{\emph{Per-validator standalone primary primitive}} \\
|
|
\midrule
|
|
\texttt{standalone.go} & \texttt{PerValidatorKeypair}, \texttt{ValidatorSign}, \texttt{ValidatorBatchVerify}, \texttt{ValidatorAggregateCert}, \texttt{BuildAggregateCert}, \texttt{VerifyAggregateCert} \\
|
|
\midrule
|
|
\multicolumn{2}{l}{\emph{THBS-SE permissionless threshold companion}} \\
|
|
\midrule
|
|
\texttt{thbsse.go} & \texttt{NewThbsSeKey}, \texttt{ThbsSeRound1}, \texttt{Combine}, \texttt{ThbsSeSlotGuard}, equivocation + share-evidence verifiers \\
|
|
\texttt{thbsse\_field.go} & Internal GF(257) byte-wise Shamir share arithmetic; \texttt{thbsseReconstructGF}, \texttt{lagrangeBasisAtZero}, \texttt{MaxCommittee257}, \texttt{EvalPointFromID} \\
|
|
\midrule
|
|
\multicolumn{2}{l}{\emph{Tests}} \\
|
|
\midrule
|
|
\texttt{standalone\_test.go} & 7 tests: round-trip, determinism, independence, batch verify, bad-sig-counted-out, unknown-validator rejection, duplicate-dedupe \\
|
|
\texttt{thbsse\_test.go} & 8 gate tests + 2 bonus: \textbf{TestThbsSE\_Wire\_FIPS205Verifiable}, \textbf{TestThbsSE\_RejectSeedReveal}, \textbf{TestThbsSE\_RejectUnselectedFORS}, \textbf{TestThbsSE\_RejectUnselectedWOTS}, \textbf{TestThbsSE\_SlotReuseRejected}, \textbf{TestThbsSE\_OverselectedCommittee}, \textbf{TestThbsSE\_SlotBindingDomainSeparation}, \textbf{BenchmarkThbsSE\_Sign\_5of7} \\
|
|
\texttt{wire\_test.go} & MAGS / MAGG roundtrip + \textbf{TestMagnetar\_Wire\_FIPS205Verifiable} (load-bearing byte-identity gate) \\
|
|
\texttt{kat\_test.go} & KAT replay including \textbf{TestKAT\_ThbsSe} (deterministic $n=7,t=4$ vectors) \\
|
|
\texttt{sign\_test.go} / \texttt{keygen\_test.go} & Single-party FIPS 205 dispatch tests \\
|
|
\texttt{race\_off\_test.go} / \texttt{race\_on\_test.go} & \texttt{raceEnabled} build-tag pattern (FIPS 205 heavy paths skipped under race) \\
|
|
\midrule
|
|
\multicolumn{2}{l}{\emph{KAT generator}} \\
|
|
\midrule
|
|
\texttt{cmd/genkat/main.go} & Deterministic KAT regeneration binary \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\end{table}
|
|
|
|
The strict layering invariant: every standalone-path file's
|
|
package-public surface calls only into lower-level packages (FIPS
|
|
205 via \texttt{circl}, cSHAKE256); no cross-file circular
|
|
dependency. The standalone primitive is implemented top-down with
|
|
\texttt{VerifyAggregateCert} sitting at the highest layer, calling
|
|
\texttt{ValidatorBatchVerify}, which dispatches the
|
|
\texttt{circl.slhdsa.Verify} workers via the same goroutine
|
|
fork-join pattern as \texttt{luxfi/crypto/slhdsa.VerifyBatch}.
|
|
|
|
\subsection{Dependencies}
|
|
\label{sec:impl:deps}
|
|
|
|
The dependency graph is deliberately narrow.
|
|
|
|
\begin{itemize}[leftmargin=2em,nosep]
|
|
\item \texttt{github.com/cloudflare/circl}~v1.6.3 \cite{circl}:
|
|
FIPS 205 SLH-DSA reference (BSD-3-Clause). Magnetar uses
|
|
\texttt{circl/sign/slhdsa} for
|
|
$\textsc{KeyGen}$ / $\textsc{DeriveKey}$ /
|
|
$\textsc{SignDeterministic}$ / $\textsc{SignRandomized}$ /
|
|
$\textsc{Verify}$. The \texttt{circl} implementation is the
|
|
most widely-deployed Go FIPS 205 backend; its constant-time
|
|
posture has been audited under Cloudflare's internal review
|
|
and is used in \texttt{cloudflare/cf-mldsa-precompile} in
|
|
production.
|
|
\item \texttt{golang.org/x/crypto}~v0.32.0: provides
|
|
\texttt{sha3.NewCShake256} for cSHAKE256 and the SP 800-185
|
|
encoding primitives. Standard-library-adjacent dependency.
|
|
\item \texttt{golang.org/x/sys}~v0.29.0 (indirect): platform
|
|
syscall layer used by \texttt{crypto/rand}.
|
|
\end{itemize}
|
|
|
|
The dependency on \texttt{circl} is the load-bearing one. The
|
|
byte-identity claim of
|
|
$\textsc{TestMagnetar\_Wire\_FIPS205Verifiable}$ binds Magnetar's
|
|
output to the exact \texttt{circl}-emitted bytes. If \texttt{circl}
|
|
v1.6.3 were ever deprecated or its FIPS 205 implementation found
|
|
non-conformant, Magnetar would need to switch to a different FIPS 205
|
|
backend. Two alternative backends are candidate: a future Go
|
|
\texttt{crypto/slhdsa} once Go's \texttt{crypto} package gains FIPS
|
|
205 support, and a vendored Magnetar copy of the NIST FIPS 205
|
|
reference C implementation wrapped via cgo. Both are tracked in
|
|
\texttt{TRUSTED-COMPUTING-BASE.md}.
|
|
|
|
\subsection{Build and test discipline}
|
|
\label{sec:impl:build}
|
|
|
|
The reproducible build is:
|
|
\begin{lstlisting}[language=bash,caption={Magnetar reproducible build.}]
|
|
cd ref/go
|
|
GOWORK=off go build ./...
|
|
GOWORK=off go test -short ./pkg/magnetar/...
|
|
GOWORK=off go test -count=1 -run TestMagnetar_Wire_FIPS205Verifiable ./pkg/magnetar/...
|
|
\end{lstlisting}
|
|
|
|
The \texttt{GOWORK=off} flag is required to suppress a workspace
|
|
file that overlays unrelated Lux packages; without it, Go's module
|
|
loader pulls in transitive paths that may not be on the developer's
|
|
machine. (This is a long-standing Lux-internal annoyance, not a
|
|
Magnetar-specific quirk.)
|
|
|
|
The \texttt{-count=1} flag bypasses Go's test cache and forces a
|
|
fresh execution, which is the standard discipline for crypto
|
|
regression gates: a cached PASS on a stale binary is not evidence.
|
|
|
|
The \texttt{-short} flag selects the fast CI configuration; the
|
|
SLH-DSA-heavy test paths run only the cheap configurations under
|
|
\texttt{-short}.
|
|
|
|
\paragraph{Race detector pattern.} The \texttt{raceEnabled}
|
|
build-tag pattern at \texttt{race\_off\_test.go} /
|
|
\texttt{race\_on\_test.go} gates SLH-DSA-heavy tests behind
|
|
\texttt{!race}; the race detector adds 5--10x overhead on the
|
|
SLH-DSA hot path, and the tests are \emph{single-goroutine} so they
|
|
cannot detect a race regardless. The
|
|
$\textsc{TestMagnetar\_Wire\_FIPS205Verifiable}$ gate uses
|
|
\texttt{skipUnderRace} to skip under \texttt{-race}; race-on runs
|
|
cover the cheap wire-codec roundtrip tests. This pattern is shared
|
|
with Pulsar and Corona and is documented in their respective
|
|
READMEs.
|
|
|
|
\paragraph{KAT regeneration.} The KAT generator at
|
|
\texttt{cmd/genkat} accepts a single 48-byte master seed
|
|
(\texttt{masterSeedHex}) and produces deterministic vector files.
|
|
Re-running the binary on a clean checkout produces byte-identical
|
|
output --- this is the deterministic-fixture gate. Drift between
|
|
committed JSON and freshly-regenerated output is a CI failure.
|
|
|
|
\subsection{Headline regression: TestMagnetar\_Wire\_FIPS205Verifiable}
|
|
\label{sec:impl:wirefips}
|
|
|
|
The byte-identity claim is gated by the test at
|
|
\texttt{ref/go/pkg/magnetar/wire\_test.go:124-220}. The test routes
|
|
through the v1.0 per-validator standalone primary path:
|
|
|
|
\begin{lstlisting}[language=go,caption={Excerpt: \texttt{TestMagnetar\_Wire\_FIPS205Verifiable} core assertions.}]
|
|
sk, pk, _ := PerValidatorKeypair(params, newDetReader(seed))
|
|
sigBytes, _ := ValidatorSign(sk, nil, msg)
|
|
sig := &Signature{Mode: mode, Bytes: sigBytes}
|
|
|
|
// Frame both via the canonical wire codec.
|
|
gkWire, _ := MarshalGroupKey(pk)
|
|
sigWire, _ := sig.MarshalBinary()
|
|
|
|
// Strip the 11-byte header to recover the raw FIPS 205 payload.
|
|
fipsPK := extractFIPS205Payload(t, gkWire, wireMagicMagnetarGroupKey)
|
|
fipsSig := extractFIPS205Payload(t, sigWire, wireMagicMagnetarSig)
|
|
|
|
// Verify under cloudflare/circl directly. No magnetar code path
|
|
// is hit on the verify side. This is the load-bearing assertion.
|
|
if !verifyDirectCircl(mode, fipsPK, msg, fipsSig) {
|
|
t.Fatalf("FIPS 205 Verify rejected the unwrapped Magnetar bytes")
|
|
}
|
|
\end{lstlisting}
|
|
|
|
The test runs for all three SHAKE parameter sets (SHAKE-192s,
|
|
SHAKE-192f, SHAKE-256s) and passes under \texttt{-count=1} and
|
|
\texttt{-race}. It is the single test that pins
|
|
\S\ref{sec:security:byte-equality} empirically.
|
|
|
|
\subsection{Configuration-as-data}
|
|
\label{sec:impl:config}
|
|
|
|
The Mode-to-Params dispatch in \texttt{params.go} is a static table
|
|
with no runtime logic:
|
|
\begin{lstlisting}[language=go,caption={Mode dispatch in \texttt{params.go}.}]
|
|
var ParamsM192s = &Params{
|
|
Mode: ModeM192s,
|
|
N: 24,
|
|
PublicKeySize: 48,
|
|
PrivateKeySize: 96,
|
|
SignatureSize: 16224,
|
|
SeedSize: 96,
|
|
ID: slhdsa.SHAKE_192s,
|
|
ShamirPrime: 257,
|
|
}
|
|
\end{lstlisting}
|
|
|
|
The \texttt{Params.Validate()} method checks that a supplied
|
|
\texttt{*Params} matches one of the canonical tables exactly. Any
|
|
deviation --- a tampered \texttt{ShamirPrime}, a wrong
|
|
\texttt{SeedSize}, an unsupported \texttt{Mode} --- is rejected at
|
|
the entry point of \texttt{PerValidatorKeypair},
|
|
\texttt{ValidatorSign}, \texttt{ValidatorBatchVerify}, and
|
|
\texttt{VerifyAggregateCert}. The \texttt{*Params} argument is the
|
|
single point where parameter selection enters the crypto path; this
|
|
matches the ``one and only one way to do everything'' discipline.
|
|
|
|
\subsection{Concurrency posture}
|
|
\label{sec:impl:concurrency}
|
|
|
|
The standalone primary path's
|
|
\texttt{ValidatorBatchVerify} dispatches across
|
|
$\min(\mathit{GOMAXPROCS}, N)$ goroutines above the
|
|
\texttt{verifyAggregatedConcurrentThreshold} constant (currently
|
|
$\sim 16$); below that, the batch runs serial. Each worker
|
|
invokes \texttt{circl.slhdsa.Verify} on a disjoint range of the
|
|
input slices; there is no shared mutable state.
|
|
|
|
\texttt{ValidatorSign} is strictly single-goroutine: the FIPS 205
|
|
signing path is sequential per signature, and a deployment running
|
|
many concurrent signing sessions allocates one signer goroutine per
|
|
session. THBS-SE Combine is also strictly single-goroutine per
|
|
session: the FIPS 205 dispatch dominates the runtime and the
|
|
Lagrange interpolation is small enough that there is no
|
|
parallelization win at the round threshold sizes (typically
|
|
$t \le 21$).
|
|
|
|
\subsection{Lux Polaris integration}
|
|
\label{sec:impl:polaris}
|
|
|
|
Magnetar plugs into the Lux Polaris cert profile at the LSS
|
|
\cite{luxlssmpc} adapter layer. The integration is intentionally
|
|
mirror-symmetric with Pulsar and Corona at the public-BFT path: a
|
|
Polaris signer is the composition $\textsc{PolarisSigner} =
|
|
(\textsc{PulsarSigner}, \textsc{CoronaSigner},
|
|
\textsc{MagnetarSigner})$, with the three lanes signing the same
|
|
Prism-bound transcript. The Magnetar lane's
|
|
$\textsc{MagnetarSigner}$ is the per-validator standalone primitive
|
|
of this paper.
|
|
|
|
The activation cert composition: a Polaris generation transition
|
|
requires three independent per-lane operations in lockstep.
|
|
For Magnetar, this is per-validator rotation of $pk_i$ in the
|
|
registry; the standalone primitive does not have a DKG-style
|
|
``activation cert'' construction (it does not need one --- no
|
|
shared key to activate). The LSS adapter contract
|
|
\cite{luxlssmpc} is primitive-agnostic at its boundary; Magnetar's
|
|
standalone adapter implements an empty $\textsc{Reshare}$
|
|
(rotation is per-validator, not committee-wide) and a
|
|
$\textsc{KeyRotate}$ that signs the old $pk_i$ replacing under
|
|
$sk_i^{\mathrm{old}}$ before installing $(sk_i^{\mathrm{new}},
|
|
pk_i^{\mathrm{new}})$.
|
|
|
|
For THBS-SE (\S\ref{sec:thbsse}), the LSS lifecycle is
|
|
committee-wide and matches the Pulsar / Corona threshold adapters
|
|
shape: a Polaris generation transition rotates the committee's
|
|
threshold material via a fresh \texttt{NewThbsSeKey} ceremony (or
|
|
the production leaderless PVSS-DKG variant in the sibling
|
|
\texttt{luxfi/threshold} package) and re-publishes the new group
|
|
public key under the next-generation LSS adapter.
|