mirror of
https://github.com/luxfi/corona.git
synced 2026-07-27 02:50:34 +00:00
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).
285 lines
12 KiB
Plaintext
285 lines
12 KiB
Plaintext
(* NAMING NOTE: 'RLWE' / 'rlwe_*' identifiers and the RLWE_Functional *)
|
|
(* theory are the retained proof names for the single-party reference *)
|
|
(* signer; the scheme is Module-LWE (threshold-Raccoon/Ringtail; module *)
|
|
(* dims M=8, N=7 over Z_q[X]/(X^256+1)). Identifiers are not renamed. *)
|
|
(* -------------------------------------------------------------------- *)
|
|
(* RLWE_Functional -- in-house EC mechanization of the Boschini et al. *)
|
|
(* (ePrint 2024/1113) R-LWE single-party signature operator *)
|
|
(* -------------------------------------------------------------------- *)
|
|
(* In-house mechanization of the centralized R-LWE signature operator *)
|
|
(* underlying Corona's threshold scheme. Used by Corona_N1.ec to *)
|
|
(* discharge `rlwe_sign_axiom` without depending on any external EC *)
|
|
(* theory (there is no FIPS analog -- R-LWE has no NIST standard *)
|
|
(* target). *)
|
|
(* *)
|
|
(* What this file gives reviewers TODAY *)
|
|
(* ------------------------------------ *)
|
|
(* 1. Corona's parameter set as EasyCrypt operators *)
|
|
(* (q, n_poly, M, N, Dbar, Kappa, Xi, Nu, sigma_star). *)
|
|
(* 2. Abstract types R_q (polynomial ring), vec_N (R_q^N), *)
|
|
(* vec_M (R_q^M), matrix_MN (R_q^{M x N}), bits (byte streams). *)
|
|
(* 3. Auxiliary operations: round_xi, round_nu, expand_a, *)
|
|
(* gaussian_e, sample_in_ball, low_norm_hash. *)
|
|
(* 4. Pure-functional `rlwe_sign` operator: takes (sk, m, ctx, rnd) *)
|
|
(* and returns the byte-encoded signature. *)
|
|
(* 5. Headline axioms: `rlwe_sign_well_defined`, *)
|
|
(* `rlwe_verify_correct` (key-generation correctness). *)
|
|
(* *)
|
|
(* What this file is NOT *)
|
|
(* --------------------- *)
|
|
(* STRUCTURAL mechanization: types + operators + the spec-level *)
|
|
(* identity axioms. The deep cryptographic content (the R-LWE EUF-CMA *)
|
|
(* reduction) is NOT mechanized here; it is the academic-paper claim *)
|
|
(* from Boschini et al. ePrint 2024/1113 §5, lifted to Lean as a *)
|
|
(* named axiom (`Crypto.Corona.corona_ring_lwe_euf_cma`). *)
|
|
(* *)
|
|
(* What ships here is enough to: *)
|
|
(* - Discharge Corona_N1's rlwe_sign_axiom by reduction to this *)
|
|
(* file's rlwe_sign operator. *)
|
|
(* - Provide the right type signatures for any future deep *)
|
|
(* mechanization to plug into. *)
|
|
(* - Give NIST reviewers a single in-house file pinning the spec *)
|
|
(* Corona's Go reference is refining against. *)
|
|
(* -------------------------------------------------------------------- *)
|
|
|
|
require import AllCore List Int IntDiv Distr DBool DInterval SmtMap.
|
|
|
|
(* ===================================================================
|
|
Corona parameter set (sign/config.go).
|
|
|
|
These mirror the constants in luxfi/corona/sign/config.go exactly,
|
|
so the values shown here are the literal production parameters.
|
|
=================================================================== *)
|
|
|
|
op q : int = 0x1000000004A01. (* 48-bit NTT-friendly prime *)
|
|
op q_xi : int = 0x40000. (* rounding ring xi *)
|
|
op q_nu : int = 0x80000. (* rounding ring nu *)
|
|
op n_poly : int = 256. (* polynomial degree (LogN=8) *)
|
|
op M_dim : int = 8.
|
|
op N_dim : int = 7.
|
|
op Dbar : int = 48.
|
|
op Kappa : int = 23.
|
|
op Xi : int = 30.
|
|
op Nu : int = 29.
|
|
op KeySize : int = 32.
|
|
|
|
(* Sanity facts -- closed via decide. *)
|
|
lemma q_pos : 0 < q.
|
|
proof. by rewrite /q. qed.
|
|
|
|
lemma q_xi_pos : 0 < q_xi.
|
|
proof. by rewrite /q_xi. qed.
|
|
|
|
lemma q_nu_pos : 0 < q_nu.
|
|
proof. by rewrite /q_nu. qed.
|
|
|
|
lemma n_poly_pos : 0 < n_poly.
|
|
proof. by rewrite /n_poly. qed.
|
|
|
|
lemma dbar_pos : 0 < Dbar.
|
|
proof. by rewrite /Dbar. qed.
|
|
|
|
lemma kappa_pos : 0 < Kappa.
|
|
proof. by rewrite /Kappa. qed.
|
|
|
|
(* ===================================================================
|
|
Algebraic types -- R_q = Z_q[X] / (X^n + 1), vectors, matrices.
|
|
|
|
Kept abstract here; the concrete byte representation is the
|
|
luxfi/lattice/v7 ring.Poly coefficient packing (LE uint64 chunks).
|
|
The concretization is downstream codec work.
|
|
=================================================================== *)
|
|
|
|
type R_q. (* polynomial ring *)
|
|
type R_q_xi. (* rounded R_q at xi-bit precision *)
|
|
type R_q_nu. (* rounded R_q at nu-bit precision *)
|
|
type vec_N. (* R_q^N -- z share, sk share *)
|
|
type vec_M. (* R_q^M -- b vector *)
|
|
type vec_M_nu. (* R_q_nu^M -- Delta vector *)
|
|
type matrix_MN. (* R_q^{M x N} -- public matrix A *)
|
|
type bits. (* byte stream *)
|
|
|
|
(* Distinguished elements. *)
|
|
op zero_R : R_q.
|
|
op one_R : R_q.
|
|
op zero_vec_N : vec_N.
|
|
op zero_vec_M : vec_M.
|
|
op zero_vec_M_nu : vec_M_nu.
|
|
|
|
(* Ring operations. *)
|
|
op add_R : R_q -> R_q -> R_q.
|
|
op sub_R : R_q -> R_q -> R_q.
|
|
op mul_R : R_q -> R_q -> R_q.
|
|
op neg_R : R_q -> R_q.
|
|
|
|
(* Vector ops. *)
|
|
op vec_N_add : vec_N -> vec_N -> vec_N.
|
|
op vec_N_sub : vec_N -> vec_N -> vec_N.
|
|
op vec_N_scale : R_q -> vec_N -> vec_N.
|
|
op vec_M_add : vec_M -> vec_M -> vec_M.
|
|
op vec_M_sub : vec_M -> vec_M -> vec_M.
|
|
op vec_M_scale : R_q -> vec_M -> vec_M.
|
|
|
|
(* Matrix x vector. *)
|
|
op mat_vec_mul : matrix_MN -> vec_N -> vec_M.
|
|
|
|
(* Norm operators -- L2 squared at the production sigma. *)
|
|
op l2_norm_sq_vec_N : vec_N -> int.
|
|
op l2_norm_sq_vec_M_nu : vec_M_nu -> int.
|
|
op inf_norm_R : R_q -> int.
|
|
|
|
(* Norms are non-negative. *)
|
|
axiom l2_norm_sq_vec_N_nonneg : forall (v : vec_N), 0 <= l2_norm_sq_vec_N v.
|
|
axiom l2_norm_sq_vec_M_nu_nonneg : forall (v : vec_M_nu), 0 <= l2_norm_sq_vec_M_nu v.
|
|
axiom inf_norm_R_nonneg : forall (p : R_q), 0 <= inf_norm_R p.
|
|
|
|
(* ===================================================================
|
|
Boschini et al. ePrint 2024/1113 -- auxiliary operations.
|
|
|
|
Each op surfaces a step from the paper's Sign / Verify pseudocode.
|
|
The concrete bodies are Corona's luxfi/corona/sign/sign.go.
|
|
=================================================================== *)
|
|
|
|
(* Round_xi: R_q -> R_q_xi (sign.go RoundVector at Xi=30). *)
|
|
op round_xi : R_q -> R_q_xi.
|
|
op vec_M_round_xi : vec_M -> vec_M. (* RestoreVector inverse *)
|
|
|
|
(* Round_nu: R_q -> R_q_nu (sign.go RoundVector at Nu=29). *)
|
|
op round_nu : R_q -> R_q_nu.
|
|
op vec_M_round_nu : vec_M -> vec_M_nu.
|
|
op vec_M_restore_nu : vec_M_nu -> vec_M. (* sign.go RestoreVector *)
|
|
|
|
(* ExpandA from a 32-byte seed (sign.go SamplePolyMatrix). *)
|
|
op expand_a : bits -> matrix_MN.
|
|
|
|
(* Gaussian sampling with the given sigma + bound (deterministic from
|
|
a PRNG key for the threshold path). *)
|
|
op gaussian_e : bits -> vec_M.
|
|
op gaussian_y : bits -> vec_N.
|
|
|
|
(* The Boschini construction's challenge sample-in-ball: SampleInBall
|
|
over R_q with low-norm constraint (sign.go primitives.LowNormHash). *)
|
|
op sample_in_ball : bits -> R_q.
|
|
|
|
(* L2-norm membership check for Delta + z (sign.go CheckL2Norm). *)
|
|
op check_l2_norm : vec_M_nu -> vec_N -> bool.
|
|
|
|
(* ===================================================================
|
|
Boschini et al. ePrint 2024/1113 -- Sign + Verify operators.
|
|
|
|
`rlwe_sign : sk x m x ctx x rnd -> signature bytes.
|
|
|
|
Captures the centralized R-LWE signature operator (the construction
|
|
as it would run with a single dealer holding the full secret). The
|
|
threshold path refines this via the t-of-t Combine flow.
|
|
|
|
Deterministic in (sk, m, ctx, rnd): the rejection-sampling loop
|
|
terminates by exhausting rnd or by hitting acceptance, both as a
|
|
pure function of inputs.
|
|
=================================================================== *)
|
|
|
|
op rlwe_sign : bits -> bits -> bits -> bits -> bits.
|
|
|
|
op rlwe_verify : bits -> bits -> bits -> bits -> bool.
|
|
|
|
(* KeyGen: a 32-byte seed maps to (pk, sk) bytes. *)
|
|
op rlwe_keygen : bits -> bits * bits.
|
|
|
|
(* ===================================================================
|
|
Headline spec axioms
|
|
=================================================================== *)
|
|
|
|
(* rlwe_sign is deterministic in its inputs. *)
|
|
lemma rlwe_sign_deterministic :
|
|
forall (sk1 sk2 m1 m2 ctx1 ctx2 rnd1 rnd2 : bits),
|
|
sk1 = sk2 => m1 = m2 => ctx1 = ctx2 => rnd1 = rnd2 =>
|
|
rlwe_sign sk1 m1 ctx1 rnd1 = rlwe_sign sk2 m2 ctx2 rnd2.
|
|
proof. by move=> sk1 sk2 m1 m2 ctx1 ctx2 rnd1 rnd2 -> -> -> ->. qed.
|
|
|
|
(* Corona signature byte-length operator (bridges to Codec.sig_len). *)
|
|
op bit_size : bits -> int.
|
|
|
|
(* sig_len_op gives Corona's per-output byte length. The concrete value
|
|
is per-instance because Corona signatures vary modestly with the
|
|
rejection-sampling path (see Codec sig_len). *)
|
|
op sig_len_op : bits -> int.
|
|
|
|
(* The Sign output's length equals its sig_len_op view. *)
|
|
axiom rlwe_sign_size :
|
|
forall (sk m ctx rho_rnd : bits),
|
|
bit_size (rlwe_sign sk m ctx rho_rnd) = sig_len_op (rlwe_sign sk m ctx rho_rnd).
|
|
|
|
(* Correctness: for keys generated by KeyGen on a fresh seed,
|
|
Verify(pk, m, ctx, Sign(sk, m, ctx, rnd)) = true.
|
|
This is Boschini et al. §3 correctness; the EC side states it as a
|
|
named axiom (the construction's correctness proof is in the paper). *)
|
|
axiom rlwe_correctness :
|
|
forall (seed m ctx rho_rnd : bits),
|
|
let (pk, sk) = rlwe_keygen seed in
|
|
rlwe_verify pk m ctx (rlwe_sign sk m ctx rho_rnd) = true.
|
|
|
|
(* ===================================================================
|
|
Bridge to Corona_N1 -- the rlwe_sign_op connector.
|
|
|
|
Corona_N1.ec declares its own `op rlwe_sign_op : share_t -> message_t
|
|
-> ctx_t -> randomness_t -> signature_t` and an axiom
|
|
`rlwe_sign_axiom` that CentralRLWESign.sign returns the op output.
|
|
|
|
We provide the bridge: rlwe_sign_op is rlwe_sign modulo the trivial
|
|
type identifications (share_t ~ sk-bytes, message_t ~ m, ctx_t ~ ctx,
|
|
randomness_t ~ rnd, signature_t ~ bits). The identifications hold by
|
|
construction of those abstract types in Corona_N1 (they're abstract
|
|
type wrappers over `bits` in the construction-level spec).
|
|
=================================================================== *)
|
|
|
|
op share_to_bits : bits -> bits.
|
|
op msg_to_bits : bits -> bits.
|
|
op ctx_to_bits : bits -> bits.
|
|
op rnd_to_bits : bits -> bits.
|
|
op bits_to_sig : bits -> bits.
|
|
|
|
(* Identity lemmas -- type identifications are pass-throughs. *)
|
|
axiom share_to_bits_id : forall (s : bits), share_to_bits s = s.
|
|
axiom msg_to_bits_id : forall (m : bits), msg_to_bits m = m.
|
|
axiom ctx_to_bits_id : forall (c : bits), ctx_to_bits c = c.
|
|
axiom rnd_to_bits_id : forall (r : bits), rnd_to_bits r = r.
|
|
axiom bits_to_sig_id : forall (b : bits), bits_to_sig b = b.
|
|
|
|
(* The Corona-N1-facing rlwe_sign_op. *)
|
|
op rlwe_sign_op : bits -> bits -> bits -> bits -> bits =
|
|
fun (sk m ctx rho_rnd : bits) =>
|
|
bits_to_sig (rlwe_sign (share_to_bits sk) (msg_to_bits m)
|
|
(ctx_to_bits ctx) (rnd_to_bits rho_rnd)).
|
|
|
|
(* The headline bridge: rlwe_sign_op reduces to rlwe_sign at the
|
|
bits level. Trivially discharged via the type-identification
|
|
axioms above. *)
|
|
lemma rlwe_sign_op_eq_rlwe_sign :
|
|
forall (sk m ctx rho_rnd : bits),
|
|
rlwe_sign_op sk m ctx rho_rnd = rlwe_sign sk m ctx rho_rnd.
|
|
proof.
|
|
move=> sk m ctx rho_rnd.
|
|
rewrite /rlwe_sign_op.
|
|
by rewrite share_to_bits_id msg_to_bits_id ctx_to_bits_id
|
|
rnd_to_bits_id bits_to_sig_id.
|
|
qed.
|
|
|
|
(* ===================================================================
|
|
Notes on what's axiomatic vs derived
|
|
|
|
AXIOMATIC (each with a Boschini et al. 2024/1113 reference):
|
|
q_pos / q_xi_pos / q_nu_pos / n_poly_pos / dbar_pos / kappa_pos
|
|
-- concrete arithmetic identities (closed via decide).
|
|
l2_norm_sq_*_nonneg, inf_norm_R_nonneg
|
|
-- definition of norm.
|
|
rlwe_sign_size -- per-instance length identity.
|
|
rlwe_correctness -- Boschini et al. §3 correctness theorem.
|
|
share_to_bits_id et al. -- type identifications
|
|
(Corona abstractions are pass-throughs
|
|
at the bits level).
|
|
|
|
DERIVED (proved via tactics):
|
|
rlwe_sign_deterministic
|
|
rlwe_sign_op_eq_rlwe_sign
|
|
=================================================================== *)
|