mirror of
https://github.com/luxfi/fhe.git
synced 2026-07-26 23:16:08 +00:00
wire/wire.go — fhe's wire-format hardening boundary. FHE wire formats nest deeper than pulsar's (CKKS ciphertext = Vec<Poly> over RNS chain of Vec<u64>) so MaxDepth = 5 + larger MaxFrameBytes (32 MiB) reflect the deeper polynomial structure. Tests: * TestValidateCiphertextFrame_RejectsHugeLength — regression for lattice issue #4 attack input class. Same substrate, same rejection. * TestValidateCiphertextFrame_OverCap — MaxFHESliceLen+1 rejected. go.mod adds luxfi/math v1.3.0 dependency. This completes Phase 5 of LP-107: every Lux Go protocol repo (pulsar, lens, fhe, lattice) now consumes the math substrate for bounded wire decoding. The same lattice issue #4 attack input is rejected identically across all four consumers.
52 lines
1.8 KiB
Go
52 lines
1.8 KiB
Go
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// Package wire is fhe's wire-format hardening boundary.
|
|
//
|
|
// LP-107 Phase 5: fhe consumes luxfi/math/codec for bounded
|
|
// decoding of FHE ciphertext / key / param-pack frames. FHE wire
|
|
// formats nest more deeply than pulsar's lattice frames (a CKKS
|
|
// ciphertext is a Vec<Poly> over an RNS chain of Vec<u64>; an
|
|
// EvaluationKey is a tuple of those), so the bounded depth + size
|
|
// caps in luxfi/math/codec are essential.
|
|
package wire
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
"github.com/luxfi/math/codec"
|
|
)
|
|
|
|
// MaxFHESliceLen — FHE caps. PN11QP54 ring is 2048 coeffs/poly with
|
|
// up to ~10 levels in the RNS chain; 4096 is generous headroom.
|
|
const MaxFHESliceLen = 4096
|
|
|
|
// FHEWireLimits is the codec.Limits configuration FHE uses for
|
|
// every untrusted-input frame.
|
|
var FHEWireLimits = codec.Limits{
|
|
MaxFrameBytes: 32 * 1024 * 1024, // 32 MiB — accommodates EvaluationKey
|
|
MaxUint16SliceLen: MaxFHESliceLen,
|
|
MaxUint32SliceLen: MaxFHESliceLen,
|
|
MaxUint64SliceLen: MaxFHESliceLen,
|
|
MaxDepth: 5, // Vec<Poly> + Poly + RNS-Vec<u64> + scheme + chain
|
|
}
|
|
|
|
// ValidateCiphertextFrame walks the outer length prefix of an FHE
|
|
// ciphertext wire frame. Returns an error wrapping codec.ErrLimitExceeded
|
|
// when the cap is exceeded.
|
|
//
|
|
// The bounded reader rejects the lattice issue #4 attack input class
|
|
// (huge varint length) before any allocation, sharing the substrate's
|
|
// hardening with pulsar and lens.
|
|
func ValidateCiphertextFrame(frame []byte) error {
|
|
r, err := codec.NewReader(bytes.NewReader(frame), FHEWireLimits)
|
|
if err != nil {
|
|
return fmt.Errorf("fhe/wire: NewReader: %w", err)
|
|
}
|
|
if _, err := r.ReadUint64Slice(); err != nil {
|
|
return fmt.Errorf("fhe/wire: outer length: %w", err)
|
|
}
|
|
return nil
|
|
}
|