Files

230 lines
7.2 KiB
Go

// Copyright (c) 2026 Lux Industries Inc.
// SPDX-License-Identifier: BSD-3-Clause
// Package params is the single Lux registry of cryptographic parameter
// identifiers. Every other package in luxfi/math (and downstream
// luxfi/lattice, luxfi/pulsar, luxfi/fhe, luxfi/lens) keys off these
// IDs; every cross-runtime KAT carries them; every backend dispatch
// uses them to route work.
//
// LP-107 §"Parameter registry" — the canonical motivation. There must
// be exactly one place that names "Pulsar's modulus" or
// "FHE PN10QP27 ring dimension"; this package is that place.
//
// IDs are stable strings — wire-formatted, log-printable, KAT-keyed.
// Renaming an ID is a breaking change. New IDs append; existing IDs
// never change semantics.
package params
import "fmt"
// ModulusID names a single prime modulus.
//
// Production identifiers MUST satisfy: stable string, lowercase, hex
// representation of the modulus where applicable, prefixed by the
// owning protocol/scheme name. Validation: see Modulus.Validate.
type ModulusID string
const (
// ModPulsarQ — Pulsar/LP-073 canonical NTT-friendly prime.
// Q = 0x1000000004A01 ≈ 2^48; satisfies (Q - 1) | 2N for N = 256.
ModPulsarQ ModulusID = "pulsar-q-0x1000000004a01"
// ModNTT998 — classical NTT-friendly prime 998244353
// (used by general vector kernels and tests; not production crypto).
ModNTT998 ModulusID = "ntt-998244353"
// ModFHE_PN10QP27 — first FHE production parameter set; 27-bit Q,
// ring dimension N = 1024.
ModFHE_PN10QP27 ModulusID = "fhe-pn10qp27"
// ModFHE_PN11QP54 — second FHE production parameter set; 54-bit Q,
// ring dimension N = 2048.
ModFHE_PN11QP54 ModulusID = "fhe-pn11qp54"
// ModFHE_PN9QP28_STD128 — STD128-tagged FHE parameter set;
// ring dimension N = 512.
ModFHE_PN9QP28_STD128 ModulusID = "fhe-pn9qp28-std128"
)
// String makes ModulusID printable.
func (m ModulusID) String() string { return string(m) }
// Validate reports whether m is a known modulus identifier in this
// process. Unknown IDs are rejected — there is no implicit registration.
func (m ModulusID) Validate() error {
switch m {
case ModPulsarQ,
ModNTT998,
ModFHE_PN10QP27,
ModFHE_PN11QP54,
ModFHE_PN9QP28_STD128:
return nil
}
return fmt.Errorf("params: unknown ModulusID %q", string(m))
}
// NTTParamID names an (N, Q, root) triple for an NTT instance.
// One ModulusID may have multiple NTTParamID values (different N).
type NTTParamID string
const (
// NTTPulsarN256 — Pulsar's R_q = Z_q[X]/(X^256 + 1) at Q = ModPulsarQ.
NTTPulsarN256 NTTParamID = "pulsar-n256-q0x1000000004a01"
// NTTFHE_PN10QP27_N1024 — FHE PN10QP27 ring at N = 1024.
NTTFHE_PN10QP27_N1024 NTTParamID = "fhe-pn10qp27-n1024"
// NTTFHE_PN11QP54_N2048 — FHE PN11QP54 ring at N = 2048.
NTTFHE_PN11QP54_N2048 NTTParamID = "fhe-pn11qp54-n2048"
// NTTFHE_PN9QP28_N512 — FHE PN9QP28 ring at N = 512.
NTTFHE_PN9QP28_N512 NTTParamID = "fhe-pn9qp28-n512"
)
// String makes NTTParamID printable.
func (p NTTParamID) String() string { return string(p) }
// Validate reports whether p is a known NTT parameter identifier.
func (p NTTParamID) Validate() error {
switch p {
case NTTPulsarN256,
NTTFHE_PN10QP27_N1024,
NTTFHE_PN11QP54_N2048,
NTTFHE_PN9QP28_N512:
return nil
}
return fmt.Errorf("params: unknown NTTParamID %q", string(p))
}
// FHEParamID names a complete FHE scheme parameter set (ring + RNS
// chain + key-switching topology + bootstrap structure). Distinct
// from NTTParamID: one FHEParamID owns one or more NTTParamIDs.
type FHEParamID string
const (
FHE_PN10QP27 FHEParamID = "fhe-pn10qp27"
FHE_PN11QP54 FHEParamID = "fhe-pn11qp54"
FHE_PN9QP28_STD128 FHEParamID = "fhe-pn9qp28-std128"
)
// String makes FHEParamID printable.
func (f FHEParamID) String() string { return string(f) }
// Validate reports whether f is a known FHE parameter set.
func (f FHEParamID) Validate() error {
switch f {
case FHE_PN10QP27, FHE_PN11QP54, FHE_PN9QP28_STD128:
return nil
}
return fmt.Errorf("params: unknown FHEParamID %q", string(f))
}
// PulsarParamID names a Pulsar threshold-signature parameter set.
type PulsarParamID string
const (
// PulsarLP073 — canonical LP-073 Pulsar parameter set.
PulsarLP073 PulsarParamID = "pulsar-lp073"
)
// String makes PulsarParamID printable.
func (p PulsarParamID) String() string { return string(p) }
// Validate reports whether p is a known Pulsar parameter set.
func (p PulsarParamID) Validate() error {
if p == PulsarLP073 {
return nil
}
return fmt.Errorf("params: unknown PulsarParamID %q", string(p))
}
// HashSuiteID names a hash construction profile.
type HashSuiteID string
const (
HashPulsarSHA3 HashSuiteID = "pulsar-sha3-v1"
HashBLAKE3 HashSuiteID = "blake3-v1"
)
// String makes HashSuiteID printable.
func (h HashSuiteID) String() string { return string(h) }
// Validate reports whether h is a known hash suite.
func (h HashSuiteID) Validate() error {
switch h {
case HashPulsarSHA3, HashBLAKE3:
return nil
}
return fmt.Errorf("params: unknown HashSuiteID %q", string(h))
}
// BackendID names a math-substrate backend (CPU pure-Go, native CPU,
// CUDA, Metal, WGSL). The same NTT/Modarith/Poly contract may be
// realized by multiple backends; KATs prove they produce byte-equal
// output.
type BackendID string
const (
BackendPureGo BackendID = "pure-go"
BackendNative BackendID = "native-cpu"
BackendAVX2 BackendID = "avx2"
BackendNEON BackendID = "neon"
BackendCUDA BackendID = "cuda"
BackendMetal BackendID = "metal"
BackendWGSL BackendID = "wgsl"
)
// String makes BackendID printable.
func (b BackendID) String() string { return string(b) }
// Validate reports whether b is a known backend.
func (b BackendID) Validate() error {
switch b {
case BackendPureGo, BackendNative, BackendAVX2, BackendNEON,
BackendCUDA, BackendMetal, BackendWGSL:
return nil
}
return fmt.Errorf("params: unknown BackendID %q", string(b))
}
// KATHeader is the canonical key-set every KAT vector MUST carry.
// LP-107 §"Parameter registry" requirement: every KAT entry binds
// itself to a specific (parameter_set, modulus, backend, hash_suite,
// implementation_version) tuple so cross-runtime replay can match
// like-for-like.
type KATHeader struct {
ParameterSet string `json:"parameter_set"`
ModulusID ModulusID `json:"modulus_id"`
BackendID BackendID `json:"backend_id"`
HashSuiteID HashSuiteID `json:"hash_suite_id"`
ImplementationName string `json:"implementation_name"`
ImplementationVersion string `json:"implementation_version"`
}
// Validate ensures every required field is set and known.
func (h *KATHeader) Validate() error {
if h == nil {
return fmt.Errorf("params: nil KATHeader")
}
if h.ParameterSet == "" {
return fmt.Errorf("params: KATHeader.ParameterSet is empty")
}
if err := h.ModulusID.Validate(); err != nil {
return fmt.Errorf("KATHeader: %w", err)
}
if err := h.BackendID.Validate(); err != nil {
return fmt.Errorf("KATHeader: %w", err)
}
if err := h.HashSuiteID.Validate(); err != nil {
return fmt.Errorf("KATHeader: %w", err)
}
if h.ImplementationName == "" {
return fmt.Errorf("params: KATHeader.ImplementationName is empty")
}
if h.ImplementationVersion == "" {
return fmt.Errorf("params: KATHeader.ImplementationVersion is empty")
}
return nil
}