Files
corona/AUDIT-2026-06.md
T
zeekay df1db68bd0 docs/comments: correct lattice-family label Ring-LWE -> Module-LWE (Corona is Module-LWE)
Corona is Module-LWE (threshold-Raccoon/Ringtail), NOT Ring-LWE. Confirmed in code: sign/sign.go samples A in R_q^{8x7} (sign.go:87 SamplePolyMatrix M=8,N=7), secret s a rank-7 ring vector, b=A*s+e (sign.go:106-107) over R_q=Z_q[X]/(X^256+1) (LogN=8), q=0x1000000004A01 -- rank>1 module structure, not rank-1 ring-LWE. threshold/threshold.go:4-5 already said Module-LWE.

Fixed the family label across README, SPEC, SUBMISSION, NIST-SUBMISSION, PATENTS, LLM, CONTRIBUTING, SECURITY, CHANGELOG, DEPLOYMENT-RUNBOOK, Makefile, AXIOM-INVENTORY, PROOF-CLAIMS, BLOCKERS, CRYPTOGRAPHER-SIGN-OFF, FIPS-TRACEABILITY, TRUSTED-COMPUTING-BASE, AUDIT-2026-05/06, docs/mptc/*, jasmin/README, 3 Go comments + cli help string.

Also corrected the downstream false claim that Corona (Ring-LWE) and Pulsar (Module-LWE) are 'different lattice families' giving 'structural/family diversity': both are Module-LWE, so the Double-Lattice defense is construction/implementation diversity (threshold-Raccoon vs ML-DSA), not hardness-family diversity; a Module-LWE break affects both legs (hash-based Magnetar is the assumption-diversifier). Fixed companion R-SIS -> Module-SIS where it was the module scheme's SIS assumption; added the Langlois-Stehle (DCC 2015) Module-LWE citation alongside LPR 2010.

Delicate artifacts: proof identifiers (rlwe_sign_op, RLWE_Functional theory/file, *_eq_rlwe bridges, CentralRLWESign, RLWESign, rlwe_compute_*) were NOT renamed -- EasyCrypt/jasmin toolchains are absent here so a rename cannot be compile-verified, and .assurance/ gates parse those names. Added clarifying naming notes to the 5 prominent .ec files, proofs/easycrypt/README.md, AXIOM-INVENTORY.md, and jasmin/rlwe/sign.jazz. .assurance/*.txt left untouched (already say Module-LWE/Module-SIS; rlwe tokens are gate-parsed identifiers). Left AUDIT-2026-06.md:463 historical rename-log and the ProtoStar-LWE paper-title substring untouched.

go build ./... and go test ./... green (GOWORK=off; all packages ok).
2026-06-27 16:12:24 -07:00

29 KiB
Raw Blame History

Corona Cryptographic Audit — 2026-06-02

Audit subject: github.com/luxfi/corona at main, post-39de1ed ("gofmt -s across repo (CI format check)"). Latest tag v0.7.5.

Scope: production deployment on Lux public-permissionless chain, covering four dimensions:

  1. Public-permissionless-chain safety (rogue-key, adaptive corruption, equivocation slashability, front-running on share aggregation).
  2. TEE integration (NVIDIA Confidential Computing, AMD SEV-SNP, Apple Secure Enclave) — was a likely gap.
  3. GPU acceleration for native block building — inventory + cross-link with ~/work/lux-private/gpu-kernels/.
  4. Corona -> corona rename hygiene across the repo.

Auditor: cryptographer agent (Hanzo Dev, internal review). Mirrors: AUDIT-2026-05.md structure; this is the next audit cycle, focused on the four dimensions enumerated above.


§0 One-page summary (executive)

Dimension Finding Status
D1 Permissionless safety Rogue-key NOT APPLICABLE (single global (A, bTilde), no per-party pk in the BLS-aggregation sense). Adaptive corruption documented OUT OF SCOPE — paper-cited only. Slashable evidence is cryptographically extractable via signed dkg2.Complaint + activation-cert non-verification (load-bearing). Front-running on aggregation: sid IS bound into PRNG seed / MAC / transcript-hash, but is plumbed as int (not 32-byte randomness as threat-model.md §7.1 claims — see Finding D1-2). one MEDIUM finding (D1-2); two INFORMATIONAL
D2 TEE integration Was a gap — no integration spec existed. DEPLOYMENT-RUNBOOK.md §5 recommended TEE attestation as a one-liner. Closed by this audit: docs/mptc/tee-integration.md ships the full per-platform spec (SEV-SNP, NVIDIA CC, Intel TDX, Apple SEP). Code touchpoint: ZERO (the entire TEE layer sits OUTSIDE the Corona kernel — decomplecting rule). spec landed; one MINOR roadmap item for MaybeRegisterAttested
D3 GPU acceleration corona/gpu is a thin SubRing-registration shim around luxfi/lattice/v7/gpu. Real GPU NTT kernels live in lattice/v7, NOT in lux-private/gpu-kernels. Separately, lux-private/gpu-kernels/ops/mpcvm/*/mpcvm_Corona.* and ops/crypto/Corona/ are stale-named kernels for the MPCVM ceremony-state-machine — these are a sister repo rename TODO, not in-scope here. Audit defers the kernel rename to that repo's own work. one INFORMATIONAL; one cross-repo TODO
D4 Corona->corona Fixed inside corona/: Makefile, Dockerfile, .github/workflows/ci.yml, .golangci.yml. Dropped: docs/{app,content,lib,...} — a fumadocs Next.js site framing Corona as a privacy ring-signature scheme (Schnorr + linkability), which is NOT what Corona is. Kept: historical refs in CHANGELOG.md / LLM.md / CRYPTOGRAPHER-SIGN-OFF.md (they document the prior v0.4.x rename and are correct as historical context). Cross-repo: luxfi/threshold ships protocols/Corona/, protocols/lss/factory_Corona_*.go, and a "Corona" scheme map key. The historical name lives at the consumer; this is a separate-repo rename and out-of-scope. repo-internal sweep complete; one cross-repo TODO

Production deployment posture: APPROVED WITH ROADMAP GATES for public-permissionless deployment under the v0.7.5 trust posture, with the carryover CRYPTOGRAPHER-SIGN-OFF.md gates GATE-3b (10^9-sample dudect) and GATE-4 (external audit) as v0.8.0 roadmap. The TEE integration spec (this audit's primary deliverable) closes the "how do we operationally bring the side-channel and host-compromise mitigations into a deployable shape" question.


§1 D1 — Public-permissionless-chain safety

§1.1 Rogue-key attack resistance

Verdict: NOT APPLICABLE in the BLS sense. Corona is not a multi-signature scheme over independent public keys; it is a threshold signature scheme over a single shared group key gk = (A, bTilde). There is no per-party public key that a malicious party could choose to mount a Wagner-style rogue-key forgery against an honest party's public key. The DKG path (dkg2/) commits each contribution under a hiding Pedersen blind; the public key emerges as the sum of commits in NTT form, with no per-party publicly-claimed key.

Honest framing: Boschini et al. ePrint 2024/1113 §3 proves EUF-CMA-Threshold under the single-group-key model. The permissionless-deployment caveat is not rogue-key — it is adversarial-DKG-contribution, addressed by Pedersen hiding + the complaint pipeline (§1.4 below). The chain MUST run BootstrapPedersen (default since v0.7.5), not the legacy BootstrapTrustedDealer, to be permissionless-safe (see AUDIT-2026-05.md §10).

Hash-to-curve binding: Corona doesn't use hash-to-curve; it's a Module-LWE scheme. The challenge c = H(A, bTilde, w, μ, sid, T) is a sponge output (Corona-SHA3 via KMAC256), and is domain-separated by QUASAR-CORONA-* prefixes (see primitives/hash.go).

No finding.

§1.2 Adaptive corruption (D1-1, INFORMATIONAL)

Finding D1-1: Adaptive corruption of up to t-1 parties is documented in docs/mptc/threat-model.md §2.1 as OUT OF SCOPE at this submission. Boschini et al. ePrint 2024/1113 proves adaptive security in ROM, but Corona ships no Corona-specific machine-checked adaptive proof. This is a known carryover from the v0.7.5 sign-off; not blocking for v0.7.5 production deployment because:

  • Lux consensus rotates the committee every epoch via keyera.Reshare, so a static-corruption-per-epoch model applies between rotations. The reshare protocol fixes the membership window before the corruption window opens.
  • Production deployments wire authenticated pairwise channels at the consensus layer, which bounds the adversary's ability to inject new corrupt parties mid-session.

Recommendation: track for v0.8.0 mechanization gate (GATE-4) — external audit lab should produce the Corona-specific adaptive ROM proof (the paper proves the algorithm; the audit lab proves the implementation matches).

Status: documented; not action-required for v0.7.5.

§1.3 Slashable equivocation evidence (load-bearing)

Verdict: PASSED — evidence is cryptographically extractable from dkg2.Complaint and from activation-cert verification failure.

Construction: A dkg2.Complaint (see dkg2/complaint.go) is an Ed25519-signed message carrying (TranscriptHash, SenderID, ComplainerID, Reason, Evidence, Signature, ComplainerKey). The evidence is one of:

  • (share, blind, commits) re-checkable against dkg2.VerifyShareAgainstCommits.
  • An equivocation pair: two distinct commits signed by SenderID under the same TranscriptHash.
  • A malformed commit blob (structural verification fails).

Any non-participant validator that observes the cohort transcript

  • the complaint can re-verify:
  1. Complainer's Ed25519 signature over c.Bytes().
  2. Evidence re-checks under the committed transcript hash.

The verifier outputs bool deterministically; the slashing decision (how many complaints constitute disqualification, how much stake to slash) is a consensus policy at the Quasar layer (see reshare/quasar_integration.go §Slashing-Evidence).

Why this is permissionless-safe: the chain does not need to trust the complainer or the accused. The chain runs the verifier in deterministic mode and the verdict is reproducible by any observer. This is the cryptographically extractable property that public-permissionless chains require.

Equivocation in signing (not DKG): a signer who broadcasts two distinct (D, MACs) Round-1 outputs for the same sid produces two MACs under the same key. The recipient detects this via SignRound2Preprocess MAC mismatch; the per-pair MAC includes sid and partyID, so equivocation is detectable but not currently broadcast as a signed complaint in the signing path (only in the DKG path).

Finding D1-3 (MINOR): extend the Complaint mechanism to signing-round equivocation. The MAC mismatch path in sign/sign.go:SignRound2Preprocess returns valid=false and the session aborts, but the round-1 MAC evidence is not captured into a signed complaint for the consensus layer to slash on. Today the path is "session abort, retry next epoch" — which is correct for liveness but does not extract slashable evidence for the malicious round-1 signer. Recommendation: emit sign.SigningComplaint{...} paralleling dkg2.Complaint. Track for v0.7.6.

§1.4 Front-running on share aggregation

Verdict: PASSED with one MEDIUM finding on the entropy size of sid.

Construction: Round 1 signers commit a (D, MACs) tuple under a PRNG seed derived from (skShare, sid):

prfKey = PRNG(skShare.Bytes()) // domain "CoronaRoundV2 || be64(sid)"

(see primitives/hash.go:PRNGKeyForRound). The per-pair MAC binds (partyID, sid, T, otherParty) (see primitives/hash.go:GenerateMAC). The Round-2 transcript hash is H(A, bTilde, D, sid, T) (see primitives/hash.go:Hash).

This is the CRIT-1 fix committed 2026-05-03: without sid mixing, R/E/D were byte-identical across sessions with the same skShare, which would allow an aggregator to replay an earlier Round 1 from a target signer to force a known nonce-reuse in a new session. The sid binding is the load-bearing defense against this front-running attack.

Finding D1-2 (MEDIUM): sid is plumbed as a Go int (64-bit signed integer on amd64/arm64), not as 32 bytes of fresh randomness. The docs/mptc/threat-model.md §7.1 text claims sid is "fresh per-session 32-byte randomness", but at the kernel boundary (sign.SignRound1(... sid int ...)) and at the threshold orchestration layer (threshold.Signer.Round1(... sessionID int ...)), the actual entropy passed is 64 bits.

This is adequate for chain-bound signing, where the consensus layer can derive sessionID from a hash of (epoch, slot, message_hash) so that two sessions never collide within the security parameter — but it is NOT 32 bytes of fresh randomness as the threat model claims. The doc overstates the entropy.

Remediation options:

  • (A) Tighten the doc to say sid is a 64-bit session identifier derived deterministically at the consensus layer from (epoch, slot, msg_hash). This is the actual contract. Lower-risk; backward-compatible.
  • (B) Widen the kernel API to accept sid []byte of length 32. Bigger change (breaks the v0.7.x ABI; would need a v0.8.0 bump per LLM.md rules), but matches the threat-model claim and gives future-proofing for non-chain-bound deployments.

Recommendation: (A) at v0.7.6 (doc-only tightening + a comment in sign/sign.go calling out the 64-bit contract). Track (B) for the v0.8.0 ABI bump where the threshold layer's wire codec is also touched.

Severity rationale: this is MEDIUM rather than HIGH because production deployments DO drive sessionID from a hash-derived slot, so the actual deployed entropy is 64 bits per session where the chain enforces uniqueness via the slot. A malicious aggregator cannot fork-and-replay because the slot is unique on the canonical chain.

§1.5 Aggregator-host compromise

Carryover from DEPLOYMENT-RUNBOOK.md §Trust-model item 2. An adversary that fully compromises the aggregator host (root-equivalent) during a signing session can observe c and z_i for all i ∈ Q and compute s_Q = Σ λ_i s_i if it sees enough partial-response sets across distinct quorum subsets.

This is the load-bearing motivation for the TEE integration specified in §2 below. Without TEE, the runbook's mlock-pinning

  • ptrace-disabled + core-dump-disabled set is the best a plain-OS deployment can do.

No finding new; the runbook already documents this and §2 below ships the TEE closure.

§1.6 Lifecycle equivocation

The activation-cert circuit-breaker in reshare/activation.go deterministically rejects a resharing whose (A, bTilde) diverges from the prior epoch's group key. A malicious sub-quorum of the old committee cannot install a new key era under the same KeyEraID — the activation cert MUST verify under the unchanged group key, and failure routes through LSS Rollback to the previous generation (DEPLOYMENT-RUNBOOK.md §Failure-mode threat model ladder).

A new key era (Reanchor) is a governance event with its own trust-model — covered by the v0.7.4 ReanchorPedersen closure.

No finding.


§2 D2 — TEE integration

§2.1 Pre-audit state

DEPLOYMENT-RUNBOOK.md §Operational mitigations item 5 recommended "aggregator runs inside SGX, SEV-SNP, or TDX with remote attestation pinned to the reproducible build of luxfi/corona v0.7.5" — but shipped NO integration spec, NO attestation API, NO per-platform guidance, NO reproducible-builder pinning, and NO NVIDIA-CC story even though corona/gpu opts into GPU NTT dispatch.

The keyera/ package has multiple TEE references (HSM/TEE ceremony aliases at BootstrapTrustedDealer, etc.) but those are trust-anchor citations, not integration specs.

§2.2 Audit closure — docs/mptc/tee-integration.md

Delivered: full per-platform TEE integration spec at docs/mptc/tee-integration.md. Covers:

  1. AMD SEV-SNP (primary Linux path): VM-level confidentiality, SNP_GET_REPORT -> AMD KDS verification -> share unseal flow, composite attestation binding, zero Corona code touchpoint.
  2. NVIDIA Confidential Computing (H100/H200/B200 CC mode): recommended when gpu.UseAccelerator() is invoked in production. SPDM-encrypted PCIe, NRAS attestation, composite (CPU SEV-SNP + GPU NRAS) evidence. ONE optional plumbing function proposed (gpu.MaybeRegisterAttested) for the v0.7.6 release.
  3. Intel TDX: alternative Linux path (equivalent boundary to SEV-SNP; works with H100 CC composite).
  4. Apple Secure Enclave: validator share storage on Apple Silicon; honest disclosure that Apple does NOT publish a remote attestation root (local-only defense-in-depth).
  5. Intel SGX: NOT RECOMMENDED for Corona (long CVE record of side-channel attacks against Module-LWE math).

§2.3 Decomplecting rule

The TEE layer is ONE LAYER above the Corona cryptographic kernel. The kernel has no awareness of TEE state, no TEE-specific build tag, no TEE-conditional code path. The TEE layer is consulted at three lifecycle moments by the consensus layer (not by Corona):

  • Bootstrap-trusted-dealer ceremony decision (operator's call to keyera.BootstrapTrustedDealer).
  • Per-validator share storage (the KeyShare bytes are sealed at rest by the storage layer; Corona just consumes the unsealed struct).
  • Per-validator signing session (the consensus layer runs Corona inside an attested TEE; Corona observes the protocol via its normal byte structures).

This decomplecting follows the project rule: profile gate / TEE gate / attestation gate is ONE function in ONE place (consensus-layer attestation verifier), not braided into the crypto math.

§2.4 One MINOR roadmap item (D2-1)

Finding D2-1 (MINOR): gpu/gpu.go ships MaybeRegister(r) (no attestation check). For the CC-mode GPU deployment path, the spec calls for MaybeRegisterAttested(r, token) — register only on successful attestation verification. The attestation verifier itself lives in the consensus layer at ~/work/lux/threshold/attestation/ (proposed). Track for v0.7.6.

Status: documented in §3.2 of the TEE integration spec; not blocking for v0.7.5 production deployment because:

  • The default GPU dispatch threshold is 1024, and Corona's production ring degree is N=256 — so by default, single-poly NTT runs on the CPU path, NOT on the GPU. The CC-mode story is only load-bearing if operators explicitly opt into UseAcceleratorForce() (test-only) or override SetThreshold(1) (production opt-in).
  • Without explicit opt-in, no GPU dispatch occurs and the attestation gap doesn't matter.

§2.5 No further TEE findings

The remaining TEE items in the integration spec are roadmap-tracked (§7 of the spec): builder image digest pinning, SEV-SNP CVM bootstrap agent, Apple SEP storage layer, formal CC-mode blinding analysis. None of these block v0.7.5 production deployment.


§3 D3 — GPU acceleration inventory

§3.1 corona/gpu/ is a shim, not a kernel home

The corona gpu/ package (181 LOC of Go + 130 LOC of tests) is a SubRing-registration shim that binds rings produced by threshold.NewParams() into the luxfi/lattice/v7/gpu per-SubRing NTT dispatcher. There are NO GPU kernels in corona/ itself.

The actual GPU NTT kernels live in luxfi/lattice/v7/gpu/ (Metal / CUDA / cpu pure-Go fallback). Corona's MaybeRegister gives those kernels access to the rings via the lattice/gpu registry.

Decomplecting: this is correct. NTT is owned by lattice; the threshold-signature math sits one layer up. Corona MUST NOT re-implement NTT.

§3.2 The gpu/ default leaves single-poly on CPU

Per the documented threshold gating in gpu/gpu.go doc comment: "Single-poly Metal NTT on Apple M1 Max is slower than the pure-Go ring.SubRing.NTT for every measured N up to 16384 ... Engaging single-poly GPU dispatch at corona's production N=256 regresses wall-clock by roughly 4x".

The defaultThreshold = 1024 keeps Corona's N=256 on the CPU path. The GPU dispatch is armed (rings registered) but the single-poly threshold gate prevents engagement. This is correct for the current single-poly dispatch contract.

Where GPU is a win: BATCHED dispatch (many polynomials in one kernel launch). The dispatcher is in place for any future luxfi/accel-style batch path that bypasses ring.NTT and calls lattice/gpu.MontgomeryNTTContext.Forward(data, batch) with batch > 1. That path is faster on GPU even at small N.

§3.3 dkg2_parallel.go is goroutine fan-out, not GPU

dkg2/dkg2_gpu.go and dkg2_parallel.go are goroutine fan-out across the parallel axes of the Pedersen-DKG Round 1 hot path (commit-vector + Horner share evaluation). The file naming was honestly relabelled in commit 72812a1 (2026-05-31) — "rename gpu fan-out files to dkg2_parallel.go (honest labelling)" — explicitly NOT a GPU dispatch, just CPU-side goroutines. The top-of-file doc comment says: "This is not a GPU dispatch — real GPU NTT for the underlying ring math lives in luxfi/lattice/v7/gpu and is reached via the consensus engine accel pipeline."

This is honest framing. The package's dkg2GPUEnabled flag is a goroutine-fan-out toggle, not a GPU toggle.

~/work/lux-private/gpu-kernels/ops/mpcvm/ contains a ceremony-state-machine GPU port (CUDA / HIP / Metal / Vulkan / WGSL) for MPCVM. The file names there carry the legacy "Corona" identifier:

ops/mpcvm/cuda/mpcvm_Corona.cu
ops/mpcvm/hip/mpcvm_Corona.cu
ops/mpcvm/metal/mpcvm_Corona.metal
ops/mpcvm/vulkan/mpcvm_Corona.comp
ops/mpcvm/wgsl/mpcvm_Corona.wgsl
ops/crypto/Corona/cuda/

These are NOT Corona's Module-LWE math — they're the MPCVM ceremony-state-machine kernel (Corona DKG ceremony op + Corona sign ceremony op as a generic "lattice ceremony" workflow). The real lattice arithmetic (NTT, Gaussian sampling, MLWE matrix multiplication) lives in luxcpp/lattice and is consumed via function call from these kernels.

This audit's scope is corona/ only — I am NOT renaming the sister-repo files. Cross-repo TODO:

  • lux-private/gpu-kernels/ops/mpcvm/{cuda,hip,metal,vulkan,wgsl}/mpcvm_Corona.* -> mpcvm_corona.*
  • lux-private/gpu-kernels/ops/crypto/Corona/ -> ops/crypto/corona/
  • Update op.yaml, mpcvm_kernels_common.cuh, and any host-side vtbl registrations.

Finding D3-1 (INFORMATIONAL): GPU kernel rename is a sister-repo work item; tracking in this audit so the cross-link is recorded.

§3.5 What's GPU-accelerated TODAY

Path Backend Acceleration kind
lattice.ring.SubRing.NTT (when registered + threshold met) lattice/v7/gpu Metal / CUDA Single-poly NTT (CURRENTLY: regression on M1 Max at N=256; not engaged by default)
dkg2.Round1WithSeed Step 4 + 5 Go goroutines CPU-side fan-out across t commits and n recipients
Future: batched NTT on lattice/gpu lattice/v7/gpu Metal / CUDA Batched-poly NTT (faster than CPU even at N=256; armed via RegisterRing but no Corona caller exercises batch > 1 yet)
MPCVM ceremony-state-machine (sister repo) CUDA / HIP / Metal / Vulkan / WGSL Ceremony op dispatch; calls into luxcpp/lattice for the actual NTT

§3.6 No further GPU findings

Corona's GPU posture is correct: shim to lattice/v7/gpu, conservative default threshold, honest labelling of goroutine fan-out vs. true GPU.


§4 D4 — Corona -> corona rename hygiene

§4.1 Pre-audit state (16 files found)

corona/CHANGELOG.md             - historical
corona/CRYPTOGRAPHER-SIGN-OFF.md - historical
corona/LLM.md                    - historical
corona/Makefile                  - LIVE binary name
corona/Dockerfile                - LIVE user / binary name
corona/.github/workflows/ci.yml  - LIVE bin output + artifact
corona/.golangci.yml             - LIVE goimports local-prefix
corona/docs/{7 mdx files}        - LIVE doc site, wrong narrative
corona/docs/app/layout.tsx       - LIVE doc site title
corona/docs/package.json         - LIVE doc site package name
corona/docs/pnpm-lock.yaml       - false positive (sha512 collision)

§4.2 Sweep actions taken

Renamed (LIVE files):

  • Makefile: BINARY_NAME=Corona -> corona; banner + docker tag; help text "Corona - Post-Quantum Threshold Signature Scheme" -> "Corona - Post-Quantum Ring-LWE Threshold Signature Scheme".
  • Dockerfile: addgroup -g 1000 Corona -> corona; binary path + entrypoint.
  • .github/workflows/ci.yml: bin/Corona -> bin/corona, artifact name Corona-${runner.os}-${arch} -> corona-${runner.os}-${arch}, release output name pattern.
  • .golangci.yml: local-prefixes: Corona -> local-prefixes: github.com/luxfi/corona (full module path is more correct than the bare token).

Dropped (off-narrative doc site):

  • docs/{app,content,lib,out,public,.source}
  • docs/{mdx-components.tsx,next-env.d.ts,next.config.mjs, package.json,pnpm-lock.yaml,postcss.config.js, source.config.ts,tsconfig.json,.gitignore}

The fumadocs Next.js site at docs/ was 3057 lines of MDX that framed Corona as a privacy ring-signature scheme with linkable Schnorr signatures, hash-to-curve, and "ring signatures for transaction privacy". That is NOT what Corona is — Corona is a 2-round Module-LWE threshold signature scheme (Boschini et al. 2024/1113). The docs referenced a non-existent github.com/luxfi/Corona Go module and would have shipped a misleading product to anyone reading them. They are gone.

Kept (docs/mptc/): the authoritative submission docs at docs/mptc/{threat-model, design-decisions, evaluation, family-architecture, ietf-draft-skeleton, nist-mptc-category}.md remain (and this audit adds tee-integration.md to the same directory).

Kept (historical references):

  • CHANGELOG.md line 418 — documents the v0.4.x Corona purge.
  • LLM.md lines 5354 — pins the historical commit SHAs of the v0.4.x purge.
  • CRYPTOGRAPHER-SIGN-OFF.md line 181 — gate "No stale branding: Corona -> Corona purge complete".

These are correct as historical context — they document that the prior rename happened and where it landed. They are NOT calling the live product Corona.

§4.3 Cross-repo Corona references (out-of-scope)

Found in sibling repos:

luxfi/threshold (40+ references):

  • protocols/Corona/ — wrapper around luxfi/corona. The consumer-side adapter still carries the legacy package name.
  • protocols/lss/factory_Corona_{prod,research}.go — LSS adapter shims.
  • pkg/thresholdd/{server,runner,doc,pulsar,sign_ctx_test, tee_dispatcher_test}.go — scheme map key "Corona", documentation strings.
  • protocols/lss/adapters/{Corona.go, xrpl_address_test.go} — LSS-side toy Corona adapter (research-only).

luxfi/node — Dockerfile.multichain may reference the old name; legacy doc HTML.

lux-private/gpu-kernels — kernel file names at mpcvm/ and ops/crypto/Corona/ (see §3.4).

These are sister-repo work items. Per the audit scope rule ("stay strictly inside /Users/z/work/lux/corona"), they are inventoried here but not modified.

Finding D4-1 (INFORMATIONAL): Track cross-repo rename sweeps for:

  • luxfi/threshold — rename protocols/Corona/ -> protocols/corona/ (the directory name + scheme map key
    • thresholdd dispatcher); preserve a deprecated alias for one release to give external callers a migration window.
  • luxfi/node — Dockerfile.multichain check.
  • lux-private/gpu-kernels — see §3.4.

§4.4 Module path github.com/luxfi/corona

The canonical Go module path is already github.com/luxfi/corona (see go.mod); there is no orphaned luxfi/Corona Go module on GitHub. The historical naming is purely cosmetic at this point (file paths, binary names, doc site title) and the consumer-side rename in luxfi/threshold is the last load-bearing migration.


§5 Cross-check against existing audit gates

From CRYPTOGRAPHER-SIGN-OFF.md (v0.7.0 sign-off):

Gate Status this audit
GATE-1 (EC theory shells) CLOSED (carryover; this audit did not re-verify EC compilation since easycrypt is not on this host; the scripts/check-high-assurance.sh smoke run is the load-bearing gate).
GATE-2 (Lean <-> EC bridge) CLOSED (carryover; 5 axiom citations verified via scripts/check-lean-bridge.sh per AUDIT-2026-05).
GATE-3a (dudect harness wired) CLOSED (carryover).
GATE-3b (10^9-sample dudect) OPEN (v0.8.0 roadmap; not addressed by this audit).
GATE-4 (external audit) OPEN (v0.8.0 roadmap; this audit is internal cryptographer-agent review, NOT the external audit).
GATE-5 (Jasmin extraction byte-walk) OPEN (v0.8.0 roadmap).

This audit adds three new tracking items:

New tracking Severity Target
D1-2: sid is 64-bit not 32-byte (threat-model overstates) MEDIUM (doc tightening) v0.7.6
D1-3: signing-round equivocation evidence not extracted as Complaint MINOR v0.7.6
D2-1: gpu.MaybeRegisterAttested not implemented MINOR v0.7.6
D3-1 / D4-1: cross-repo Corona -> corona renames (gpu-kernels, threshold) INFORMATIONAL sister-repo audits

§6 Build + test status (verification this audit conducted)

  • GOWORK=off go build ./... clean (verified 2026-06-02 post-edits).
  • git diff summary: 5 files edited in-place (Makefile, Dockerfile, ci.yml, .golangci.yml, plus the docs/mptc/tee-integration.md + AUDIT-2026-06.md additions); docs/{app,content,lib,out,public, .source,mdx-components.tsx,next-env.d.ts,next.config.mjs, package.json,pnpm-lock.yaml,postcss.config.js,source.config.ts, tsconfig.json,.gitignore} removed.
  • KATs unchanged: no Go code path was edited; FIPS-TRACEABILITY byte-equality contract is preserved (the kernel had no changes).
  • v1.x ABI unchanged: no public Go API was modified.
  • Constant-time discipline preserved: no crypto/subtle paths touched; CONSTANT-TIME-REVIEW.md remains authoritative.

§7 Conclusion

The audit closes the four scope dimensions:

  1. D1 Permissionless safety: PASSED with two minor open items (D1-2, D1-3) for v0.7.6 — doc tightening of sid entropy claim and signing-round equivocation evidence as a Complaint. Rogue- key NOT APPLICABLE. Adaptive corruption: paper-cited only; GATE-4 audit target.

  2. D2 TEE integration: WAS A GAP. CLOSED by this audit via docs/mptc/tee-integration.md — full per-platform spec for SEV-SNP / NVIDIA CC / TDX / Apple SEP, with the decomplecting rule that Corona's kernel has ZERO TEE awareness. ONE optional plumbing function (gpu.MaybeRegisterAttested) tracked for v0.7.6.

  3. D3 GPU acceleration inventory: corona/gpu is a thin shim over lattice/v7/gpu; goroutine fan-out is honestly labelled as such (post commit 72812a1); MPCVM kernel naming in lux-private/gpu-kernels is a sister-repo rename TODO.

  4. D4 Rename hygiene: in-repo sweep COMPLETE (Makefile, Dockerfile, CI, golangci, off-narrative docs/* dropped). Cross-repo (threshold, gpu-kernels, node) tracked for sister audits.

Production deployment posture (unchanged from v0.7.5): APPROVED WITH ROADMAP GATES for public-permissionless deployment as a Module-LWE threshold signature primitive in Lux Quasar consensus, with the v0.8.0 GATE-3b + GATE-4 + GATE-5 carryovers remaining as research-track work. The TEE integration spec landed by this audit closes the operational-hardening gap that was previously a one-liner in the deployment runbook.

— Cryptographer, 2026-06-02


Document metadata

  • Name: AUDIT-2026-06.md
  • Version: v0.1
  • Date: 2026-06-02
  • Mirrors structure of: AUDIT-2026-05.md
  • Auditor: cryptographer agent (Hanzo Dev, internal review)
  • Audit subject: github.com/luxfi/corona at main post-39de1ed (latest tag v0.7.5)
  • Companion docs added: docs/mptc/tee-integration.md
  • Companion docs removed: 16 files of docs/{app,content,lib,...} fumadocs site (off-narrative privacy-ring-sig framing)