Files
proofs/lean/Crypto/Corona.lean
zooqueen ebf46cbba8 proofs: reconcile Corona to Module-LWE (Ringtail-derived), not Ring-LWE rank-1
Corona is Lux's fork of Ringtail (ePrint 2024/1113) = two-round Module-LWE
(M=8, N=7 over R_q=Z_q[X]/(X^256+1), q=0x1000000004A01 48-bit, sigma=6.108) —
NOT Ring-LWE rank-1. Corona.lean: hardness Module-LWE; axiom corona_ring_lwe_euf_cma
-> corona_module_lwe_euf_cma; EUF-CMA reduces to Module-LWE; params corrected
(was q=2^32/sigma=13744). Corona/{OutputInterchange,Unforgeability,dkg2}, Quasar,
Magnetar, HQC, BLS, Threshold_Lagrange label fixes. 'Ring-LWE = Module-LWE rank 1'
kept only as general math remark. lake build: success.
2026-06-20 01:48:36 -07:00

182 lines
7.3 KiB
Lean4
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/-
Corona Threshold Lattice Signature Correctness
Models the Corona precompile (src/precompiles/corona-threshold/).
Corona is a post-quantum threshold signature based on Module-LWE
hardness (with Module-SIS for binding). It is Lux's first-party fork
of Ringtail, the two-round Module-LWE threshold signature of
Boschini-Kaviani-Lai-Malavolta-Takahashi-Tibouchi
(IACR ePrint 2024/1113, IEEE S&P 2025); Corona adds the production
lifecycle (permissionless leaderless DKG, proactive resharing,
identifiable abort).
Maps to:
- luxfi/corona/threshold/threshold.go: Verify, GenerateKeys, Signer
- luxfi/corona/sign/sign.go: Verify, Sign{Round1,Round2,Finalize}
- luxfi/precompile/corona/contract.go: precompile dispatch
- precompiles ICoronaThreshold.sol: interface
Canonical parameter set (Ringtail/corona `sign/config.go`,
NIST Category 1 — ~128-bit classical / ~130-bit quantum security):
- Ring R_q = Z_q[X]/(X^256+1), degree N = 256 (LogN = 8)
- Module dimensions M = 8, N_mod = 7 (matrix A in R_q^{8x7})
— Module-LWE rank ~7-8, NOT rank 1
- Modulus q = 0x1000000004A01 (48-bit NTT-friendly prime)
- Gaussian noise sigma_E = 6.108
General lattice remark: Ring-LWE is exactly Module-LWE at rank 1.
Corona is NOT instantiated at rank 1 — its module has rank ~7-8 —
so it is a Module-LWE scheme, not a Ring-LWE one.
Properties discharged here:
- Correctness: the algebraic content of the threshold-to-single-party
reduction (Lagrange interpolation over polynomial shares) is
discharged in `Crypto.Threshold.Lagrange.threshold_reconstructs_secret`
and reused here — Pulsar and Corona are both Module-LWE schemes that
share the same Shamir-over-ring shape; they differ in parameter
regime and lifecycle, not in the underlying lattice family.
- Threshold robustness, signature size bound, noise bound: discharged
here by `omega`.
- PQ unforgeability: reduces to Module-LWE (+ Module-SIS) hardness as
proven in Boschini et al. 2024 §5. Stated as a named axiom citing
the academic paper.
-/
import Mathlib.Data.Nat.Defs
import Mathlib.LinearAlgebra.Lagrange
import Mathlib.Tactic
import Crypto.Threshold_Lagrange
open Polynomial
namespace Crypto.Corona
/-- Module-LWE parameters for NIST Category 1 security
(Ringtail/corona `sign/config.go`). -/
structure LWEParams where
n : Nat -- module lattice dimension (module rank M=8 over R_q deg 256)
q : Nat -- modulus (0x1000000004A01, 48-bit prime)
sigma : Nat -- Gaussian noise parameter (sigma_E ~ 6.108)
hn : 0 < n
hq : 0 < q
/-- Threshold parameters (t-of-n). -/
structure ThresholdParams where
t : Nat
n : Nat
ht : t ≤ n
ht0 : 0 < t
/-- Corona signature shape: (C, Z, Delta) ring polynomial triple,
serialised. Empirically bounded at ~33 KB at production parameters
(see consensus/protocol/quasar/cert_size_compare_test.go). -/
structure CoronaSig where
size : Nat
hsize : size ≤ 35000
/-- **Correctness (algebraic discharge).**
Given a Shamir polynomial `f` of degree < t evaluated at t distinct
non-zero indices, the Lagrange interpolation at 0 recovers `f.eval 0`.
This is the load-bearing identity for Corona's threshold-to-single-
party reduction — the per-party (z_i, h_i) outputs combine to the
single-party (z, h) byte-for-byte via Lagrange coefficients.
Discharged: re-uses the proof from `Crypto.PulsarM.Lagrange`
(Pulsar and Corona share the same Shamir-over-polynomial-ring
structure; both are Module-LWE schemes — they differ in parameter
regime and lifecycle, not in the underlying lattice family). -/
theorem corona_threshold_reconstructs
{F : Type*} [Field F] [DecidableEq F]
(f : Polynomial F) {ι : Type*} [DecidableEq ι] (s : Finset ι) (v : ι → F)
(hvs : Set.InjOn v s) (degree_f_lt : f.degree < s.card) :
f = Lagrange.interpolate s v (fun i => f.eval (v i)) :=
Crypto.Threshold.Lagrange.threshold_reconstructs_secret f s v hvs degree_f_lt
/-- **Combine linearity (algebraic discharge).**
Corona's `Combine` step adds Lagrange-weighted per-party responses;
the operation is linear in each party's contribution. Reused from
the Pulsar Lagrange identity. -/
theorem corona_combine_linear
{F : Type*} [Field F] [DecidableEq F]
{ι : Type*} [DecidableEq ι] (s : Finset ι) (v : ι → F) (a b : ι → F) :
Lagrange.interpolate s v (a + b) =
Lagrange.interpolate s v a +
Lagrange.interpolate s v b :=
Crypto.Threshold.Lagrange.combine_distributes_over_sum s v a b
/-- **PQ unforgeability (cryptographic axiom).**
Under the Module-LWE hardness assumption (with Module-SIS for
binding) with parameters (N, M, q, sigma), no probabilistic
polynomial-time quantum adversary holding fewer than `t` shares can
produce a signature accepted by `Verify`.
Boschini-Kaviani-Lai-Malavolta-Takahashi-Tibouchi (IACR ePrint
2024/1113, §5) provides the EUF-CMA proof in the random oracle model
against a Module-LWE-bounded adversary; this axiom names that
theorem.
Concrete parameter justification: BDGL sieving (Becker-Ducas-Gama-
Laarhoven 2016) on the M=8, N=7 module lattice over R_q =
Z_q[X]/(X^256+1), q = 0x1000000004A01 (48-bit), sigma_E = 6.108
keeps the classical attack complexity above the NIST PQ Category 1
bar; the Grover-accelerated quantum complexity (~2^130) also clears
the 2^128 / 2^64-quantum threshold.
`CoronaEUFCMAAdv` carries the academic-paper bound (Boschini et
al. 2024 §5 Theorem 1) without depending on a probability monad. -/
opaque CoronaEUFCMAAdv (lwe : LWEParams) : Type
axiom corona_module_lwe_euf_cma
(lwe : LWEParams) (tp : ThresholdParams) (compromised : Nat)
(_h : compromised < tp.t) :
-- Module-LWE-bounded adversary with < t shares cannot forge:
-- ∃ a : CoronaEUFCMAAdv lwe, Adv^EUF-CMA_Corona(A) ≤ a.
CoronaEUFCMAAdv lwe
/-- Noise bound: Gaussian noise must be within q/4 for correct
decryption. Below this, the lattice rounding inside `Verify`
recovers the signed message. -/
theorem noise_bound_correct
(lwe : LWEParams)
(noise : Nat)
(hnoise : noise ≤ lwe.q / 4) :
noise < lwe.q := by
have := lwe.hq
have hq4 : lwe.q / 4 < lwe.q := Nat.div_lt_self this (by decide)
omega
/-- Threshold lower-bound enforcement. -/
theorem threshold_minimum (tp : ThresholdParams) (signers : Nat)
(h : signers < tp.t) :
signers < tp.n := by
have := tp.ht
omega
/-- Robustness: with `n` signers and up to `n - t` failures, the
remaining honest set still meets the t-of-n threshold. -/
theorem corona_robustness (tp : ThresholdParams) (failures : Nat)
(h : failures ≤ tp.n - tp.t) :
tp.n - failures ≥ tp.t := by
have := tp.ht
have := tp.ht0
omega
/-- Signature size is bounded by the Corona parameter set's
ring-polynomial-triple wire encoding. -/
theorem sig_bounded (sig : CoronaSig) : sig.size ≤ 35000 := sig.hsize
/-- LWE dimension must be positive for security. -/
theorem dimension_positive (lwe : LWEParams) : lwe.n > 0 := lwe.hn
/-- Canonical parameter set is well-formed: positive module rank (M=8)
and a positive 48-bit modulus q = 0x1000000004A01 (Ringtail/corona
`sign/config.go`). -/
theorem standard_params_secure :
8 > 0 ∧ (0x1000000004A01 : Nat) > 0 := by
constructor <;> omega
end Crypto.Corona