Files
Hanzo AI a7cafe5f25 LP-107 Phase 5: fhe consumes luxfi/math/codec
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.
2026-05-04 09:50:34 -07:00

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
}