mirror of
https://github.com/luxfi/lattice.git
synced 2026-09-24 00:25:44 +00:00
- Update module path to github.com/luxfi/lattice/v7 - Add GPU acceleration with Metal (macOS) and CUDA backends - Enhance threshold FHE operations - Revert to vanilla Apache 2.0 license (remove tfhe) - Update Go version to 1.25.5 - Merge upstream lattigo improvements
122 lines
3.6 KiB
Go
122 lines
3.6 KiB
Go
package rgsw
|
|
|
|
import (
|
|
"github.com/luxfi/lattice/v7/core/rlwe"
|
|
"github.com/luxfi/lattice/v7/ring"
|
|
"github.com/luxfi/lattice/v7/ring/ringqp"
|
|
)
|
|
|
|
// Encryptor is a type for encrypting RGSW ciphertexts. It implements the [rlwe.Encryptor]
|
|
// interface overriding the [rlwe.Encryptor.Encrypt] and [rlwe.Encryptor.EncryptZero] methods to accept [rgsw.Ciphertext]
|
|
// types in addition to ciphertexts types in the rlwe package.
|
|
type Encryptor struct {
|
|
*rlwe.Encryptor
|
|
pool *rlwe.BufferPool
|
|
}
|
|
|
|
// NewEncryptor creates a new Encryptor type. Note that only secret-key encryption is
|
|
// supported at the moment.
|
|
func NewEncryptor(params rlwe.ParameterProvider, key rlwe.EncryptionKey) *Encryptor {
|
|
return &Encryptor{rlwe.NewEncryptor(params, key), rlwe.NewPool(params.GetRLWEParameters().RingQP())}
|
|
}
|
|
|
|
// Encrypt encrypts a plaintext pt into a ciphertext ct, which can be a [rgsw.Ciphertext]
|
|
// or any of the `rlwe` cipheretxt types.
|
|
func (enc Encryptor) Encrypt(pt *rlwe.Plaintext, ct interface{}) (err error) {
|
|
|
|
var rgswCt *Ciphertext
|
|
var isRGSW bool
|
|
if rgswCt, isRGSW = ct.(*Ciphertext); !isRGSW {
|
|
return enc.Encryptor.Encrypt(pt, ct)
|
|
}
|
|
|
|
if err = enc.EncryptZero(rgswCt); err != nil {
|
|
return
|
|
}
|
|
|
|
params := enc.GetRLWEParameters()
|
|
|
|
levelQ := rgswCt.LevelQ()
|
|
ringQ := params.RingQ().AtLevel(levelQ)
|
|
|
|
if pt != nil {
|
|
|
|
buffQP := enc.pool.GetBuffPolyQP()
|
|
defer enc.pool.RecycleBuffPolyQP(buffQP)
|
|
|
|
if !pt.IsNTT {
|
|
ringQ.NTT(pt.Value, buffQP.Q)
|
|
|
|
if !pt.IsMontgomery {
|
|
ringQ.MForm(buffQP.Q, buffQP.Q)
|
|
}
|
|
|
|
} else {
|
|
if !pt.IsMontgomery {
|
|
ringQ.MForm(pt.Value, buffQP.Q)
|
|
} else {
|
|
pt.Value.CopyLvl(levelQ, buffQP.Q)
|
|
}
|
|
}
|
|
|
|
if err := rlwe.AddPolyTimesGadgetVectorToGadgetCiphertext(
|
|
buffQP.Q,
|
|
[]rlwe.GadgetCiphertext{rgswCt.Value[0], rgswCt.Value[1]},
|
|
*params.RingQP(),
|
|
buffQP.Q); err != nil {
|
|
// Sanity check, this error should not happen.
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// EncryptZero generates an encryption of zero into a ciphertext ct, which can be a [rgsw.Ciphertext]
|
|
// or any of the `rlwe` ciphertext types.
|
|
func (enc Encryptor) EncryptZero(ct interface{}) (err error) {
|
|
|
|
var rgswCt *Ciphertext
|
|
var isRGSW bool
|
|
if rgswCt, isRGSW = ct.(*Ciphertext); !isRGSW {
|
|
return enc.Encryptor.EncryptZero(rgswCt)
|
|
}
|
|
|
|
BaseRNSDecompositionVectorSize := rgswCt.Value[0].BaseRNSDecompositionVectorSize()
|
|
BaseTwoDecompositionVectorSize := rgswCt.Value[0].BaseTwoDecompositionVectorSize()
|
|
|
|
metadata := &rlwe.MetaData{}
|
|
metadata.IsMontgomery = true
|
|
metadata.IsNTT = true
|
|
|
|
for i := 0; i < BaseRNSDecompositionVectorSize; i++ {
|
|
for j := 0; j < BaseTwoDecompositionVectorSize[i]; j++ {
|
|
|
|
// extract the RingQ polynomial in case not P moduli have been provided
|
|
if rgswCt.LevelP() == -1 {
|
|
q0 := make([]ring.Poly, len(rgswCt.Value[0].Value[i][j]))
|
|
q1 := make([]ring.Poly, len(rgswCt.Value[1].Value[i][j]))
|
|
for k := range q0 {
|
|
q0[k] = rgswCt.Value[0].Value[i][j][k].Q
|
|
q1[k] = rgswCt.Value[1].Value[i][j][k].Q
|
|
}
|
|
if err = enc.Encryptor.EncryptZero(&rlwe.Ciphertext{Element: rlwe.Element[ring.Poly]{MetaData: metadata, Value: q0}}); err != nil {
|
|
return
|
|
}
|
|
if err = enc.Encryptor.EncryptZero(&rlwe.Ciphertext{Element: rlwe.Element[ring.Poly]{MetaData: metadata, Value: q1}}); err != nil {
|
|
return
|
|
}
|
|
} else {
|
|
if err = enc.Encryptor.EncryptZero(rlwe.Element[ringqp.Poly]{MetaData: metadata, Value: []ringqp.Poly(rgswCt.Value[0].Value[i][j])}); err != nil {
|
|
return
|
|
}
|
|
if err = enc.Encryptor.EncryptZero(rlwe.Element[ringqp.Poly]{MetaData: metadata, Value: []ringqp.Poly(rgswCt.Value[1].Value[i][j])}); err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|