mirror of
https://github.com/luxfi/lattice.git
synced 2026-09-24 00:25:44 +00:00
108 lines
3.2 KiB
Go
108 lines
3.2 KiB
Go
package rgsw
|
|
|
|
import (
|
|
"github.com/luxfi/lattice/v5/core/rlwe"
|
|
"github.com/luxfi/lattice/v5/ring/ringqp"
|
|
)
|
|
|
|
// Encryptor is a type for encrypting RGSW ciphertexts. It implements the rlwe.Encryptor
|
|
// interface overriding the `Encrypt` and `EncryptZero` methods to accept rgsw.Ciphertext
|
|
// types in addition to ciphertexts types in the rlwe package.
|
|
type Encryptor struct {
|
|
*rlwe.Encryptor
|
|
buffQP ringqp.Poly
|
|
}
|
|
|
|
// 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), params.GetRLWEParameters().RingQP().NewPoly()}
|
|
}
|
|
|
|
// 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 {
|
|
|
|
if !pt.IsNTT {
|
|
ringQ.NTT(pt.Value, enc.buffQP.Q)
|
|
|
|
if !pt.IsMontgomery {
|
|
ringQ.MForm(enc.buffQP.Q, enc.buffQP.Q)
|
|
}
|
|
|
|
} else {
|
|
if !pt.IsMontgomery {
|
|
ringQ.MForm(pt.Value, enc.buffQP.Q)
|
|
} else {
|
|
pt.Value.CopyLvl(levelQ, enc.buffQP.Q)
|
|
}
|
|
}
|
|
|
|
if err := rlwe.AddPolyTimesGadgetVectorToGadgetCiphertext(
|
|
enc.buffQP.Q,
|
|
[]rlwe.GadgetCiphertext{rgswCt.Value[0], rgswCt.Value[1]},
|
|
*params.RingQP(),
|
|
enc.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` cipheretxt 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++ {
|
|
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
|
|
}
|
|
|
|
// ShallowCopy creates a shallow copy of this Encryptor in which all the read-only data-structures are
|
|
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
|
// Encryptors can be used concurrently.
|
|
func (enc Encryptor) ShallowCopy() *Encryptor {
|
|
return &Encryptor{Encryptor: enc.Encryptor.ShallowCopy(), buffQP: enc.GetRLWEParameters().RingQP().NewPoly()}
|
|
}
|