Replaced some errors when allocating structs or generating keys by panics when irrecoverable

This commit is contained in:
Jean-Philippe Bossuat
2023-08-07 14:37:15 +02:00
parent 281645f9ea
commit 3d87424835
38 changed files with 262 additions and 744 deletions

View File

@@ -42,13 +42,13 @@ func NewCiphertext(params Parameters, degree int, level ...int) (ct *rlwe.Cipher
// NewEncryptor instantiates a new rlwe.Encryptor from the given BFV parameters and
// encryption key. This key can be either a *rlwe.SecretKey or a *rlwe.PublicKey.
func NewEncryptor(params Parameters, key rlwe.EncryptionKey) (*rlwe.Encryptor, error) {
func NewEncryptor(params Parameters, key rlwe.EncryptionKey) *rlwe.Encryptor {
return rlwe.NewEncryptor(params, key)
}
// NewDecryptor instantiates a new rlwe.Decryptor from the given BFV parameters and
// secret decryption key.
func NewDecryptor(params Parameters, key *rlwe.SecretKey) (*rlwe.Decryptor, error) {
func NewDecryptor(params Parameters, key *rlwe.SecretKey) *rlwe.Decryptor {
return rlwe.NewDecryptor(params, key)
}

View File

@@ -103,25 +103,10 @@ func genTestParams(params Parameters) (tc *testContext, err error) {
tc.sk, tc.pk = tc.kgen.GenKeyPairNew()
tc.encoder = NewEncoder(tc.params)
if tc.encryptorPk, err = NewEncryptor(tc.params, tc.pk); err != nil {
return
}
if tc.encryptorSk, err = NewEncryptor(tc.params, tc.sk); err != nil {
return
}
if tc.decryptor, err = NewDecryptor(tc.params, tc.sk); err != nil {
return
}
var rlk *rlwe.RelinearizationKey
if rlk, err = tc.kgen.GenRelinearizationKeyNew(tc.sk); err != nil {
return
}
evk := rlwe.NewMemEvaluationKeySet(rlk)
tc.evaluator = NewEvaluator(tc.params, evk)
tc.encryptorPk = NewEncryptor(tc.params, tc.pk)
tc.encryptorSk = NewEncryptor(tc.params, tc.sk)
tc.decryptor = NewDecryptor(tc.params, tc.sk)
tc.evaluator = NewEvaluator(tc.params, rlwe.NewMemEvaluationKeySet(tc.kgen.GenRelinearizationKeyNew(tc.sk)))
tc.testLevel = []int{0, params.MaxLevel()}

View File

@@ -47,7 +47,7 @@ func NewCiphertext(params Parameters, degree, level int) (ct *rlwe.Ciphertext) {
// - key: *rlwe.SecretKey or *rlwe.PublicKey
//
// output: an rlwe.Encryptor instantiated with the provided key.
func NewEncryptor(params Parameters, key rlwe.EncryptionKey) (*rlwe.Encryptor, error) {
func NewEncryptor(params Parameters, key rlwe.EncryptionKey) *rlwe.Encryptor {
return rlwe.NewEncryptor(params, key)
}
@@ -58,7 +58,7 @@ func NewEncryptor(params Parameters, key rlwe.EncryptionKey) (*rlwe.Encryptor, e
// - key: *rlwe.SecretKey
//
// output: an rlwe.Decryptor instantiated with the provided key.
func NewDecryptor(params Parameters, key *rlwe.SecretKey) (*rlwe.Decryptor, error) {
func NewDecryptor(params Parameters, key *rlwe.SecretKey) *rlwe.Decryptor {
return rlwe.NewDecryptor(params, key)
}

View File

@@ -111,25 +111,10 @@ func genTestParams(params Parameters) (tc *testContext, err error) {
tc.sk, tc.pk = tc.kgen.GenKeyPairNew()
tc.encoder = NewEncoder(tc.params)
if tc.encryptorPk, err = NewEncryptor(tc.params, tc.pk); err != nil {
return
}
if tc.encryptorSk, err = NewEncryptor(tc.params, tc.sk); err != nil {
return
}
if tc.decryptor, err = NewDecryptor(tc.params, tc.sk); err != nil {
return
}
var rlk *rlwe.RelinearizationKey
if rlk, err = tc.kgen.GenRelinearizationKeyNew(tc.sk); err != nil {
return
}
evk := rlwe.NewMemEvaluationKeySet(rlk)
tc.evaluator = NewEvaluator(tc.params, evk)
tc.encryptorPk = NewEncryptor(tc.params, tc.pk)
tc.encryptorSk = NewEncryptor(tc.params, tc.sk)
tc.decryptor = NewDecryptor(tc.params, tc.sk)
tc.evaluator = NewEvaluator(tc.params, rlwe.NewMemEvaluationKeySet(tc.kgen.GenRelinearizationKeyNew(tc.sk)))
tc.testLevel = []int{0, params.MaxLevel()}
@@ -144,7 +129,9 @@ func newTestVectorsLvl(level int, scale rlwe.Scale, tc *testContext, encryptor *
plaintext = NewPlaintext(tc.params, level)
plaintext.Scale = scale
tc.encoder.Encode(coeffs.Coeffs[0], plaintext)
if err := tc.encoder.Encode(coeffs.Coeffs[0], plaintext); err != nil {
panic(err)
}
if encryptor != nil {
var err error
ciphertext, err = encryptor.EncryptNew(plaintext)

View File

@@ -135,10 +135,7 @@ func testLinearTransformation(tc *testContext, t *testing.T) {
galEls := GaloisElementsForLinearTransformation(params, ltparams)
gks, err := tc.kgen.GenGaloisKeysNew(galEls, tc.sk)
require.NoError(t, err)
ltEval := NewEvaluator(tc.evaluator.WithKey(rlwe.NewMemEvaluationKeySet(nil, gks...)))
ltEval := NewEvaluator(tc.evaluator.WithKey(rlwe.NewMemEvaluationKeySet(nil, tc.kgen.GenGaloisKeysNew(galEls, tc.sk)...)))
require.NoError(t, ltEval.LinearTransformation(ciphertext, linTransf, ciphertext))
@@ -207,10 +204,7 @@ func testLinearTransformation(tc *testContext, t *testing.T) {
galEls := GaloisElementsForLinearTransformation(params, ltparams)
gks, err := tc.kgen.GenGaloisKeysNew(galEls, tc.sk)
require.NoError(t, err)
ltEval := NewEvaluator(tc.evaluator.WithKey(rlwe.NewMemEvaluationKeySet(nil, gks...)))
ltEval := NewEvaluator(tc.evaluator.WithKey(rlwe.NewMemEvaluationKeySet(nil, tc.kgen.GenGaloisKeysNew(galEls, tc.sk)...)))
require.NoError(t, ltEval.LinearTransformation(ciphertext, linTransf, ciphertext))
@@ -343,25 +337,10 @@ func genTestParams(params bfv.Parameters) (tc *testContext, err error) {
tc.sk, tc.pk = tc.kgen.GenKeyPairNew()
tc.encoder = bgv.NewEncoder(bgv.Parameters(tc.params.Parameters))
if tc.encryptorPk, err = bfv.NewEncryptor(tc.params, tc.pk); err != nil {
return
}
if tc.encryptorSk, err = bfv.NewEncryptor(tc.params, tc.sk); err != nil {
return
}
if tc.decryptor, err = bfv.NewDecryptor(tc.params, tc.sk); err != nil {
return
}
var rlk *rlwe.RelinearizationKey
if rlk, err = tc.kgen.GenRelinearizationKeyNew(tc.sk); err != nil {
return
}
evk := rlwe.NewMemEvaluationKeySet(rlk)
tc.evaluator = bfv.NewEvaluator(tc.params, evk)
tc.encryptorPk = bfv.NewEncryptor(tc.params, tc.pk)
tc.encryptorSk = bfv.NewEncryptor(tc.params, tc.sk)
tc.decryptor = bfv.NewDecryptor(tc.params, tc.sk)
tc.evaluator = bfv.NewEvaluator(tc.params, rlwe.NewMemEvaluationKeySet(tc.kgen.GenRelinearizationKeyNew(tc.sk)))
tc.testLevel = []int{0, params.MaxLevel()}

View File

@@ -127,10 +127,8 @@ func testHomomorphicEncoding(params ckks.Parameters, LogSlots int, t *testing.T)
kgen := ckks.NewKeyGenerator(params)
sk := kgen.GenSecretKeyNew()
encoder := ckks.NewEncoder(params, 90) // Required to force roots.(type) to be []*bignum.Complex instead of []complex128
encryptor, err := ckks.NewEncryptor(params, sk)
require.NoError(t, err)
decryptor, err := ckks.NewDecryptor(params, sk)
require.NoError(t, err)
encryptor := ckks.NewEncryptor(params, sk)
decryptor := ckks.NewDecryptor(params, sk)
// Generates the encoding matrices
CoeffsToSlotMatrices, err := NewHomomorphicDFTMatrixFromLiteral(params, CoeffsToSlotsParametersLiteral, encoder)
@@ -140,11 +138,8 @@ func testHomomorphicEncoding(params ckks.Parameters, LogSlots int, t *testing.T)
galEls := append(CoeffsToSlotsParametersLiteral.GaloisElements(params), params.GaloisElementOrderTwoOrthogonalSubgroup())
// Generates and adds the keys
gks, err := kgen.GenGaloisKeysNew(galEls, sk)
require.NoError(t, err)
// Instantiates the EvaluationKeySet
evk := rlwe.NewMemEvaluationKeySet(nil, gks...)
evk := rlwe.NewMemEvaluationKeySet(nil, kgen.GenGaloisKeysNew(galEls, sk)...)
// Creates an evaluator with the rotation keys
eval := ckks.NewEvaluator(params, evk)
@@ -336,10 +331,8 @@ func testHomomorphicDecoding(params ckks.Parameters, LogSlots int, t *testing.T)
kgen := ckks.NewKeyGenerator(params)
sk := kgen.GenSecretKeyNew()
encoder := ckks.NewEncoder(params)
encryptor, err := ckks.NewEncryptor(params, sk)
require.NoError(t, err)
decryptor, err := ckks.NewDecryptor(params, sk)
require.NoError(t, err)
encryptor := ckks.NewEncryptor(params, sk)
decryptor := ckks.NewDecryptor(params, sk)
// Generates the encoding matrices
SlotsToCoeffsMatrix, err := NewHomomorphicDFTMatrixFromLiteral(params, SlotsToCoeffsParametersLiteral, encoder)
@@ -349,11 +342,8 @@ func testHomomorphicDecoding(params ckks.Parameters, LogSlots int, t *testing.T)
galEls := append(SlotsToCoeffsParametersLiteral.GaloisElements(params), params.GaloisElementOrderTwoOrthogonalSubgroup())
// Generates and adds the keys
gks, err := kgen.GenGaloisKeysNew(galEls, sk)
require.NoError(t, err)
// Instantiates the EvaluationKeySet
evk := rlwe.NewMemEvaluationKeySet(nil, gks...)
evk := rlwe.NewMemEvaluationKeySet(nil, kgen.GenGaloisKeysNew(galEls, sk)...)
// Creates an evaluator with the rotation keys
eval := ckks.NewEvaluator(params, evk)

View File

@@ -72,17 +72,9 @@ func testEvalMod(params ckks.Parameters, t *testing.T) {
kgen := ckks.NewKeyGenerator(params)
sk := kgen.GenSecretKeyNew()
encoder := ckks.NewEncoder(params)
encryptor, err := ckks.NewEncryptor(params, sk)
require.NoError(t, err)
decryptor, err := ckks.NewDecryptor(params, sk)
require.NoError(t, err)
rlk, err := kgen.GenRelinearizationKeyNew(sk)
require.NoError(t, err)
evk := rlwe.NewMemEvaluationKeySet(rlk)
eval := ckks.NewEvaluator(params, evk)
encryptor := ckks.NewEncryptor(params, sk)
decryptor := ckks.NewDecryptor(params, sk)
eval := ckks.NewEvaluator(params, rlwe.NewMemEvaluationKeySet(kgen.GenRelinearizationKeyNew(sk)))
modEval := NewHModEvaluator(eval)

View File

@@ -114,24 +114,10 @@ func genCKKSTestParams(defaultParam ckks.Parameters) (tc *ckksTestContext, err e
tc.encoder = ckks.NewEncoder(tc.params)
if tc.encryptorPk, err = ckks.NewEncryptor(tc.params, tc.pk); err != nil {
return
}
if tc.encryptorSk, err = ckks.NewEncryptor(tc.params, tc.sk); err != nil {
return
}
if tc.decryptor, err = ckks.NewDecryptor(tc.params, tc.sk); err != nil {
return
}
rlk, err := tc.kgen.GenRelinearizationKeyNew(tc.sk)
if err != nil {
return nil, err
}
tc.evaluator = ckks.NewEvaluator(tc.params, rlwe.NewMemEvaluationKeySet(rlk))
tc.encryptorPk = ckks.NewEncryptor(tc.params, tc.pk)
tc.encryptorSk = ckks.NewEncryptor(tc.params, tc.sk)
tc.decryptor = ckks.NewDecryptor(tc.params, tc.sk)
tc.evaluator = ckks.NewEvaluator(tc.params, rlwe.NewMemEvaluationKeySet(tc.kgen.GenRelinearizationKeyNew(tc.sk)))
return tc, nil
@@ -188,13 +174,9 @@ func testCKKSLinearTransformation(tc *ckksTestContext, t *testing.T) {
batch := 1 << logBatch
n := slots / batch
gks, err := tc.kgen.GenGaloisKeysNew(rlwe.GaloisElementsForInnerSum(tc.params, batch, n), tc.sk)
require.NoError(t, err)
evk := rlwe.NewMemEvaluationKeySet(nil, gks...)
eval := tc.evaluator.WithKey(rlwe.NewMemEvaluationKeySet(nil, tc.kgen.GenGaloisKeysNew(rlwe.GaloisElementsForInnerSum(tc.params, batch, n), tc.sk)...))
eval := tc.evaluator.WithKey(evk)
eval.Average(ciphertext, logBatch, ciphertext)
require.NoError(t, eval.Average(ciphertext, logBatch, ciphertext))
tmp0 := make([]*bignum.Complex, len(values))
for i := range tmp0 {
@@ -258,9 +240,7 @@ func testCKKSLinearTransformation(tc *ckksTestContext, t *testing.T) {
galEls := GaloisElementsForLinearTransformation(params, ltparams)
gks, err := tc.kgen.GenGaloisKeysNew(galEls, tc.sk)
require.NoError(t, err)
evk := rlwe.NewMemEvaluationKeySet(nil, gks...)
evk := rlwe.NewMemEvaluationKeySet(nil, tc.kgen.GenGaloisKeysNew(galEls, tc.sk)...)
ltEval := NewEvaluator(tc.evaluator.WithKey(evk))
@@ -323,9 +303,7 @@ func testCKKSLinearTransformation(tc *ckksTestContext, t *testing.T) {
galEls := GaloisElementsForLinearTransformation(params, ltparams)
gks, err := tc.kgen.GenGaloisKeysNew(galEls, tc.sk)
require.NoError(t, err)
evk := rlwe.NewMemEvaluationKeySet(nil, gks...)
evk := rlwe.NewMemEvaluationKeySet(nil, tc.kgen.GenGaloisKeysNew(galEls, tc.sk)...)
ltEval := NewEvaluator(tc.evaluator.WithKey(evk))

View File

@@ -106,25 +106,10 @@ func genBGVTestParams(params bgv.Parameters) (tc *bgvTestContext, err error) {
tc.sk, tc.pk = tc.kgen.GenKeyPairNew()
tc.encoder = bgv.NewEncoder(tc.params)
if tc.encryptorPk, err = bgv.NewEncryptor(tc.params, tc.pk); err != nil {
return
}
if tc.encryptorSk, err = bgv.NewEncryptor(tc.params, tc.sk); err != nil {
return
}
if tc.decryptor, err = bgv.NewDecryptor(tc.params, tc.sk); err != nil {
return
}
var rlk *rlwe.RelinearizationKey
if rlk, err = tc.kgen.GenRelinearizationKeyNew(tc.sk); err != nil {
return
}
evk := rlwe.NewMemEvaluationKeySet(rlk)
tc.evaluator = bgv.NewEvaluator(tc.params, evk)
tc.encryptorPk = bgv.NewEncryptor(tc.params, tc.pk)
tc.encryptorSk = bgv.NewEncryptor(tc.params, tc.sk)
tc.decryptor = bgv.NewDecryptor(tc.params, tc.sk)
tc.evaluator = bgv.NewEvaluator(tc.params, rlwe.NewMemEvaluationKeySet(tc.kgen.GenRelinearizationKeyNew(tc.sk)))
tc.testLevel = []int{0, params.MaxLevel()}
@@ -230,9 +215,7 @@ func testBGVLinearTransformation(tc *bgvTestContext, t *testing.T) {
galEls := GaloisElementsForLinearTransformation(params, ltparams)
gks, err := tc.kgen.GenGaloisKeysNew(galEls, tc.sk)
require.NoError(t, err)
eval := tc.evaluator.WithKey(rlwe.NewMemEvaluationKeySet(nil, gks...))
eval := tc.evaluator.WithKey(rlwe.NewMemEvaluationKeySet(nil, tc.kgen.GenGaloisKeysNew(galEls, tc.sk)...))
ltEval := NewEvaluator(eval)
require.NoError(t, ltEval.LinearTransformation(ciphertext, linTransf, ciphertext))
@@ -302,9 +285,7 @@ func testBGVLinearTransformation(tc *bgvTestContext, t *testing.T) {
galEls := GaloisElementsForLinearTransformation(params, ltparams)
gks, err := tc.kgen.GenGaloisKeysNew(galEls, tc.sk)
require.NoError(t, err)
eval := tc.evaluator.WithKey(rlwe.NewMemEvaluationKeySet(nil, gks...))
eval := tc.evaluator.WithKey(rlwe.NewMemEvaluationKeySet(nil, tc.kgen.GenGaloisKeysNew(galEls, tc.sk)...))
ltEval := NewEvaluator(eval)
require.NoError(t, ltEval.LinearTransformation(ciphertext, linTransf, ciphertext))

View File

@@ -86,35 +86,22 @@ func NewBootstrapper(params ckks.Parameters, btpParams Parameters, btpKeys *Eval
// EvaluationKeySet: struct compliant to the interface rlwe.EvaluationKeySetInterface.
// EvkDtS: *rlwe.EvaluationKey
// EvkStD: *rlwe.EvaluationKey
func GenEvaluationKeySetNew(btpParams Parameters, ckksParams ckks.Parameters, sk *rlwe.SecretKey) (*EvaluationKeySet, error) {
func GenEvaluationKeySetNew(btpParams Parameters, ckksParams ckks.Parameters, sk *rlwe.SecretKey) *EvaluationKeySet {
kgen := ckks.NewKeyGenerator(ckksParams)
gks, err := kgen.GenGaloisKeysNew(append(btpParams.GaloisElements(ckksParams), ckksParams.GaloisElementForComplexConjugation()), sk)
if err != nil {
return nil, err
}
EvkDtS, EvkStD := btpParams.GenEncapsulationEvaluationKeysNew(ckksParams, sk)
EvkDtS, EvkStD, err := btpParams.GenEncapsulationEvaluationKeysNew(ckksParams, sk)
if err != nil {
return nil, err
}
rlk, err := kgen.GenRelinearizationKeyNew(sk)
if err != nil {
return nil, err
}
evk := rlwe.NewMemEvaluationKeySet(rlk, gks...)
evk := rlwe.NewMemEvaluationKeySet(kgen.GenRelinearizationKeyNew(sk), kgen.GenGaloisKeysNew(append(btpParams.GaloisElements(ckksParams), ckksParams.GaloisElementForComplexConjugation()), sk)...)
return &EvaluationKeySet{
MemEvaluationKeySet: evk,
EvkDtS: EvkDtS,
EvkStD: EvkStD,
}, nil
}
}
// GenEncapsulationEvaluationKeysNew generates the low level encapsulation EvaluationKeys for the bootstrapping.
func (p *Parameters) GenEncapsulationEvaluationKeysNew(params ckks.Parameters, skDense *rlwe.SecretKey) (EvkDtS, EvkStD *rlwe.EvaluationKey, err error) {
func (p *Parameters) GenEncapsulationEvaluationKeysNew(params ckks.Parameters, skDense *rlwe.SecretKey) (EvkDtS, EvkStD *rlwe.EvaluationKey) {
if p.EphemeralSecretWeight == 0 {
return
@@ -130,18 +117,8 @@ func (p *Parameters) GenEncapsulationEvaluationKeysNew(params ckks.Parameters, s
kgenDense := rlwe.NewKeyGenerator(params.Parameters)
skSparse := kgenSparse.GenSecretKeyWithHammingWeightNew(p.EphemeralSecretWeight)
EvkDtS, err = kgenDense.GenEvaluationKeyNew(skDense, skSparse)
if err != nil {
return nil, nil, err
}
EvkStD, err = kgenDense.GenEvaluationKeyNew(skSparse, skDense)
if err != nil {
return nil, nil, err
}
EvkDtS = kgenDense.GenEvaluationKeyNew(skDense, skSparse)
EvkStD = kgenDense.GenEvaluationKeyNew(skSparse, skDense)
return
}

View File

@@ -23,10 +23,7 @@ func BenchmarkBootstrap(b *testing.B) {
kgen := ckks.NewKeyGenerator(params)
sk := kgen.GenSecretKeyNew()
evk, err := GenEvaluationKeySetNew(btpParams, params, sk)
require.NoError(b, err)
btp, err := NewBootstrapper(params, btpParams, evk)
btp, err := NewBootstrapper(params, btpParams, GenEvaluationKeySetNew(btpParams, params, sk))
require.NoError(b, err)
b.Run(ParamsToString(params, btpParams.LogMaxDimensions().Cols, "Bootstrap/"), func(b *testing.B) {

View File

@@ -130,15 +130,9 @@ func testbootstrap(params ckks.Parameters, btpParams Parameters, t *testing.T) {
sk := kgen.GenSecretKeyNew()
encoder := ckks.NewEncoder(params)
encryptor, err := ckks.NewEncryptor(params, sk)
require.NoError(t, err)
decryptor, err := ckks.NewDecryptor(params, sk)
require.NoError(t, err)
evk, err := GenEvaluationKeySetNew(btpParams, params, sk)
require.NoError(t, err)
encryptor := ckks.NewEncryptor(params, sk)
decryptor := ckks.NewDecryptor(params, sk)
evk := GenEvaluationKeySetNew(btpParams, params, sk)
btp, err := NewBootstrapper(params, btpParams, evk)
require.NoError(t, err)

View File

@@ -48,7 +48,7 @@ func NewCiphertext(params Parameters, degree, level int) (ct *rlwe.Ciphertext) {
// - key: *rlwe.SecretKey or *rlwe.PublicKey
//
// output: an rlwe.Encryptor instantiated with the provided key.
func NewEncryptor(params Parameters, key rlwe.EncryptionKey) (*rlwe.Encryptor, error) {
func NewEncryptor(params Parameters, key rlwe.EncryptionKey) *rlwe.Encryptor {
return rlwe.NewEncryptor(params, key)
}
@@ -59,7 +59,7 @@ func NewEncryptor(params Parameters, key rlwe.EncryptionKey) (*rlwe.Encryptor, e
// - key: *rlwe.SecretKey
//
// output: an rlwe.Decryptor instantiated with the provided key.
func NewDecryptor(params Parameters, key *rlwe.SecretKey) (*rlwe.Decryptor, error) {
func NewDecryptor(params Parameters, key *rlwe.SecretKey) *rlwe.Decryptor {
return rlwe.NewDecryptor(params, key)
}

View File

@@ -4,8 +4,6 @@ import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
"github.com/tuneinsight/lattigo/v4/ring"
"github.com/tuneinsight/lattigo/v4/rlwe"
"github.com/tuneinsight/lattigo/v4/utils/sampling"
@@ -94,10 +92,7 @@ func benchEvaluator(tc *testContext, b *testing.B) {
ciphertext2 := rlwe.NewCiphertextRandom(tc.prng, tc.params.Parameters, 1, tc.params.MaxLevel())
receiver := rlwe.NewCiphertextRandom(tc.prng, tc.params.Parameters, 2, tc.params.MaxLevel())
rlk, err := tc.kgen.GenRelinearizationKeyNew(tc.sk)
require.NoError(b, err)
eval := tc.evaluator.WithKey(rlwe.NewMemEvaluationKeySet(rlk))
eval := tc.evaluator.WithKey(rlwe.NewMemEvaluationKeySet(tc.kgen.GenRelinearizationKeyNew(tc.sk)))
b.Run(GetTestName(tc.params, "Evaluator/Add/Scalar"), func(b *testing.B) {
for i := 0; i < b.N; i++ {

View File

@@ -121,24 +121,13 @@ func genTestParams(defaultParam Parameters) (tc *testContext, err error) {
tc.encoder = NewEncoder(tc.params)
if tc.encryptorPk, err = NewEncryptor(tc.params, tc.pk); err != nil {
return
}
tc.encryptorPk = NewEncryptor(tc.params, tc.pk)
if tc.encryptorSk, err = NewEncryptor(tc.params, tc.sk); err != nil {
return
}
tc.encryptorSk = NewEncryptor(tc.params, tc.sk)
if tc.decryptor, err = NewDecryptor(tc.params, tc.sk); err != nil {
return
}
tc.decryptor = NewDecryptor(tc.params, tc.sk)
rlk, err := tc.kgen.GenRelinearizationKeyNew(tc.sk)
if err != nil {
return nil, err
}
tc.evaluator = NewEvaluator(tc.params, rlwe.NewMemEvaluationKeySet(rlk))
tc.evaluator = NewEvaluator(tc.params, rlwe.NewMemEvaluationKeySet(tc.kgen.GenRelinearizationKeyNew(tc.sk)))
return tc, nil
@@ -146,8 +135,6 @@ func genTestParams(defaultParam Parameters) (tc *testContext, err error) {
func newTestVectors(tc *testContext, encryptor *rlwe.Encryptor, a, b complex128, t *testing.T) (values []*bignum.Complex, pt *rlwe.Plaintext, ct *rlwe.Ciphertext) {
var err error
prec := tc.encoder.Prec()
pt = NewPlaintext(tc.params, tc.params.MaxLevel())
@@ -176,8 +163,11 @@ func newTestVectors(tc *testContext, encryptor *rlwe.Encryptor, a, b complex128,
tc.encoder.Encode(values, pt)
if encryptor != nil {
var err error
ct, err = encryptor.EncryptNew(pt)
require.NoError(t, err)
if err != nil {
panic(err)
}
}
return values, pt, ct
@@ -793,9 +783,9 @@ func testFunctions(tc *testContext, t *testing.T) {
logPrec := math.Log2(tc.params.DefaultScale().Float64()) - float64(tc.params.LogN()-1)
btp, err := NewSecretKeyBootstrapper(tc.params, tc.sk)
require.NoError(t, err)
btp := NewSecretKeyBootstrapper(tc.params, tc.sk)
var err error
if ciphertext, err = tc.evaluator.GoldschmidtDivisionNew(ciphertext, min, logPrec, btp); err != nil {
t.Fatal(err)
}
@@ -828,13 +818,11 @@ func testBridge(tc *testContext, t *testing.T) {
stdKeyGen := NewKeyGenerator(stdParams)
stdSK := stdKeyGen.GenSecretKeyNew()
stdDecryptor, err := NewDecryptor(stdParams, stdSK)
require.NoError(t, err)
stdDecryptor := NewDecryptor(stdParams, stdSK)
stdEncoder := NewEncoder(stdParams)
stdEvaluator := NewEvaluator(stdParams, nil)
evkCtR, evkRtC, err := stdKeyGen.GenEvaluationKeysForRingSwapNew(stdSK, tc.sk)
require.NoError(t, err)
evkCtR, evkRtC := stdKeyGen.GenEvaluationKeysForRingSwapNew(stdSK, tc.sk)
switcher, err := NewDomainSwitcher(stdParams, evkCtR, evkRtC)
if err != nil {

View File

@@ -17,28 +17,15 @@ type SecretKeyBootstrapper struct {
Counter int // records the number of bootstrapping
}
func NewSecretKeyBootstrapper(params Parameters, sk *rlwe.SecretKey) (rlwe.Bootstrapper, error) {
dec, err := NewDecryptor(params, sk)
if err != nil {
return nil, err
}
enc, err := NewEncryptor(params, sk)
if err != nil {
return nil, err
}
func NewSecretKeyBootstrapper(params Parameters, sk *rlwe.SecretKey) rlwe.Bootstrapper {
return &SecretKeyBootstrapper{
params,
NewEncoder(params),
dec,
enc,
NewDecryptor(params, sk),
NewEncryptor(params, sk),
sk,
make([]*bignum.Complex, params.N()),
0}, nil
0}
}
func (d *SecretKeyBootstrapper) Bootstrap(ct *rlwe.Ciphertext) (*rlwe.Ciphertext, error) {
@@ -53,11 +40,8 @@ func (d *SecretKeyBootstrapper) Bootstrap(ct *rlwe.Ciphertext) (*rlwe.Ciphertext
return nil, err
}
ct.Resize(1, d.MaxLevel())
if err := d.Encrypt(pt, ct); err != nil {
return nil, err
}
d.Counter++
return ct, nil
return ct, d.Encrypt(pt, ct)
}
func (d SecretKeyBootstrapper) BootstrapMany(cts []*rlwe.Ciphertext) ([]*rlwe.Ciphertext, error) {

View File

@@ -151,25 +151,11 @@ func gentestContext(nParties int, params bgv.Parameters) (tc *testContext, err e
}
// Publickeys
if tc.pk0, err = kgen.GenPublicKeyNew(tc.sk0); err != nil {
return
}
if tc.pk1, err = kgen.GenPublicKeyNew(tc.sk1); err != nil {
return
}
if tc.encryptorPk0, err = bgv.NewEncryptor(tc.params, tc.pk0); err != nil {
return
}
if tc.decryptorSk0, err = bgv.NewDecryptor(tc.params, tc.sk0); err != nil {
return
}
if tc.decryptorSk1, err = bgv.NewDecryptor(tc.params, tc.sk1); err != nil {
return
}
tc.pk0 = kgen.GenPublicKeyNew(tc.sk0)
tc.pk1 = kgen.GenPublicKeyNew(tc.sk1)
tc.encryptorPk0 = bgv.NewEncryptor(tc.params, tc.pk0)
tc.decryptorSk0 = bgv.NewDecryptor(tc.params, tc.sk0)
tc.decryptorSk1 = bgv.NewDecryptor(tc.params, tc.sk1)
return
}
@@ -489,8 +475,7 @@ func testRefreshAndTransformSwitchParams(tc *testContext, t *testing.T) {
transform.Func(coeffs)
coeffsHave := make([]uint64, tc.params.MaxSlots())
dec, err := rlwe.NewDecryptor(paramsOut.Parameters, skIdealOut)
require.NoError(t, err)
dec := rlwe.NewDecryptor(paramsOut.Parameters, skIdealOut)
bgv.NewEncoder(paramsOut).Decode(dec.DecryptNew(ciphertext), coeffsHave)
//Decrypts and compares
@@ -501,7 +486,8 @@ func testRefreshAndTransformSwitchParams(tc *testContext, t *testing.T) {
func newTestVectors(tc *testContext, encryptor *rlwe.Encryptor, t *testing.T) (coeffs []uint64, plaintext *rlwe.Plaintext, ciphertext *rlwe.Ciphertext) {
prng, _ := sampling.NewPRNG()
prng, err := sampling.NewPRNG()
require.NoError(t, err)
uniformSampler := ring.NewUniformSampler(prng, tc.ringT)
coeffsPol := uniformSampler.ReadNew()
@@ -512,9 +498,10 @@ func newTestVectors(tc *testContext, encryptor *rlwe.Encryptor, t *testing.T) (c
plaintext = bgv.NewPlaintext(tc.params, tc.params.MaxLevel())
plaintext.Scale = tc.params.NewScale(2)
require.NoError(t, tc.encoder.Encode(coeffsPol.Coeffs[0], plaintext))
var err error
ciphertext, err = encryptor.EncryptNew(plaintext)
require.NoError(t, err)
if err != nil {
panic(err)
}
return coeffsPol.Coeffs[0], plaintext, ciphertext
}

View File

@@ -140,25 +140,11 @@ func genTestParams(params ckks.Parameters, NParties int) (tc *testContext, err e
}
// Publickeys
if tc.pk0, err = kgen.GenPublicKeyNew(tc.sk0); err != nil {
return
}
if tc.pk1, err = kgen.GenPublicKeyNew(tc.sk1); err != nil {
return
}
if tc.encryptorPk0, err = ckks.NewEncryptor(tc.params, tc.pk0); err != nil {
return
}
if tc.decryptorSk0, err = ckks.NewDecryptor(tc.params, tc.sk0); err != nil {
return
}
if tc.decryptorSk1, err = ckks.NewDecryptor(tc.params, tc.sk1); err != nil {
return
}
tc.pk0 = kgen.GenPublicKeyNew(tc.sk0)
tc.pk1 = kgen.GenPublicKeyNew(tc.sk1)
tc.encryptorPk0 = ckks.NewEncryptor(tc.params, tc.pk0)
tc.decryptorSk0 = ckks.NewDecryptor(tc.params, tc.sk0)
tc.decryptorSk1 = ckks.NewDecryptor(tc.params, tc.sk1)
return
}
@@ -505,10 +491,7 @@ func testRefreshAndTransformSwitchParams(tc *testContext, t *testing.T) {
coeffs[i][1].Mul(coeffs[i][1], bignum.NewFloat(0.7071067811865476, logBound))
}
dec, err := ckks.NewDecryptor(paramsOut, skIdealOut)
require.NoError(t, err)
ckks.VerifyTestVectors(paramsOut, ckks.NewEncoder(paramsOut), dec, coeffs, ciphertext, nil, *printPrecisionStats, t)
ckks.VerifyTestVectors(paramsOut, ckks.NewEncoder(paramsOut), ckks.NewDecryptor(paramsOut, skIdealOut), coeffs, ciphertext, nil, *printPrecisionStats, t)
})
}
@@ -544,12 +527,13 @@ func newTestVectorsAtScale(tc *testContext, encryptor *rlwe.Encryptor, a, b comp
panic("invalid ring type")
}
tc.encoder.Encode(values, pt)
if err := tc.encoder.Encode(values, pt); err != nil {
panic(err)
}
if encryptor != nil {
var err error
ct, err = encryptor.EncryptNew(pt)
if err != nil {
if ct, err = encryptor.EncryptNew(pt); err != nil {
panic(err)
}
}

View File

@@ -355,10 +355,7 @@ func testKeySwitchProtocol(tc *testContext, levelQ, levelP, bpw2 int, t *testing
}
ct := rlwe.NewCiphertext(params, 1, levelQ)
enc2, err := rlwe.NewEncryptor(params, tc.skIdeal)
require.NoError(t, err)
require.NoError(t, enc2.EncryptZero(ct))
rlwe.NewEncryptor(params, tc.skIdeal).EncryptZero(ct)
shares := make([]KeySwitchShare, nbParties)
for i := range shares {
@@ -377,8 +374,7 @@ func testKeySwitchProtocol(tc *testContext, levelQ, levelP, bpw2 int, t *testing
ksCt := rlwe.NewCiphertext(params, 1, ct.Level())
dec, err := rlwe.NewDecryptor(params, skOutIdeal)
require.NoError(t, err)
dec := rlwe.NewDecryptor(params, skOutIdeal)
cks[0].KeySwitch(ct, shares[0], ksCt)
@@ -429,10 +425,7 @@ func testPublicKeySwitchProtocol(tc *testContext, levelQ, levelP, bpw2 int, t *t
ct := rlwe.NewCiphertext(params, 1, levelQ)
enc2, err := rlwe.NewEncryptor(params, tc.skIdeal)
require.NoError(t, err)
require.NoError(t, enc2.EncryptZero(ct))
rlwe.NewEncryptor(params, tc.skIdeal).EncryptZero(ct)
shares := make([]PublicKeySwitchShare, nbParties)
for i := range shares {
@@ -451,8 +444,7 @@ func testPublicKeySwitchProtocol(tc *testContext, levelQ, levelP, bpw2 int, t *t
buffer.RequireSerializerCorrect(t, &shares[0])
ksCt := rlwe.NewCiphertext(params, 1, levelQ)
dec, err := rlwe.NewDecryptor(params, skOut)
require.NoError(t, err)
dec := rlwe.NewDecryptor(params, skOut)
pcks[0].KeySwitch(ct, shares[0], ksCt)

View File

@@ -41,10 +41,7 @@ func NewPublicKeySwitchProtocol(params rlwe.Parameters, noiseFlooding ring.Distr
panic(err)
}
pcks.Encryptor, err = rlwe.NewEncryptor(params, nil)
if err != nil {
panic(err)
}
pcks.Encryptor = rlwe.NewEncryptor(params, nil)
switch noiseFlooding.(type) {
case ring.DiscreteGaussian:
@@ -69,17 +66,14 @@ func (pcks PublicKeySwitchProtocol) AllocateShare(levelQ int) (s PublicKeySwitch
// ct is the rlwe.Ciphertext to keyswitch. Note that ct.Value[0] is not used by the function and can be nil/zero.
//
// Expected noise: ctNoise + encFreshPk + smudging
func (pcks PublicKeySwitchProtocol) GenShare(sk *rlwe.SecretKey, pk *rlwe.PublicKey, ct *rlwe.Ciphertext, shareOut *PublicKeySwitchShare) (err error) {
func (pcks PublicKeySwitchProtocol) GenShare(sk *rlwe.SecretKey, pk *rlwe.PublicKey, ct *rlwe.Ciphertext, shareOut *PublicKeySwitchShare) {
levelQ := utils.Min(shareOut.Level(), ct.Value[1].Level())
ringQ := pcks.params.RingQ().AtLevel(levelQ)
// Encrypt zero
enc, err := pcks.Encryptor.WithKey(pk)
if err != nil {
return fmt.Errorf("cannot GenShare: %w", err)
}
enc := pcks.Encryptor.WithKey(pk)
if err := enc.EncryptZero(&rlwe.Ciphertext{
Operand: rlwe.Operand[ring.Poly]{
@@ -90,7 +84,7 @@ func (pcks PublicKeySwitchProtocol) GenShare(sk *rlwe.SecretKey, pk *rlwe.Public
MetaData: ct.MetaData,
},
}); err != nil {
return fmt.Errorf("cannot GenShare: %w", err)
panic(err)
}
// Add ct[1] * s and noise
@@ -106,8 +100,6 @@ func (pcks PublicKeySwitchProtocol) GenShare(sk *rlwe.SecretKey, pk *rlwe.Public
pcks.noiseSampler.ReadAndAdd(pcks.buf)
ringQ.Add(shareOut.Value[0], pcks.buf, shareOut.Value[0])
}
return
}
// AggregateShares is the second part of the first and unique round of the PublicKeySwitchProtocol protocol. Each party upon receiving the j-1 elements from the
@@ -155,15 +147,10 @@ func (pcks PublicKeySwitchProtocol) ShallowCopy() PublicKeySwitchProtocol {
panic(err)
}
enc, err := rlwe.NewEncryptor(params, nil)
if err != nil {
panic(err)
}
return PublicKeySwitchProtocol{
noiseSampler: Xe,
noise: pcks.noise,
Encryptor: enc,
Encryptor: pcks.Encryptor.ShallowCopy(),
params: params,
buf: params.RingQ().NewPoly(),
}

View File

@@ -75,20 +75,9 @@ func obliviousRiding() {
riderSk, riderPk := kgen.GenKeyPairNew()
decryptor, err := bfv.NewDecryptor(params, riderSk)
if err != nil {
panic(err)
}
encryptorRiderPk, err := bfv.NewEncryptor(params, riderPk)
if err != nil {
panic(err)
}
encryptorRiderSk, err := bfv.NewEncryptor(params, riderSk)
if err != nil {
panic(err)
}
decryptor := bfv.NewDecryptor(params, riderSk)
encryptorRiderPk := bfv.NewEncryptor(params, riderPk)
encryptorRiderSk := bfv.NewEncryptor(params, riderSk)
evaluator := bfv.NewEvaluator(params, nil)

View File

@@ -132,23 +132,14 @@ func main() {
kgenN12 := ckks.NewKeyGenerator(paramsN12)
skN12 := kgenN12.GenSecretKeyNew()
encoderN12 := ckks.NewEncoder(paramsN12)
encryptorN12, err := ckks.NewEncryptor(paramsN12, skN12)
if err != nil {
panic(err)
}
decryptorN12, err := ckks.NewDecryptor(paramsN12, skN12)
if err != nil {
panic(err)
}
encryptorN12 := ckks.NewEncryptor(paramsN12, skN12)
decryptorN12 := ckks.NewDecryptor(paramsN12, skN12)
kgenN11 := ckks.NewKeyGenerator(paramsN11)
skN11 := kgenN11.GenSecretKeyNew()
// EvaluationKey RLWEN12 -> RLWEN11
evkN12ToN11, err := ckks.NewKeyGenerator(paramsN12).GenEvaluationKeyNew(skN12, skN11)
if err != nil {
panic(err)
}
evkN12ToN11 := ckks.NewKeyGenerator(paramsN12).GenEvaluationKeyNew(skN12, skN11)
fmt.Printf("Gen SlotsToCoeffs Matrices... ")
now = time.Now()
@@ -168,12 +159,7 @@ func main() {
galEls = append(galEls, CoeffsToSlotsParameters.GaloisElements(paramsN12)...)
galEls = append(galEls, paramsN12.GaloisElementForComplexConjugation())
gks, err := kgenN12.GenGaloisKeysNew(galEls, skN12)
if err != nil {
panic(err)
}
evk := rlwe.NewMemEvaluationKeySet(nil, gks...)
evk := rlwe.NewMemEvaluationKeySet(nil, kgenN12.GenGaloisKeysNew(galEls, skN12)...)
// LUT Evaluator
evalLUT := lut.NewEvaluator(paramsN12.Parameters, paramsN11.Parameters)
@@ -184,10 +170,7 @@ func main() {
fmt.Printf("Encrypting bits of skLWE in RGSW... ")
now = time.Now()
blindRotateKey, err := lut.GenEvaluationKeyNew(paramsN12.Parameters, skN12, paramsN11.Parameters, skN11, evkParams) // Generate RGSW(sk_i) for all coefficients of sk
if err != nil {
panic(err)
}
blindRotateKey := lut.GenEvaluationKeyNew(paramsN12.Parameters, skN12, paramsN11.Parameters, skN11, evkParams) // Generate RGSW(sk_i) for all coefficients of sk
fmt.Printf("Done (%s)\n", time.Since(now))
// Generates the starting plaintext values.
@@ -202,6 +185,7 @@ func main() {
if err := encoderN12.Encode(values, pt); err != nil {
panic(err)
}
ctN12, err := encryptorN12.EncryptNew(pt)
if err != nil {
panic(err)

View File

@@ -96,21 +96,12 @@ func main() {
sk, pk := kgen.GenKeyPairNew()
encoder := ckks.NewEncoder(params)
decryptor, err := ckks.NewDecryptor(params, sk)
if err != nil {
panic(err)
}
encryptor, err := ckks.NewEncryptor(params, pk)
if err != nil {
panic(err)
}
decryptor := ckks.NewDecryptor(params, sk)
encryptor := ckks.NewEncryptor(params, pk)
fmt.Println()
fmt.Println("Generating bootstrapping keys...")
evk, err := bootstrapping.GenEvaluationKeySetNew(btpParams, params, sk)
if err != nil {
panic(err)
}
evk := bootstrapping.GenEvaluationKeySetNew(btpParams, params, sk)
fmt.Println("Done")
var btp *bootstrapping.Bootstrapper

View File

@@ -159,14 +159,8 @@ func main() {
// - PublicKey: an encryption of zero, which can be shared and enable anyone to encrypt plaintexts.
// - RelinearizationKey: an evaluation key which is used during ciphertext x ciphertext multiplication to ensure ciphertext compactness.
sk := kgen.GenSecretKeyNew()
pk, err := kgen.GenPublicKeyNew(sk) // Note that we can generate any number of public keys associated to the same Secret Key.
if err != nil {
panic(err)
}
rlk, err := kgen.GenRelinearizationKeyNew(sk)
if err != nil {
panic(err)
}
pk := kgen.GenPublicKeyNew(sk) // Note that we can generate any number of public keys associated to the same Secret Key.
rlk := kgen.GenRelinearizationKeyNew(sk)
// To store and manage the loading of evaluation keys, we instantiate a struct that complies to the `rlwe.EvaluationKeySetInterface` Interface.
// The package `rlwe` provides a simple struct that complies to this interface, but a user can design its own struct compliant to the `rlwe.EvaluationKeySetInterface`
@@ -218,10 +212,7 @@ func main() {
// To generate ciphertexts we need an encryptor.
// An encryptor will accept both a secret key or a public key,
// in this example we will use the public key.
enc, err := ckks.NewEncryptor(params, pk)
if err != nil {
panic(err)
}
enc := ckks.NewEncryptor(params, pk)
// And we create the ciphertext.
// Note that the metadata of the plaintext will be copied on the resulting ciphertext.
@@ -229,6 +220,7 @@ func main() {
if err != nil {
panic(err)
}
// It is also possible to first allocate the ciphertext the same way it was done
// for the plaintext with with `ct := ckks.NewCiphertext(params, 1, pt.Level())`.
@@ -239,10 +231,7 @@ func main() {
// We are able to generate ciphertext from plaintext using the encryptor.
// To do the converse, generate plaintexts from ciphertexts, we need to instantiate a decryptor.
// Obviously, the decryptor will only accept the secret key.
dec, err := ckks.NewDecryptor(params, sk)
if err != nil {
panic(err)
}
dec := ckks.NewDecryptor(params, sk)
// ================
// Evaluator Basics
@@ -484,13 +473,8 @@ func main() {
}
// We then generate the `rlwe.GaloisKey`s element that corresponds to these galois elements.
gks, err := kgen.GenGaloisKeysNew(galEls, sk)
if err != nil {
panic(err)
}
// Then we update the evaluator's `rlwe.EvaluationKeySet` with the new keys.
eval = eval.WithKey(rlwe.NewMemEvaluationKeySet(rlk, gks...))
// And we update the evaluator's `rlwe.EvaluationKeySet` with the new keys.
eval = eval.WithKey(rlwe.NewMemEvaluationKeySet(rlk, kgen.GenGaloisKeysNew(galEls, sk)...))
// Rotation by 5 positions to the left
for i := 0; i < Slots; i++ {
@@ -612,12 +596,7 @@ func main() {
// The innersum operations is carried out with log2(n) + HW(n) automorphisms and we need to
// generate the corresponding Galois keys and provide them to the `Evaluator`.
gks, err = kgen.GenGaloisKeysNew(params.GaloisElementsForInnerSum(batch, n), sk)
if err != nil {
panic(err)
}
eval = eval.WithKey(rlwe.NewMemEvaluationKeySet(rlk, gks...))
eval = eval.WithKey(rlwe.NewMemEvaluationKeySet(rlk, kgen.GenGaloisKeysNew(params.GaloisElementsForInnerSum(batch, n), sk)...))
// Plaintext circuit
copy(want, values1)
@@ -637,12 +616,7 @@ func main() {
fmt.Printf("Innersum %s", ckks.GetPrecisionStats(params, ecd, dec, want, res, nil, false).String())
// The replicate operation is exactly the same as the innersum operation, but in reverse
gks, err = kgen.GenGaloisKeysNew(params.GaloisElementsForReplicate(batch, n), sk)
if err != nil {
panic(err)
}
eval = eval.WithKey(rlwe.NewMemEvaluationKeySet(rlk, gks...))
eval = eval.WithKey(rlwe.NewMemEvaluationKeySet(rlk, kgen.GenGaloisKeysNew(params.GaloisElementsForReplicate(batch, n), sk)...))
// Plaintext circuit
copy(want, values1)
@@ -720,11 +694,8 @@ func main() {
// The list of Galois elements can also be obtained with `lt.GaloisElements`
// but this requires to have it pre-allocated, which is not always desirable.
galEls = circuits.GaloisElementsForLinearTransformation(params, ltparams)
gks, err = kgen.GenGaloisKeysNew(galEls, sk)
if err != nil {
panic(err)
}
ltEval := circuits.NewEvaluator(eval.WithKey(rlwe.NewMemEvaluationKeySet(rlk, gks...)))
ltEval := circuits.NewEvaluator(eval.WithKey(rlwe.NewMemEvaluationKeySet(rlk, kgen.GenGaloisKeysNew(galEls, sk)...)))
// And we valuate the linear transform
if err := ltEval.LinearTransformation(ct1, lt, res); err != nil {

View File

@@ -41,24 +41,10 @@ func example() {
sk := kgen.GenSecretKeyNew()
encryptor, err := ckks.NewEncryptor(params, sk)
if err != nil {
panic(err)
}
decryptor, err := ckks.NewDecryptor(params, sk)
if err != nil {
panic(err)
}
encryptor := ckks.NewEncryptor(params, sk)
decryptor := ckks.NewDecryptor(params, sk)
encoder := ckks.NewEncoder(params)
rlk, err := kgen.GenRelinearizationKeyNew(sk)
if err != nil {
panic(err)
}
evk := rlwe.NewMemEvaluationKeySet(rlk)
evk := rlwe.NewMemEvaluationKeySet(kgen.GenRelinearizationKeyNew(sk))
evaluator := ckks.NewEvaluator(params, evk)
fmt.Printf("Done in %s \n", time.Since(start))

View File

@@ -41,27 +41,13 @@ func chebyshevinterpolation() {
sk, pk := kgen.GenKeyPairNew()
// Encryptor
encryptor, err := ckks.NewEncryptor(params, pk)
if err != nil {
panic(err)
}
encryptor := ckks.NewEncryptor(params, pk)
// Decryptor
decryptor, err := ckks.NewDecryptor(params, sk)
if err != nil {
panic(err)
}
decryptor := ckks.NewDecryptor(params, sk)
// Relinearization key
rlk, err := kgen.GenRelinearizationKeyNew(sk)
if err != nil {
panic(err)
}
evk := rlwe.NewMemEvaluationKeySet(rlk)
// Evaluator
evaluator := ckks.NewEvaluator(params, evk)
// Evaluator with relinearization key
evaluator := ckks.NewEvaluator(params, rlwe.NewMemEvaluationKeySet(kgen.GenRelinearizationKeyNew(sk)))
// Values to encrypt
slots := params.MaxSlots()

View File

@@ -164,10 +164,7 @@ func main() {
// Ciphertexts encrypted under collective public key and stored in the cloud
l.Println("> Encrypt Phase")
encryptor, err := bfv.NewEncryptor(params, pk)
if err != nil {
panic(err)
}
encryptor := bfv.NewEncryptor(params, pk)
pt := bfv.NewPlaintext(params, params.MaxLevel())
elapsedEncryptParty := runTimedParty(func() {
for i, pi := range P {
@@ -194,10 +191,7 @@ func main() {
l.Println("> ResulPlaintextModulus:")
// Decryption by the external party
decryptor, err := bfv.NewDecryptor(params, P[0].sk)
if err != nil {
panic(err)
}
decryptor := bfv.NewDecryptor(params, P[0].sk)
ptres := bfv.NewPlaintext(params, params.MaxLevel())
elapsedDecParty := runTimed(func() {
decryptor.Decrypt(encOut, ptres)

View File

@@ -136,10 +136,7 @@ func main() {
// Decrypt the result with the target secret key
l.Println("> ResulPlaintextModulus:")
decryptor, err := bfv.NewDecryptor(params, tsk)
if err != nil {
panic(err)
}
decryptor := bfv.NewDecryptor(params, tsk)
ptres := bfv.NewPlaintext(params, params.MaxLevel())
elapsedDecParty := runTimed(func() {
decryptor.Decrypt(encOut, ptres)
@@ -176,10 +173,7 @@ func encPhase(params bfv.Parameters, P []*party, pk *rlwe.PublicKey, encoder *bf
// Each party encrypts its input vector
l.Println("> Encrypt Phase")
encryptor, err := bfv.NewEncryptor(params, pk)
if err != nil {
panic(err)
}
encryptor := bfv.NewEncryptor(params, pk)
pt := bfv.NewPlaintext(params, params.MaxLevel())
elapsedEncryptParty = runTimedParty(func() {
@@ -329,9 +323,7 @@ func pcksPhase(params bfv.Parameters, tpk *rlwe.PublicKey, encRes *rlwe.Cipherte
l.Println("> PublicKeySwitch Phase")
elapsedPCKSParty = runTimedParty(func() {
for _, pi := range P {
if err = pcks.GenShare(pi.sk, tpk, encRes, &pi.pcksShare); err != nil {
panic(err)
}
pcks.GenShare(pi.sk, tpk, encRes, &pi.pcksShare)
}
}, len(P))

View File

@@ -71,10 +71,7 @@ func main() {
skLWE := rlwe.NewKeyGenerator(paramsLWE).GenSecretKeyNew()
// RLWE encryptor for the samples
encryptorLWE, err := rlwe.NewEncryptor(paramsLWE, skLWE)
if err != nil {
panic(err)
}
encryptorLWE := rlwe.NewEncryptor(paramsLWE, skLWE)
// Values to encrypt in the RLWE sample
values := make([]float64, slots)
@@ -107,10 +104,7 @@ func main() {
skLUT := rlwe.NewKeyGenerator(paramsLUT).GenSecretKeyNew()
// Collection of RGSW ciphertexts encrypting the bits of skLWE under skLUT
blindeRotateKey, err := lut.GenEvaluationKeyNew(paramsLUT, skLUT, paramsLWE, skLWE, evkParams)
if err != nil {
panic(err)
}
blindeRotateKey := lut.GenEvaluationKeyNew(paramsLUT, skLUT, paramsLWE, skLWE, evkParams)
// Evaluation of LUT(ctLWE)
// Returns one RLWE sample per slot in ctLWE
@@ -125,10 +119,7 @@ func main() {
// Decrypts, decodes and compares
q := paramsLUT.Q()[0]
qHalf := q >> 1
decryptorLUT, err := rlwe.NewDecryptor(paramsLUT, skLUT)
if err != nil {
panic(err)
}
decryptorLUT := rlwe.NewDecryptor(paramsLUT, skLUT)
ptLUT := rlwe.NewPlaintext(paramsLUT, paramsLUT.MaxLevel())
for i := 0; i < slots; i++ {

View File

@@ -18,9 +18,8 @@ type Encryptor struct {
// NewEncryptor creates a new Encryptor type. Note that only secret-key encryption is
// supported at the moment.
func NewEncryptor(params rlwe.Parameters, key rlwe.EncryptionKey) (*Encryptor, error) {
enc, err := rlwe.NewEncryptor(params, key)
return &Encryptor{enc, params, params.RingQP().NewPoly()}, err
func NewEncryptor(params rlwe.Parameters, key rlwe.EncryptionKey) *Encryptor {
return &Encryptor{rlwe.NewEncryptor(params, key), params, params.RingQP().NewPoly()}
}
// Encrypt encrypts a plaintext pt into a ciphertext ct, which can be a rgsw.Ciphertext
@@ -57,14 +56,16 @@ func (enc Encryptor) Encrypt(pt *rlwe.Plaintext, ct interface{}) (err error) {
}
}
return rlwe.AddPolyTimesGadgetVectorToGadgetCiphertext(
if err := rlwe.AddPolyTimesGadgetVectorToGadgetCiphertext(
enc.buffQP.Q,
[]rlwe.GadgetCiphertext{rgswCt.Value[0], rgswCt.Value[1]},
*enc.params.RingQP(),
enc.buffQP.Q)
enc.buffQP.Q); err != nil {
panic(err)
}
}
return
return nil
}
// EncryptZero generates an encryption of zero into a ciphertext ct, which can be a rgsw.Ciphertext
@@ -74,7 +75,7 @@ func (enc Encryptor) EncryptZero(ct interface{}) (err error) {
var rgswCt *Ciphertext
var isRGSW bool
if rgswCt, isRGSW = ct.(*Ciphertext); !isRGSW {
return enc.Encryptor.EncryptZero(ct)
return enc.Encryptor.EncryptZero(rgswCt)
}
BaseRNSDecompositionVectorSize := rgswCt.Value[0].BaseRNSDecompositionVectorSize()
@@ -86,18 +87,16 @@ func (enc Encryptor) EncryptZero(ct interface{}) (err error) {
for i := 0; i < BaseRNSDecompositionVectorSize; i++ {
for j := 0; j < BaseTwoDecompositionVectorSize[i]; j++ {
if err = enc.Encryptor.EncryptZero(rlwe.Operand[ringqp.Poly]{MetaData: metadata, Value: []ringqp.Poly(rgswCt.Value[0].Value[i][j])}); err != nil {
return
}
if err = enc.Encryptor.EncryptZero(rlwe.Operand[ringqp.Poly]{MetaData: metadata, Value: []ringqp.Poly(rgswCt.Value[1].Value[i][j])}); err != nil {
return
}
}
}
return
return nil
}
// ShallowCopy creates a shallow copy of this Encryptor in which all the read-only data-structures are

View File

@@ -43,7 +43,7 @@ func (evk MemBlindRotatationEvaluationKeySet) GetEvaluationKeySet() (rlwe.Evalua
}
// GenEvaluationKeyNew generates a new LUT evaluation key
func GenEvaluationKeyNew(paramsRLWE rlwe.Parameters, skRLWE *rlwe.SecretKey, paramsLWE rlwe.Parameters, skLWE *rlwe.SecretKey, evkParams ...rlwe.EvaluationKeyParameters) (key MemBlindRotatationEvaluationKeySet, err error) {
func GenEvaluationKeyNew(paramsRLWE rlwe.Parameters, skRLWE *rlwe.SecretKey, paramsLWE rlwe.Parameters, skLWE *rlwe.SecretKey, evkParams ...rlwe.EvaluationKeyParameters) (key MemBlindRotatationEvaluationKeySet) {
skLWECopy := skLWE.CopyNew()
paramsLWE.RingQ().AtLevel(0).INTT(skLWECopy.Value.Q, skLWECopy.Value.Q)
@@ -54,10 +54,7 @@ func GenEvaluationKeyNew(paramsRLWE rlwe.Parameters, skRLWE *rlwe.SecretKey, par
}
paramsLWE.RingQ().AtLevel(0).PolyToBigintCentered(skLWECopy.Value.Q, 1, sk)
encryptor, err := rgsw.NewEncryptor(paramsRLWE, skRLWE)
if err != nil {
return key, err
}
encryptor := rgsw.NewEncryptor(paramsRLWE, skRLWE)
levelQ, levelP, BaseTwoDecomposition := rlwe.ResolveEvaluationKeyParameters(paramsRLWE, evkParams)
@@ -82,8 +79,8 @@ func GenEvaluationKeyNew(paramsRLWE rlwe.Parameters, skRLWE *rlwe.SecretKey, par
skiRGSW[i] = rgsw.NewCiphertext(paramsRLWE, levelQ, levelP, BaseTwoDecomposition)
if err = encryptor.Encrypt(ptXi[siInt], skiRGSW[i]); err != nil {
return
if err := encryptor.Encrypt(ptXi[siInt], skiRGSW[i]); err != nil {
panic(err)
}
}
@@ -96,15 +93,11 @@ func GenEvaluationKeyNew(paramsRLWE rlwe.Parameters, skRLWE *rlwe.SecretKey, par
galEls = append(galEls, paramsRLWE.RingQ().NthRoot()-ring.GaloisGen)
gks, err := kgen.GenGaloisKeysNew(galEls, skRLWE, rlwe.EvaluationKeyParameters{
gks := kgen.GenGaloisKeysNew(galEls, skRLWE, rlwe.EvaluationKeyParameters{
LevelQ: utils.Pointy(levelQ),
LevelP: utils.Pointy(levelP),
BaseTwoDecomposition: utils.Pointy(BaseTwoDecomposition),
})
if err != nil {
return MemBlindRotatationEvaluationKeySet{}, err
}
return MemBlindRotatationEvaluationKeySet{BlindRotationKeys: skiRGSW, AutomorphismKeys: gks}, nil
return MemBlindRotatationEvaluationKeySet{BlindRotationKeys: skiRGSW, AutomorphismKeys: gks}
}

View File

@@ -94,8 +94,7 @@ func testLUT(t *testing.T) {
skLWE := rlwe.NewKeyGenerator(paramsLWE).GenSecretKeyNew()
// RLWE encryptor for the samples
encryptorLWE, err := rlwe.NewEncryptor(paramsLWE, skLWE)
require.NoError(t, err)
encryptorLWE := rlwe.NewEncryptor(paramsLWE, skLWE)
// Values to encrypt in the RLWE sample
values := make([]float64, slots)
@@ -129,8 +128,7 @@ func testLUT(t *testing.T) {
skLUT := rlwe.NewKeyGenerator(paramsLUT).GenSecretKeyNew()
// Collection of RGSW ciphertexts encrypting the bits of skLWE under skLUT
btpKey, err := GenEvaluationKeyNew(paramsLUT, skLUT, paramsLWE, skLWE, evkParams)
require.NoError(t, err)
btpKey := GenEvaluationKeyNew(paramsLUT, skLUT, paramsLWE, skLWE, evkParams)
// Evaluation of LUT(ctLWE)
// Returns one RLWE sample per slot in ctLWE
@@ -140,8 +138,7 @@ func testLUT(t *testing.T) {
// Decrypts, decodes and compares
q := paramsLUT.Q()[0]
qHalf := q >> 1
decryptorLUT, err := rlwe.NewDecryptor(paramsLUT, skLUT)
require.NoError(t, err)
decryptorLUT := rlwe.NewDecryptor(paramsLUT, skLUT)
ptLUT := rlwe.NewPlaintext(paramsLUT, paramsLUT.MaxLevel())
for i := 0; i < slots; i++ {

View File

@@ -38,10 +38,7 @@ func TestRGSW(t *testing.T) {
ct := NewCiphertext(params, params.MaxLevelQ(), params.MaxLevelP(), 0)
enc, err := NewEncryptor(params, sk)
require.NoError(t, err)
enc.Encrypt(pt, ct)
NewEncryptor(params, sk).Encrypt(pt, ct)
left, right := NoiseRGSWCiphertext(ct, pt.Value, sk, params)
@@ -53,10 +50,7 @@ func TestRGSW(t *testing.T) {
ct := NewCiphertext(params, params.MaxLevelQ(), params.MaxLevelP(), 0)
enc, err := NewEncryptor(params, pk)
require.NoError(t, err)
enc.Encrypt(pt, ct)
NewEncryptor(params, pk).Encrypt(pt, ct)
left, right := NoiseRGSWCiphertext(ct, pt.Value, sk, params)
@@ -83,23 +77,13 @@ func TestRGSW(t *testing.T) {
ctRGSW := NewCiphertext(params, params.MaxLevelQ(), params.MaxLevelP(), 0)
ctRLWE := rlwe.NewCiphertext(params, 1, params.MaxLevelQ())
rgswEnc, err := NewEncryptor(params, sk)
require.NoError(t, err)
rgswEnc.Encrypt(ptRGSW, ctRGSW)
rlweEnc, err := rlwe.NewEncryptor(params, sk)
require.NoError(t, err)
rlweEnc.Encrypt(ptRLWE, ctRLWE)
NewEncryptor(params, sk).Encrypt(ptRGSW, ctRGSW)
rlwe.NewEncryptor(params, sk).Encrypt(ptRLWE, ctRLWE)
// X^{k0} * Scale * X^{k1}
NewEvaluator(params, nil).ExternalProduct(ctRLWE, ctRGSW, ctRLWE)
dec, err := rlwe.NewDecryptor(params, sk)
require.NoError(t, err)
ptHave := dec.DecryptNew(ctRLWE)
ptHave := rlwe.NewDecryptor(params, sk).DecryptNew(ctRLWE)
params.RingQ().INTT(ptHave.Value, ptHave.Value)
@@ -130,9 +114,7 @@ func TestRGSW(t *testing.T) {
t.Run("WriteAndRead", func(t *testing.T) {
ct := NewCiphertext(params, params.MaxLevelQ(), params.MaxLevelP(), 0)
enc, err := NewEncryptor(params, pk)
require.NoError(t, err)
enc.Encrypt(nil, ct)
NewEncryptor(params, pk).Encrypt(nil, ct)
buffer.RequireSerializerCorrect(t, ct)
})
}

View File

@@ -16,12 +16,12 @@ type Decryptor struct {
}
// NewDecryptor instantiates a new generic RLWE Decryptor.
func NewDecryptor(params ParameterProvider, sk *SecretKey) (*Decryptor, error) {
func NewDecryptor(params ParameterProvider, sk *SecretKey) *Decryptor {
p := params.GetRLWEParameters()
if sk.Value.Q.N() != p.N() {
return nil, fmt.Errorf("cannot NewDecryptor: secret_key ring degree does not match parameters ring degree")
panic(fmt.Errorf("cannot NewDecryptor: secret_key ring degree does not match parameters ring degree"))
}
return &Decryptor{
@@ -29,7 +29,7 @@ func NewDecryptor(params ParameterProvider, sk *SecretKey) (*Decryptor, error) {
ringQ: p.RingQ(),
buff: p.RingQ().NewPoly(),
sk: sk,
}, nil
}
}
// DecryptNew decrypts the Ciphertext and returns the result in a new Plaintext.

View File

@@ -17,7 +17,7 @@ type EncryptionKey interface {
}
// NewEncryptor creates a new Encryptor from either a public key or a private key.
func NewEncryptor(params ParameterProvider, key EncryptionKey) (*Encryptor, error) {
func NewEncryptor(params ParameterProvider, key EncryptionKey) *Encryptor {
p := *params.GetRLWEParameters()
@@ -29,15 +29,15 @@ func NewEncryptor(params ParameterProvider, key EncryptionKey) (*Encryptor, erro
case *SecretKey:
err = enc.checkSk(key)
case nil:
return newEncryptor(p), nil
return newEncryptor(p)
default:
return nil, fmt.Errorf("key must be either *rlwe.PublicKey, *rlwe.SecretKey or nil but have %T", key)
panic(fmt.Errorf("key must be either *rlwe.PublicKey, *rlwe.SecretKey or nil but have %T", key))
}
if err != nil {
return nil, fmt.Errorf("key is not correct: %w", err)
panic(fmt.Errorf("key is not correct: %w", err))
}
enc.encKey = key
return enc, nil
return enc
}
type Encryptor struct {
@@ -439,27 +439,26 @@ func (enc Encryptor) WithPRNG(prng sampling.PRNG) *Encryptor {
}
func (enc Encryptor) ShallowCopy() *Encryptor {
encSh, _ := NewEncryptor(enc.params, enc.encKey)
return encSh
return NewEncryptor(enc.params, enc.encKey)
}
func (enc Encryptor) WithKey(key EncryptionKey) (*Encryptor, error) {
func (enc Encryptor) WithKey(key EncryptionKey) *Encryptor {
switch key := key.(type) {
case *SecretKey:
if err := enc.checkSk(key); err != nil {
return nil, fmt.Errorf("cannot WithKey: %w", err)
panic(fmt.Errorf("cannot WithKey: %w", err))
}
case *PublicKey:
if err := enc.checkPk(key); err != nil {
return nil, fmt.Errorf("cannot WithKey: %w", err)
panic(fmt.Errorf("cannot WithKey: %w", err))
}
case nil:
return &enc, nil
return &enc
default:
return nil, fmt.Errorf("invalid key type, want *rlwe.SecretKey, *rlwe.PublicKey or nil but have %T", key)
panic(fmt.Errorf("invalid key type, want *rlwe.SecretKey, *rlwe.PublicKey or nil but have %T", key))
}
enc.encKey = key
return &enc, nil
return &enc
}
// checkPk checks that a given pk is correct for the parameters.

View File

@@ -16,12 +16,8 @@ type KeyGenerator struct {
// NewKeyGenerator creates a new KeyGenerator, from which the secret and public keys, as well as EvaluationKeys.
func NewKeyGenerator(params ParameterProvider) *KeyGenerator {
enc, err := NewEncryptor(params, nil)
if err != nil {
panic(err)
}
return &KeyGenerator{
Encryptor: enc,
Encryptor: NewEncryptor(params, nil),
}
}
@@ -70,60 +66,58 @@ func (kgen KeyGenerator) genSecretKeyFromSampler(sampler ring.Sampler, sk *Secre
}
// GenPublicKeyNew generates a new public key from the provided SecretKey.
func (kgen KeyGenerator) GenPublicKeyNew(sk *SecretKey) (pk *PublicKey, err error) {
func (kgen KeyGenerator) GenPublicKeyNew(sk *SecretKey) (pk *PublicKey) {
pk = NewPublicKey(kgen.params)
return pk, kgen.GenPublicKey(sk, pk)
kgen.GenPublicKey(sk, pk)
return
}
// GenPublicKey generates a public key from the provided SecretKey.
func (kgen KeyGenerator) GenPublicKey(sk *SecretKey, pk *PublicKey) (err error) {
enc, err := kgen.WithKey(sk)
if err != nil {
return fmt.Errorf("cannot GenPublicKey: %w", err)
}
return enc.EncryptZero(Operand[ringqp.Poly]{
func (kgen KeyGenerator) GenPublicKey(sk *SecretKey, pk *PublicKey) {
if err := kgen.WithKey(sk).EncryptZero(Operand[ringqp.Poly]{
MetaData: &MetaData{CiphertextMetaData: CiphertextMetaData{IsNTT: true, IsMontgomery: true}},
Value: []ringqp.Poly(pk.Value)})
Value: []ringqp.Poly(pk.Value),
}); err != nil {
panic(err)
}
}
// GenKeyPairNew generates a new SecretKey and a corresponding public key.
// Distribution is of the SecretKey set according to `rlwe.Parameters.HammingWeight()`.
func (kgen KeyGenerator) GenKeyPairNew() (sk *SecretKey, pk *PublicKey) {
sk = kgen.GenSecretKeyNew()
var err error
if pk, err = kgen.GenPublicKeyNew(sk); err != nil {
panic(err)
}
pk = kgen.GenPublicKeyNew(sk)
return
}
// GenRelinearizationKeyNew generates a new EvaluationKey that will be used to relinearize Ciphertexts during multiplication.
func (kgen KeyGenerator) GenRelinearizationKeyNew(sk *SecretKey, evkParams ...EvaluationKeyParameters) (rlk *RelinearizationKey, err error) {
func (kgen KeyGenerator) GenRelinearizationKeyNew(sk *SecretKey, evkParams ...EvaluationKeyParameters) (rlk *RelinearizationKey) {
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(kgen.params, evkParams)
rlk = &RelinearizationKey{EvaluationKey: EvaluationKey{GadgetCiphertext: *NewGadgetCiphertext(kgen.params, 1, levelQ, levelP, BaseTwoDecomposition)}}
return rlk, kgen.GenRelinearizationKey(sk, rlk)
kgen.GenRelinearizationKey(sk, rlk)
return
}
// GenRelinearizationKey generates an EvaluationKey that will be used to relinearize Ciphertexts during multiplication.
func (kgen KeyGenerator) GenRelinearizationKey(sk *SecretKey, rlk *RelinearizationKey) (err error) {
func (kgen KeyGenerator) GenRelinearizationKey(sk *SecretKey, rlk *RelinearizationKey) {
kgen.buffQP.Q.CopyValues(sk.Value.Q)
kgen.params.RingQ().AtLevel(rlk.LevelQ()).MulCoeffsMontgomery(kgen.buffQP.Q, sk.Value.Q, kgen.buffQP.Q)
return kgen.genEvaluationKey(kgen.buffQP.Q, sk.Value, &rlk.EvaluationKey)
kgen.genEvaluationKey(kgen.buffQP.Q, sk.Value, &rlk.EvaluationKey)
}
// GenGaloisKeyNew generates a new GaloisKey, enabling the automorphism X^{i} -> X^{i * galEl}.
func (kgen KeyGenerator) GenGaloisKeyNew(galEl uint64, sk *SecretKey, evkParams ...EvaluationKeyParameters) (gk *GaloisKey, err error) {
func (kgen KeyGenerator) GenGaloisKeyNew(galEl uint64, sk *SecretKey, evkParams ...EvaluationKeyParameters) (gk *GaloisKey) {
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(kgen.params, evkParams)
gk = &GaloisKey{
EvaluationKey: EvaluationKey{GadgetCiphertext: *NewGadgetCiphertext(kgen.params, 1, levelQ, levelP, BaseTwoDecomposition)},
NthRoot: kgen.params.GetRLWEParameters().RingQ().NthRoot(),
}
return gk, kgen.GenGaloisKey(galEl, sk, gk)
kgen.GenGaloisKey(galEl, sk, gk)
return
}
// GenGaloisKey generates a GaloisKey, enabling the automorphism X^{i} -> X^{i * galEl}.
func (kgen KeyGenerator) GenGaloisKey(galEl uint64, sk *SecretKey, gk *GaloisKey) (err error) {
func (kgen KeyGenerator) GenGaloisKey(galEl uint64, sk *SecretKey, gk *GaloisKey) {
skIn := sk.Value
skOut := kgen.buffQP
@@ -151,55 +145,42 @@ func (kgen KeyGenerator) GenGaloisKey(galEl uint64, sk *SecretKey, gk *GaloisKey
ringP.AutomorphismNTTWithIndex(skIn.P, index, skOut.P)
}
if err = kgen.genEvaluationKey(skIn.Q, skOut, &gk.EvaluationKey); err != nil {
return fmt.Errorf("cannot GenGaloisKey: %w", err)
}
kgen.genEvaluationKey(skIn.Q, skOut, &gk.EvaluationKey)
gk.GaloisElement = galEl
gk.NthRoot = ringQ.NthRoot()
return
}
// GenGaloisKeys generates the GaloisKey objects for all galois elements in galEls, and stores
// the resulting key for galois element i in gks[i].
// The galEls and gks parameters must have the same length.
func (kgen KeyGenerator) GenGaloisKeys(galEls []uint64, sk *SecretKey, gks []*GaloisKey) (err error) {
func (kgen KeyGenerator) GenGaloisKeys(galEls []uint64, sk *SecretKey, gks []*GaloisKey) {
if len(galEls) != len(gks) {
return fmt.Errorf("galEls and gks must have the same length")
panic(fmt.Errorf("galEls and gks must have the same length"))
}
for i, galEl := range galEls {
if gks[i] == nil {
if gks[i], err = kgen.GenGaloisKeyNew(galEl, sk); err != nil {
return
}
gks[i] = kgen.GenGaloisKeyNew(galEl, sk)
} else {
return kgen.GenGaloisKey(galEl, sk, gks[i])
kgen.GenGaloisKey(galEl, sk, gks[i])
}
}
return nil
}
// GenGaloisKeysNew generates the GaloisKey objects for all galois elements in galEls, and
// returns the resulting keys in a newly allocated []*GaloisKey.
func (kgen KeyGenerator) GenGaloisKeysNew(galEls []uint64, sk *SecretKey, evkParams ...EvaluationKeyParameters) (gks []*GaloisKey, err error) {
func (kgen KeyGenerator) GenGaloisKeysNew(galEls []uint64, sk *SecretKey, evkParams ...EvaluationKeyParameters) (gks []*GaloisKey) {
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(kgen.params, evkParams)
gks = make([]*GaloisKey, len(galEls))
for i, galEl := range galEls {
gks[i] = newGaloisKey(kgen.params, levelQ, levelP, BaseTwoDecomposition)
if err = kgen.GenGaloisKey(galEl, sk, gks[i]); err != nil {
return
}
kgen.GenGaloisKey(galEl, sk, gks[i])
}
return
}
// GenEvaluationKeysForRingSwapNew generates the necessary EvaluationKeys to switch from a standard ring to to a conjugate invariant ring and vice-versa.
func (kgen KeyGenerator) GenEvaluationKeysForRingSwapNew(skStd, skConjugateInvariant *SecretKey, evkParams ...EvaluationKeyParameters) (stdToci, ciToStd *EvaluationKey, err error) {
func (kgen KeyGenerator) GenEvaluationKeysForRingSwapNew(skStd, skConjugateInvariant *SecretKey, evkParams ...EvaluationKeyParameters) (stdToci, ciToStd *EvaluationKey) {
levelQ := utils.Min(skStd.Value.Q.Level(), skConjugateInvariant.Value.Q.Level())
@@ -213,14 +194,10 @@ func (kgen KeyGenerator) GenEvaluationKeysForRingSwapNew(skStd, skConjugateInvar
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(kgen.params, evkParams)
stdToci = newEvaluationKey(kgen.params, levelQ, levelP, BaseTwoDecomposition)
if err = kgen.GenEvaluationKey(skStd, skCIMappedToStandard, stdToci); err != nil {
return
}
kgen.GenEvaluationKey(skStd, skCIMappedToStandard, stdToci)
ciToStd = newEvaluationKey(kgen.params, levelQ, levelP, BaseTwoDecomposition)
if err = kgen.GenEvaluationKey(skCIMappedToStandard, skStd, ciToStd); err != nil {
return
}
kgen.GenEvaluationKey(skCIMappedToStandard, skStd, ciToStd)
return
}
@@ -234,10 +211,11 @@ func (kgen KeyGenerator) GenEvaluationKeysForRingSwapNew(skStd, skConjugateInvar
// using SwitchCiphertextRingDegreeNTT(ctSmallDim, nil, ctLargeDim).
// When re-encrypting a Ciphertext from X^{N} to Y^{N/n}, the output of the re-encryption is in still X^{N} and
// must be mapped Y^{N/n} using SwitchCiphertextRingDegreeNTT(ctLargeDim, ringQLargeDim, ctSmallDim).
func (kgen KeyGenerator) GenEvaluationKeyNew(skInput, skOutput *SecretKey, evkParams ...EvaluationKeyParameters) (evk *EvaluationKey, err error) {
func (kgen KeyGenerator) GenEvaluationKeyNew(skInput, skOutput *SecretKey, evkParams ...EvaluationKeyParameters) (evk *EvaluationKey) {
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(kgen.params, evkParams)
evk = newEvaluationKey(kgen.params, levelQ, levelP, BaseTwoDecomposition)
return evk, kgen.GenEvaluationKey(skInput, skOutput, evk)
kgen.GenEvaluationKey(skInput, skOutput, evk)
return
}
// GenEvaluationKey generates an EvaluationKey, that will re-encrypt a Ciphertext encrypted under the input key into the output key.
@@ -249,7 +227,7 @@ func (kgen KeyGenerator) GenEvaluationKeyNew(skInput, skOutput *SecretKey, evkPa
// using SwitchCiphertextRingDegreeNTT(ctSmallDim, nil, ctLargeDim).
// When re-encrypting a Ciphertext from X^{N} to Y^{N/n}, the output of the re-encryption is in still X^{N} and
// must be mapped Y^{N/n} using SwitchCiphertextRingDegreeNTT(ctLargeDim, ringQLargeDim, ctSmallDim).
func (kgen KeyGenerator) GenEvaluationKey(skInput, skOutput *SecretKey, evk *EvaluationKey) (err error) {
func (kgen KeyGenerator) GenEvaluationKey(skInput, skOutput *SecretKey, evk *EvaluationKey) {
ringQ := kgen.params.RingQ()
ringP := kgen.params.RingP()
@@ -266,7 +244,7 @@ func (kgen KeyGenerator) GenEvaluationKey(skInput, skOutput *SecretKey, evk *Eva
ring.MapSmallDimensionToLargerDimensionNTT(skInput.Value.Q, kgen.buffQ[0])
kgen.extendQ2P(ringQ, ringQ.AtLevel(skOutput.Value.Q.Level()), kgen.buffQ[0], kgen.buffQ[1], kgen.buffQ[0])
return kgen.genEvaluationKey(kgen.buffQ[0], kgen.buffQP, evk)
kgen.genEvaluationKey(kgen.buffQ[0], kgen.buffQP, evk)
}
func (kgen KeyGenerator) extendQ2P2(levelP int, polQ, buff, polP ring.Poly) {
@@ -340,21 +318,21 @@ func (kgen KeyGenerator) extendQ2P(rQ, rP *ring.Ring, polQ, buff, polP ring.Poly
rP.MForm(polP, polP)
}
func (kgen KeyGenerator) genEvaluationKey(skIn ring.Poly, skOut ringqp.Poly, evk *EvaluationKey) (err error) {
func (kgen KeyGenerator) genEvaluationKey(skIn ring.Poly, skOut ringqp.Poly, evk *EvaluationKey) {
enc := kgen.WithKey(&SecretKey{Value: skOut})
enc, err := kgen.WithKey(&SecretKey{Value: skOut})
if err != nil {
return err
}
// Samples an encryption of zero for each element of the EvaluationKey.
for i := 0; i < len(evk.Value); i++ {
for j := 0; j < len(evk.Value[i]); j++ {
if err = enc.EncryptZero(Operand[ringqp.Poly]{MetaData: &MetaData{CiphertextMetaData: CiphertextMetaData{IsNTT: true, IsMontgomery: true}}, Value: []ringqp.Poly(evk.Value[i][j])}); err != nil {
return
if err := enc.EncryptZero(Operand[ringqp.Poly]{MetaData: &MetaData{CiphertextMetaData: CiphertextMetaData{IsNTT: true, IsMontgomery: true}}, Value: []ringqp.Poly(evk.Value[i][j])}); err != nil {
panic(err)
}
}
}
// Adds the plaintext (input-key) to the EvaluationKey.
return AddPolyTimesGadgetVectorToGadgetCiphertext(skIn, []GadgetCiphertext{evk.GadgetCiphertext}, *kgen.params.RingQP(), kgen.buffQ[0])
if err := AddPolyTimesGadgetVectorToGadgetCiphertext(skIn, []GadgetCiphertext{evk.GadgetCiphertext}, *kgen.params.RingQP(), kgen.buffQ[0]); err != nil {
panic(err)
}
}

View File

@@ -82,10 +82,7 @@ func benchEncryptor(tc *TestContext, bpw2 int, b *testing.B) {
b.Run(testString(params, params.MaxLevelQ(), params.MaxLevelP(), bpw2, "Encryptor/EncryptZero/SecretKey"), func(b *testing.B) {
ct := NewCiphertext(params, 1, params.MaxLevel())
enc, err := tc.enc.WithKey(tc.sk)
if err != nil {
b.Fatal(err)
}
enc := tc.enc.WithKey(tc.sk)
b.ResetTimer()
for i := 0; i < b.N; i++ {
enc.EncryptZero(ct)
@@ -95,10 +92,7 @@ func benchEncryptor(tc *TestContext, bpw2 int, b *testing.B) {
b.Run(testString(params, params.MaxLevelQ(), params.MaxLevelP(), bpw2, "Encryptor/EncryptZero/PublicKey"), func(b *testing.B) {
ct := NewCiphertext(params, 1, params.MaxLevel())
enc, err := tc.enc.WithKey(tc.pk)
if err != nil {
b.Fatal(err)
}
enc := tc.enc.WithKey(tc.pk)
b.ResetTimer()
for i := 0; i < b.N; i++ {
enc.EncryptZero(ct)
@@ -130,19 +124,11 @@ func benchEvaluator(tc *TestContext, bpw2 int, b *testing.B) {
b.Run(testString(params, params.MaxLevelQ(), params.MaxLevelP(), bpw2, "Evaluator/GadgetProduct"), func(b *testing.B) {
enc, err := NewEncryptor(params, sk)
if err != nil {
b.Fatal(err)
}
enc := NewEncryptor(params, sk)
ct := enc.EncryptZeroNew(params.MaxLevel())
evk, err := kgen.GenEvaluationKeyNew(sk, kgen.GenSecretKeyNew())
if err != nil {
b.Fatal(err)
}
evk := kgen.GenEvaluationKeyNew(sk, kgen.GenSecretKeyNew())
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -155,11 +141,7 @@ func benchMarshalling(tc *TestContext, bpw2 int, b *testing.B) {
params := tc.params
sk := tc.sk
enc, err := NewEncryptor(params, sk)
if err != nil {
b.Fatal(err)
}
enc := NewEncryptor(params, sk)
ctf := enc.EncryptZeroNew(params.MaxLevel())

View File

@@ -155,22 +155,13 @@ func NewTestContext(params Parameters) (tc *TestContext, err error) {
kgen := NewKeyGenerator(params)
sk := kgen.GenSecretKeyNew()
pk, err := kgen.GenPublicKeyNew(sk)
if err != nil {
return nil, err
}
pk := kgen.GenPublicKeyNew(sk)
eval := NewEvaluator(params, nil)
enc, err := NewEncryptor(params, sk)
if err != nil {
return nil, err
}
enc := NewEncryptor(params, sk)
dec, err := NewDecryptor(params, sk)
if err != nil {
return nil, err
}
dec := NewDecryptor(params, sk)
return &TestContext{
params: params,
@@ -378,12 +369,7 @@ func testEncryptor(tc *TestContext, level, bpw2 int, t *testing.T) {
pt := NewPlaintext(params, level)
ct := NewCiphertext(params, 1, level)
encPk, err := enc.WithKey(pk)
//encPk, err := enc.WithKey(pk)
require.NoError(t, err)
require.NoError(t, encPk.Encrypt(pt, ct))
enc.WithKey(pk).Encrypt(pt, ct)
dec.Decrypt(ct, pt)
@@ -397,8 +383,7 @@ func testEncryptor(tc *TestContext, level, bpw2 int, t *testing.T) {
})
t.Run(testString(params, level, params.MaxLevelP(), bpw2, "Encryptor/Encrypt/Pk/ShallowCopy"), func(t *testing.T) {
pkEnc1, err := enc.WithKey(pk)
require.NoError(t, err)
pkEnc1 := enc.WithKey(pk)
pkEnc2 := pkEnc1.ShallowCopy()
require.True(t, pkEnc1.params.Equal(pkEnc2.params))
require.True(t, pkEnc1.encKey == pkEnc2.encKey)
@@ -428,8 +413,7 @@ func testEncryptor(tc *TestContext, level, bpw2 int, t *testing.T) {
pt := NewPlaintext(params, level)
enc, err := NewEncryptor(params, sk)
require.NoError(t, err)
enc := NewEncryptor(params, sk)
ct := NewCiphertext(params, 1, level)
@@ -452,8 +436,7 @@ func testEncryptor(tc *TestContext, level, bpw2 int, t *testing.T) {
})
t.Run(testString(params, level, params.MaxLevelP(), bpw2, "Encrypt/Sk/ShallowCopy"), func(t *testing.T) {
skEnc1, err := NewEncryptor(params, sk)
require.NoError(t, err)
skEnc1 := NewEncryptor(params, sk)
skEnc2 := skEnc1.ShallowCopy()
require.True(t, skEnc1.params.Equal(skEnc2.params))
@@ -466,11 +449,8 @@ func testEncryptor(tc *TestContext, level, bpw2 int, t *testing.T) {
t.Run(testString(params, level, params.MaxLevelP(), bpw2, "Encrypt/WithKey/Sk->Sk"), func(t *testing.T) {
sk2 := kgen.GenSecretKeyNew()
skEnc1, err := NewEncryptor(params, sk)
require.NoError(t, err)
skEnc2, err := skEnc1.WithKey(sk2)
require.NoError(t, err)
skEnc1 := NewEncryptor(params, sk)
skEnc2 := skEnc1.WithKey(sk2)
require.True(t, skEnc1.params.Equal(skEnc2.params))
require.True(t, skEnc1.encKey == sk)
require.True(t, skEnc2.encKey == sk2)
@@ -519,14 +499,13 @@ func testGadgetProduct(tc *TestContext, levelQ, bpw2 int, t *testing.T) {
evk := NewEvaluationKey(params, evkParams)
// Generate the evaluationkey [-bs1 + s1, b]
require.NoError(t, kgen.GenEvaluationKey(sk, skOut, evk))
kgen.GenEvaluationKey(sk, skOut, evk)
// Gadget product: ct = [-cs1 + as0 , c]
eval.GadgetProduct(levelQ, a, &evk.GadgetCiphertext, ct)
// pt = as0
dec, err := NewDecryptor(params, skOut)
require.NoError(t, err)
dec := NewDecryptor(params, skOut)
pt := dec.DecryptNew(ct)
@@ -574,10 +553,7 @@ func testGadgetProduct(tc *TestContext, levelQ, bpw2 int, t *testing.T) {
eval.GadgetProductHoisted(levelQ, eval.BuffDecompQP, &evk.GadgetCiphertext, ct)
// pt = as0
dec, err := NewDecryptor(params, skOut)
require.NoError(t, err)
pt := dec.DecryptNew(ct)
pt := NewDecryptor(params, skOut).DecryptNew(ct)
ringQ := params.RingQ().AtLevel(levelQ)
@@ -619,15 +595,9 @@ func testApplyEvaluationKey(tc *TestContext, level, bpw2 int, t *testing.T) {
enc.Encrypt(pt, ct)
// Test that Dec(KS(Enc(ct, sk), skOut), skOut) has a small norm
evk, err := kgen.GenEvaluationKeyNew(sk, skOut, evkParams)
require.NoError(t, err)
eval.ApplyEvaluationKey(ct, kgen.GenEvaluationKeyNew(sk, skOut, evkParams), ct)
eval.ApplyEvaluationKey(ct, evk, ct)
dec, err := NewDecryptor(params, skOut)
require.NoError(t, err)
dec.Decrypt(ct, pt)
NewDecryptor(params, skOut).Decrypt(ct, pt)
ringQ := params.RingQ().AtLevel(level)
@@ -656,11 +626,9 @@ func testApplyEvaluationKey(tc *TestContext, level, bpw2 int, t *testing.T) {
kgenSmallDim := NewKeyGenerator(paramsSmallDim)
skSmallDim := kgenSmallDim.GenSecretKeyNew()
evk, err := kgenLargeDim.GenEvaluationKeyNew(skLargeDim, skSmallDim, evkParams)
require.NoError(t, err)
evk := kgenLargeDim.GenEvaluationKeyNew(skLargeDim, skSmallDim, evkParams)
enc, err := NewEncryptor(paramsLargeDim, skLargeDim)
require.NoError(t, err)
enc := NewEncryptor(paramsLargeDim, skLargeDim)
ctLargeDim := enc.EncryptZeroNew(level)
@@ -670,8 +638,7 @@ func testApplyEvaluationKey(tc *TestContext, level, bpw2 int, t *testing.T) {
eval.ApplyEvaluationKey(ctLargeDim, evk, ctSmallDim)
// Decrypts with smaller dimension key
dec, err := NewDecryptor(paramsSmallDim, skSmallDim)
require.NoError(t, err)
dec := NewDecryptor(paramsSmallDim, skSmallDim)
ptSmallDim := dec.DecryptNew(ctSmallDim)
@@ -701,13 +668,9 @@ func testApplyEvaluationKey(tc *TestContext, level, bpw2 int, t *testing.T) {
kgenSmallDim := NewKeyGenerator(paramsSmallDim)
skSmallDim := kgenSmallDim.GenSecretKeyNew()
evk, err := kgenLargeDim.GenEvaluationKeyNew(skSmallDim, skLargeDim, evkParams)
require.NoError(t, err)
evk := kgenLargeDim.GenEvaluationKeyNew(skSmallDim, skLargeDim, evkParams)
enc, err := NewEncryptor(paramsSmallDim, skSmallDim)
require.NoError(t, err)
ctSmallDim := enc.EncryptZeroNew(level)
ctSmallDim := NewEncryptor(paramsSmallDim, skSmallDim).EncryptZeroNew(level)
ctLargeDim := NewCiphertext(paramsLargeDim, 1, level)
@@ -753,12 +716,8 @@ func testAutomorphism(tc *TestContext, level, bpw2 int, t *testing.T) {
// Chooses a Galois Element (must be coprime with 2N)
galEl := params.GaloisElement(-1)
// Generate the GaloisKey
gk, err := kgen.GenGaloisKeyNew(galEl, sk, evkParams)
require.NoError(t, err)
// Allocate a new EvaluationKeySet and adds the GaloisKey
evk := NewMemEvaluationKeySet(nil, gk)
evk := NewMemEvaluationKeySet(nil, kgen.GenGaloisKeyNew(galEl, sk, evkParams))
// Evaluate the automorphism
eval.WithKey(evk).Automorphism(ct, galEl, ct)
@@ -804,12 +763,8 @@ func testAutomorphism(tc *TestContext, level, bpw2 int, t *testing.T) {
// Chooses a Galois Element (must be coprime with 2N)
galEl := params.GaloisElement(-1)
// Generate the GaloisKey
gk, err := kgen.GenGaloisKeyNew(galEl, sk, evkParams)
require.NoError(t, err)
// Allocate a new EvaluationKeySet and adds the GaloisKey
evk := NewMemEvaluationKeySet(nil, gk)
evk := NewMemEvaluationKeySet(nil, kgen.GenGaloisKeyNew(galEl, sk, evkParams))
//Decompose the ciphertext
eval.DecomposeNTT(level, params.MaxLevelP(), params.MaxLevelP()+1, ct.Value[1], ct.IsNTT, eval.BuffDecompQP)
@@ -858,12 +813,8 @@ func testAutomorphism(tc *TestContext, level, bpw2 int, t *testing.T) {
// Chooses a Galois Element (must be coprime with 2N)
galEl := params.GaloisElement(-1)
// Generate the GaloisKey
gk, err := kgen.GenGaloisKeyNew(galEl, sk, evkParams)
require.NoError(t, err)
// Allocate a new EvaluationKeySet and adds the GaloisKey
evk := NewMemEvaluationKeySet(nil, gk)
evk := NewMemEvaluationKeySet(nil, kgen.GenGaloisKeyNew(galEl, sk, evkParams))
//Decompose the ciphertext
eval.DecomposeNTT(level, params.MaxLevelP(), params.MaxLevelP()+1, ct.Value[1], ct.IsNTT, eval.BuffDecompQP)
@@ -945,10 +896,7 @@ func testSlotOperations(tc *TestContext, level, bpw2 int, t *testing.T) {
enc.Encrypt(pt, ctIn)
// GaloisKeys
var gks, err = kgen.GenGaloisKeysNew(GaloisElementsForExpand(params, logN), sk, evkParams)
require.NoError(t, err)
evk := NewMemEvaluationKeySet(nil, gks...)
evk := NewMemEvaluationKeySet(nil, kgen.GenGaloisKeysNew(GaloisElementsForExpand(params, logN), sk, evkParams)...)
eval := NewEvaluator(params, evk)
@@ -1016,10 +964,7 @@ func testSlotOperations(tc *TestContext, level, bpw2 int, t *testing.T) {
}
// Galois Keys
gks, err := kgen.GenGaloisKeysNew(GaloisElementsForPack(params, params.LogN()), sk, evkParams)
require.NoError(t, err)
evk := NewMemEvaluationKeySet(nil, gks...)
evk := NewMemEvaluationKeySet(nil, kgen.GenGaloisKeysNew(GaloisElementsForPack(params, params.LogN()), sk, evkParams)...)
ct, err := eval.WithKey(evk).Pack(ciphertexts, params.LogN(), false)
require.NoError(t, err)
@@ -1091,10 +1036,7 @@ func testSlotOperations(tc *TestContext, level, bpw2 int, t *testing.T) {
}
// Galois Keys
gks, err := kgen.GenGaloisKeysNew(GaloisElementsForPack(params, params.LogN()-1), sk, evkParams)
require.NoError(t, err)
evk := NewMemEvaluationKeySet(nil, gks...)
evk := NewMemEvaluationKeySet(nil, kgen.GenGaloisKeysNew(GaloisElementsForPack(params, params.LogN()-1), sk, evkParams)...)
ct, err := eval.WithKey(evk).Pack(ciphertexts, params.LogN()-1, true)
require.NoError(t, err)
@@ -1134,12 +1076,9 @@ func testSlotOperations(tc *TestContext, level, bpw2 int, t *testing.T) {
require.NoError(t, err)
// Galois Keys
gks, err := kgen.GenGaloisKeysNew(GaloisElementsForInnerSum(params, batch, n), sk)
require.NoError(t, err)
evk := NewMemEvaluationKeySet(nil, kgen.GenGaloisKeysNew(GaloisElementsForInnerSum(params, batch, n), sk)...)
evk := NewMemEvaluationKeySet(nil, gks...)
eval.WithKey(evk).InnerSum(ct, batch, n, ct)
require.NoError(t, eval.WithKey(evk).InnerSum(ct, batch, n, ct))
dec.Decrypt(ct, pt)
@@ -1275,34 +1214,22 @@ func testWriteAndRead(tc *TestContext, bpw2 int, t *testing.T) {
})
t.Run(testString(params, levelQ, levelP, bpw2, "WriteAndRead/EvaluationKey"), func(t *testing.T) {
evk, err := tc.kgen.GenEvaluationKeyNew(sk, sk)
require.NoError(t, err)
buffer.RequireSerializerCorrect(t, evk)
buffer.RequireSerializerCorrect(t, tc.kgen.GenEvaluationKeyNew(sk, sk))
})
t.Run(testString(params, levelQ, levelP, bpw2, "WriteAndRead/RelinearizationKey"), func(t *testing.T) {
rlk, err := tc.kgen.GenRelinearizationKeyNew(tc.sk)
require.NoError(t, err)
buffer.RequireSerializerCorrect(t, rlk)
buffer.RequireSerializerCorrect(t, tc.kgen.GenRelinearizationKeyNew(tc.sk))
})
t.Run(testString(params, levelQ, levelP, bpw2, "WriteAndRead/GaloisKey"), func(t *testing.T) {
gk, err := tc.kgen.GenGaloisKeyNew(5, tc.sk)
require.NoError(t, err)
buffer.RequireSerializerCorrect(t, gk)
buffer.RequireSerializerCorrect(t, tc.kgen.GenGaloisKeyNew(5, tc.sk))
})
t.Run(testString(params, levelQ, levelP, bpw2, "WriteAndRead/EvaluationKeySet"), func(t *testing.T) {
rlk, err := tc.kgen.GenRelinearizationKeyNew(tc.sk)
require.NoError(t, err)
galEl := uint64(5)
gk, err := tc.kgen.GenGaloisKeyNew(galEl, tc.sk)
require.NoError(t, err)
buffer.RequireSerializerCorrect(t, &MemEvaluationKeySet{
Rlk: rlk,
Gks: map[uint64]*GaloisKey{galEl: gk},
Rlk: tc.kgen.GenRelinearizationKeyNew(tc.sk),
Gks: map[uint64]*GaloisKey{galEl: tc.kgen.GenGaloisKeyNew(galEl, tc.sk)},
})
})
}