mirror of
https://github.com/luxfi/fhe.git
synced 2026-07-26 23:16:08 +00:00
100 lines
2.1 KiB
Go
100 lines
2.1 KiB
Go
// Copyright (c) 2025, Lux Industries Inc
|
|||
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
||
|
|
|
||
|
|
package fhe
|
||
|
|
|
||
|
|
import (
|
||
|
|
"github.com/luxfi/lattice/v7/core/rlwe"
|
||
|
|
"github.com/luxfi/lattice/v7/ring"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Decryptor decrypts FHE ciphertexts to boolean values
|
||
|
|
type Decryptor struct {
|
||
|
|
params Parameters
|
||
|
|
decryptor *rlwe.Decryptor
|
||
|
|
ringQ *ring.Ring
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewDecryptor creates a new decryptor from secret key
|
||
|
|
func NewDecryptor(params Parameters, sk *SecretKey) *Decryptor {
|
||
|
|
return &Decryptor{
|
||
|
|
params: params,
|
||
|
|
decryptor: rlwe.NewDecryptor(params.paramsLWE, sk.SKLWE),
|
||
|
|
ringQ: params.paramsLWE.RingQ(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Decrypt decrypts a ciphertext to a boolean
|
||
|
|
func (dec *Decryptor) Decrypt(ct *Ciphertext) bool {
|
||
|
|
pt := rlwe.NewPlaintext(dec.params.paramsLWE, ct.Level())
|
||
|
|
dec.decryptor.Decrypt(ct.Ciphertext, pt)
|
||
|
|
|
||
|
|
if pt.IsNTT {
|
||
|
|
dec.ringQ.INTT(pt.Value, pt.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get the constant term
|
||
|
|
c := pt.Value.Coeffs[0][0]
|
||
|
|
q := dec.params.QLWE()
|
||
|
|
qHalf := q >> 1
|
||
|
|
|
||
|
|
// Decode:
|
||
|
|
// - true was encoded as Q/8, so c ∈ [0, Q/2) means true
|
||
|
|
// - false was encoded as 7Q/8, so c ∈ [Q/2, Q) means false
|
||
|
|
return c < qHalf
|
||
|
|
}
|
||
|
|
|
||
|
|
// DecryptBit returns the decrypted bit as int (0 or 1)
|
||
|
|
func (dec *Decryptor) DecryptBit(ct *Ciphertext) int {
|
||
|
|
if dec.Decrypt(ct) {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// DecryptByte decrypts 8 ciphertexts to a byte
|
||
|
|
func (dec *Decryptor) DecryptByte(cts [8]*Ciphertext) byte {
|
||
|
|
var b byte
|
||
|
|
for i := 0; i < 8; i++ {
|
||
|
|
if dec.Decrypt(cts[i]) {
|
||
|
|
b |= 1 << i
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return b
|
||
|
|
}
|
||
|
|
|
||
|
|
// DecryptUint32 decrypts 32 ciphertexts to uint32
|
||
|
|
func (dec *Decryptor) DecryptUint32(cts [32]*Ciphertext) uint32 {
|
||
|
|
var v uint32
|
||
|
|
for i := 0; i < 32; i++ {
|
||
|
|
if dec.Decrypt(cts[i]) {
|
||
|
|
v |= 1 << i
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return v
|
||
|
|
}
|
||
|
|
|
||
|
|
// DecryptUint64 decrypts 64 ciphertexts to uint64
|
||
|
|
func (dec *Decryptor) DecryptUint64(cts [64]*Ciphertext) uint64 {
|
||
|
|
var v uint64
|
||
|
|
for i := 0; i < 64; i++ {
|
||
|
|
if dec.Decrypt(cts[i]) {
|
||
|
|
v |= 1 << i
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return v
|
||
|
|
}
|
||
|
|
|
||
|
|
// DecryptUint256 decrypts 256 ciphertexts to 4 uint64s
|
||
|
|
func (dec *Decryptor) DecryptUint256(cts [256]*Ciphertext) [4]uint64 {
|
||
|
|
var v [4]uint64
|
||
|
|
for w := 0; w < 4; w++ {
|
||
|
|
for i := 0; i < 64; i++ {
|
||
|
|
if dec.Decrypt(cts[w*64+i]) {
|
||
|
|
v[w] |= 1 << i
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return v
|
||
|
|
}
|