mirror of
https://github.com/luxfi/math.git
synced 2026-07-27 03:38:49 +00:00
230 lines
7.2 KiB
Go
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
|
|
}
|