mirror of
https://github.com/luxfi/fhe.git
synced 2026-07-26 23:16:08 +00:00
docs(threshold): decomplect the threshold-FHE package — one canonical path
Establish exactly one way to do each thing and fence off the legacy primitives: - doc.go (new): package overview. DealerlessKeyGen is THE production keygen (dealerless); PartialDecryptLWE/CombineLWE is THE threshold decrypt (no-reconstruct); ShareLWESecretKey is a trusted-dealer test oracle only. Documents the F ⊥ M boundary (this package is FHE-only; MPC signing lives in luxfi/threshold) and the dealerless-bootstrap-key residual (homomorphic compute), stated honestly, not faked. - keygen.go: re-document GenerateSharedKey. It is a TRUSTED-DEALER key-COMMITMENT VSS that shares the SHA-256 hash of the key — useful for verifiable-sharing audit, NOT usable for threshold decryption. Marked Deprecated for the keygen role; points to DealerlessKeyGen. Removes the misleading 'distributed key generation … for now we generate keys and split them' framing. - partial_decrypt.go: label ShareLWESecretKey as TRUSTED-DEALER (retained as a KAT oracle); point to DealerlessKeyGen for production. No behaviour change; kernel tests green.
This commit is contained in:
@@ -0,0 +1,55 @@
|
|||||||
|
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// Package threshold is the ONE threshold-FHE implementation for Lux — the
|
||||||
|
// F-Chain confidential-decrypt lane. It is held to the trustless-by-default law:
|
||||||
|
// no trusted dealer (dealerless key generation) and no reconstruction of the FHE
|
||||||
|
// secret key at decrypt time, the same standard Corona / Pulsar / Magnetar meet.
|
||||||
|
//
|
||||||
|
// There is exactly one way to do each thing here. The canonical trustless flow:
|
||||||
|
//
|
||||||
|
// pub, shares := DealerlessKeyGen(params, t, n, crsSeed) // dealerless keygen
|
||||||
|
// ct := encrypt(pub, m) // collective public key
|
||||||
|
// d_j := PartialDecryptLWE(shares[j], ct, …) // per-party, no s formed
|
||||||
|
// m := CombineLWE(ct, {d_j}_{|S|≥t}, …) // s masked behind c_1, never recovered
|
||||||
|
//
|
||||||
|
// File map (decomplected — each file is one concern, no overlap):
|
||||||
|
//
|
||||||
|
// - dealerless_dkg.go — THE production key generation. Dealerless (GJKR/Pedersen
|
||||||
|
// DKG composed with the audited Lattigo multiparty CKG): each committee
|
||||||
|
// member samples only its own contribution s_j, the collective secret
|
||||||
|
// s = Σ s_j is NEVER formed, and the output is the collective LWE public key
|
||||||
|
// plus one t-of-n LWEShare per party.
|
||||||
|
//
|
||||||
|
// - partial_decrypt.go — THE threshold decryption (AJL+12 noise-flooding with
|
||||||
|
// Bendlin-Damgård denominator clearing). PartialDecryptLWE / CombineLWE are
|
||||||
|
// no-reconstruct: the secret s appears only as the coefficient of the public
|
||||||
|
// c_1 inside the masked aggregate and is never materialised. ShareLWESecretKey
|
||||||
|
// in this file is a TRUSTED-DEALER split of a whole key — retained only as a
|
||||||
|
// test/KAT oracle for the same LWEShare type; production uses DealerlessKeyGen.
|
||||||
|
//
|
||||||
|
// - lsss.go + keygen.go — a SEPARATE primitive: large-prime Shamir VSS with
|
||||||
|
// Feldman commitments, and GenerateSharedKey, which shares the SHA-256 *hash*
|
||||||
|
// of a serialized key. This is a key-COMMITMENT / verifiable-secret-sharing
|
||||||
|
// facility (audit, dealer-equivocation checks). Its KeyShare values are shares
|
||||||
|
// of a hash and are NOT usable for threshold DECRYPTION — do not mistake
|
||||||
|
// GenerateSharedKey for the threshold-FHE keygen; that is DealerlessKeyGen.
|
||||||
|
//
|
||||||
|
// Scope and residual. This package realises the trustless confidential-DECRYPT
|
||||||
|
// lane completely: dealerless generation of the encryption key + t-of-n shares,
|
||||||
|
// and no-reconstruct threshold decryption. It deliberately does NOT generate the
|
||||||
|
// FHEW blind-rotation / bootstrap (evaluation) key, which homomorphic COMPUTE on
|
||||||
|
// committee ciphertexts requires. Dealerless bootstrap-key generation is a
|
||||||
|
// distinct multiparty-FHEW protocol (collaborative RGSW key generation) and is
|
||||||
|
// the documented residual — it is not faked here. Until it lands, the committee
|
||||||
|
// can trustlessly ENCRYPT (collective public key) and trustlessly threshold-
|
||||||
|
// DECRYPT (the launch-critical confidentiality property); homomorphic compute on
|
||||||
|
// the committee's own ciphertexts still depends on a bootstrap key generated by a
|
||||||
|
// dealer and is therefore out of the strict trustless lane.
|
||||||
|
//
|
||||||
|
// Decomplecting boundary (F ⊥ M). This package is FHE only (confidential
|
||||||
|
// decrypt). It shares nothing with threshold MPC SIGNING (M-Chain: CGGMP21 /
|
||||||
|
// FROST for bridge custody), which lives in github.com/luxfi/threshold. The two
|
||||||
|
// are orthogonal primitives — different math, different purpose — and must never
|
||||||
|
// be conflated.
|
||||||
|
package threshold
|
||||||
+14
-3
@@ -40,9 +40,20 @@ type KeyGenResult struct {
|
|||||||
Shares []*KeyShare // One per party
|
Shares []*KeyShare // One per party
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateSharedKey performs distributed key generation.
|
// GenerateSharedKey is a TRUSTED-DEALER key-COMMITMENT facility, NOT the
|
||||||
// In a real implementation, this would be done via MPC.
|
// threshold-FHE key generator. It generates a keypair in one process and
|
||||||
// For now, we generate keys and split them using LSSS.
|
// large-prime Shamir-splits the SHA-256 HASH of each secret-key component
|
||||||
|
// (hashToFieldElement) — i.e. it shares a COMMITMENT to the key, for verifiable-
|
||||||
|
// secret-sharing / dealer-equivocation auditing. The resulting KeyShare values
|
||||||
|
// are shares of a hash and CANNOT perform threshold decryption.
|
||||||
|
//
|
||||||
|
// For the trustless threshold-FHE lane use DealerlessKeyGen (dealerless_dkg.go),
|
||||||
|
// which is dealerless (no party ever holds the FHE secret key) and produces
|
||||||
|
// decrypt-capable LWEShare values consumed by PartialDecryptLWE / CombineLWE. See
|
||||||
|
// the package doc for the canonical flow.
|
||||||
|
//
|
||||||
|
// Deprecated: not part of the threshold-decrypt path; retained only for the
|
||||||
|
// commitment-VSS use case.
|
||||||
func GenerateSharedKey(params fhe.Parameters, threshold, total int, sessionID string) (*KeyGenResult, error) {
|
func GenerateSharedKey(params fhe.Parameters, threshold, total int, sessionID string) (*KeyGenResult, error) {
|
||||||
if threshold > total {
|
if threshold > total {
|
||||||
return nil, fmt.Errorf("threshold %d exceeds total %d", threshold, total)
|
return nil, fmt.Errorf("threshold %d exceeds total %d", threshold, total)
|
||||||
|
|||||||
@@ -241,6 +241,12 @@ type LWEPartialDecryption struct {
|
|||||||
// ShareLWESecretKey Shamir-splits the LWE secret key coefficient-by-
|
// ShareLWESecretKey Shamir-splits the LWE secret key coefficient-by-
|
||||||
// coefficient over Z_q where q is the LWE modulus.
|
// coefficient over Z_q where q is the LWE modulus.
|
||||||
//
|
//
|
||||||
|
// TRUSTED-DEALER. This takes a WHOLE secret key, so the caller momentarily holds
|
||||||
|
// the full FHE secret — a single point of compromise. It is retained as a
|
||||||
|
// test/KAT oracle for the LWEShare type; the trustless PRODUCTION key generation
|
||||||
|
// is DealerlessKeyGen (dealerless_dkg.go), where no party ever holds the secret.
|
||||||
|
// Both produce the same LWEShare via the same dealing helpers (dealCoeffSubShares).
|
||||||
|
//
|
||||||
// Pipeline:
|
// Pipeline:
|
||||||
//
|
//
|
||||||
// 1. Extract the secret-key polynomial from NTT+Montgomery form back to
|
// 1. Extract the secret-key polynomial from NTT+Montgomery form back to
|
||||||
|
|||||||
Reference in New Issue
Block a user