Merge branch 'main' into serialization-compressed-keys

This commit is contained in:
lehugueni
2024-11-18 14:04:40 +01:00
4 changed files with 230 additions and 0 deletions

View File

@@ -99,6 +99,29 @@ func newEncryptor(params Parameters) *Encryptor {
}
}
// NewTestEncryptorWithPRNG creates a new [Encryptor] that uses the provided prng for randomness.
// CAUTION: THIS FUNCTION SHOULD BE USED FOR TESTING PURPOSES ONLY.
func NewTestEncryptorWithPRNG(params ParameterProvider, key EncryptionKey, prng sampling.PRNG) *Encryptor {
p := *params.GetRLWEParameters()
enc := NewEncryptor(params, key)
xeSampler, err := ring.NewSampler(prng, p.RingQ(), p.Xe(), false)
if err != nil {
panic(fmt.Errorf("NewEncryptorWithPRNG: cannot create xeSampler %w", err))
}
xsSampler, err := ring.NewSampler(prng, p.RingQ(), p.Xs(), false)
if err != nil {
panic(fmt.Errorf("NewEncryptorWithPRNG: cannot create xsSampler %w", err))
}
uniformSampler := ringqp.NewUniformSampler(prng, *p.RingQP())
enc.prng = prng
enc.xeSampler = xeSampler
enc.xsSampler = xsSampler
enc.uniformSampler = uniformSampler
return enc
}
type encryptorBuffers struct {
buffQP [3]ringqp.Poly
}

View File

@@ -1,6 +1,7 @@
package rlwe
import (
"encoding/base64"
"encoding/json"
"flag"
"fmt"
@@ -8,6 +9,8 @@ import (
"runtime"
"testing"
"golang.org/x/crypto/blake2b"
"github.com/stretchr/testify/require"
"github.com/tuneinsight/lattigo/v6/ring"
@@ -31,6 +34,86 @@ func testString(params Parameters, levelQ, levelP, bpw2 int, opname string) stri
params.RingType())
}
// TestRLWEConstSerialization test detects (fails) if the serialization of
// [PublicKey], [SecretKey], [Ciphertext], [GaloisKey], [MemEvaluationKeySet] has changed.
// If such a modification is intended, this test must be updated and users notified s.t.
// old serialized objects can be converted to the new format.
func TestRLWEConstSerialization(t *testing.T) {
// Note: changing nbIteration will change the expected value
const nbIteration = 10
const expected = "XRdlwx5vEX9qdGY3CeeAxzGHa0gbXghzpLhV0eIgVk8="
var err error
defaultParamsLiteral := testInsecure
seedKeyGen := []byte{'l', 'a', 't'}
seedEnc := []byte{'t', 'i', 'g', 'o'}
hash, err := blake2b.New(32, nil)
require.Nil(t, err)
for _, paramsLit := range defaultParamsLiteral[:] {
for _, NTTFlag := range []bool{true, false}[:] {
for _, RingType := range []ring.Type{ring.Standard, ring.ConjugateInvariant}[:] {
paramsLit.NTTFlag = NTTFlag
paramsLit.RingType = RingType
var params Parameters
if params, err = NewParametersFromLiteral(paramsLit.ParametersLiteral); err != nil {
t.Fatal(err)
}
detTC, err := NewDeterministicTestContext(params, seedKeyGen, seedEnc)
require.Nil(t, err)
for i := 0; i < nbIteration; i++ {
// Add marshalled (sk, pk) to the hash input
sk, pk := detTC.kgen.GenKeyPairNew()
skBytes, err := sk.MarshalBinary()
hash.Write(skBytes)
require.Nil(t, err)
pkBytes, err := pk.MarshalBinary()
require.Nil(t, err)
hash.Write(pkBytes)
// Add marshalled GaloisKey to the hash input
galEl := params.GaloisElement(-1)
galEl2 := params.GaloisElement(3)
galKey := detTC.kgen.GenGaloisKeysNew([]uint64{galEl, galEl2}, sk)
galKeyBytes, err := galKey[0].MarshalBinary()
require.Nil(t, err)
hash.Write(galKeyBytes)
// Add marshalled MemEvaluationKeySet to the hash input
relinKey := detTC.kgen.GenRelinearizationKeyNew(sk)
evk := NewMemEvaluationKeySet(relinKey, galKey...)
evkBytes, err := evk.MarshalBinary()
require.Nil(t, err)
hash.Write(evkBytes)
// Add marshalled MemEvaluationKeySet to the hash input
ct := NewCiphertext(params, 1, params.MaxLevel())
pt := genPlaintext(params, params.MaxLevel(), (1<<int(params.LogQ()))-1)
detTC.enc.Encrypt(pt, ct)
ctBytes, err := ct.MarshalBinary()
require.Nil(t, err)
hash.Write(ctBytes)
ctJSON, err := ct.MarshalJSON()
require.Nil(t, err)
hash.Write(ctJSON)
}
}
}
}
digest := base64.StdEncoding.EncodeToString(hash.Sum(nil))
// In case the value expected must be updated, uncomment to print the new expected value:
// fmt.Println(digest)
require.Equal(t, expected, digest)
}
func TestRLWE(t *testing.T) {
var err error
@@ -219,6 +302,40 @@ func testUserDefinedParameters(t *testing.T) {
}
func NewDeterministicTestContext(params Parameters, seedKeyGen, seedEnc []byte) (tc *TestContext, err error) {
prngKGen, err := sampling.NewKeyedPRNG(seedKeyGen)
if err != nil {
panic(fmt.Errorf("NewDeterministicTestContext: failed to make prngKGen %w", err))
}
prngEnc, err := sampling.NewKeyedPRNG(seedEnc)
if err != nil {
panic(fmt.Errorf("NewDeterministicTestContext: failed to make prngEnc %w", err))
}
kgen := NewKeyGenerator(params)
kgenEncryptor := NewTestEncryptorWithPRNG(params, nil, prngKGen)
kgen.Encryptor = kgenEncryptor
sk := kgen.GenSecretKeyNew()
pk := kgen.GenPublicKeyNew(sk)
eval := NewEvaluator(params, nil)
enc := NewTestEncryptorWithPRNG(params, sk, prngEnc)
dec := NewDecryptor(params, sk)
return &TestContext{
params: params,
kgen: kgen,
sk: sk,
pk: pk,
enc: enc,
dec: dec,
eval: eval,
}, nil
}
func NewTestContext(params Parameters) (tc *TestContext, err error) {
kgen := NewKeyGenerator(params)
sk := kgen.GenSecretKeyNew()

View File

@@ -1,6 +1,7 @@
package bgv
import (
"encoding/base64"
"encoding/json"
"flag"
"fmt"
@@ -9,6 +10,7 @@ import (
"testing"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/blake2b"
"github.com/tuneinsight/lattigo/v6/core/rlwe"
"github.com/tuneinsight/lattigo/v6/ring"
@@ -871,6 +873,49 @@ func testEvaluatorBfv(tc *TestContext, t *testing.T) {
})
}
// TestBGVParamsConstSerialization test detects (fails) if the serialization of [Parameters] has changed.
// If such a modification is intended, this test must be updated and users notified s.t.
// old serialized parameters can be converted to the new format.
func TestBGVParamsConstSerialization(t *testing.T) {
const expected = "7aw0pU3xCs2Hu8zHKqkPRUpltHC0+P+UxzMSqKJwSFs="
var err error
distribs := []ring.DistributionParameters{rlwe.DefaultXe, rlwe.DefaultXs, ring.Ternary{H: 192}}
hash, err := blake2b.New(32, nil)
if err != nil {
t.Fatal(err)
}
// Test with different CKKS params, including different plaintext moduli and distributions
for _, paramsLit := range []ParametersLiteral{ExampleParameters128BitLogN14LogQP438, testInsecure}[:] {
for _, ptMod := range testPlaintextModulus[:] {
for _, distXe := range distribs {
for _, distXs := range distribs {
paramsLit.Xe = distXe
paramsLit.Xs = distXs
paramsLit.PlaintextModulus = ptMod
var params Parameters
if params, err = NewParametersFromLiteral(paramsLit); err != nil {
t.Fatal(err)
}
paramsBytes, err := params.MarshalBinary()
require.Nil(t, err)
hash.Write(paramsBytes)
paramsBytes, err = params.MarshalJSON()
require.Nil(t, err)
hash.Write(paramsBytes)
}
}
}
}
digest := base64.StdEncoding.EncodeToString(hash.Sum(nil))
// In case the value expected must be updated, uncomment to print the new expected value:
// fmt.Println(digest)
require.Equal(t, expected, digest)
}
var (
// testInsecure are insecure parameters used for the sole purpose of fast testing.
testInsecure = ParametersLiteral{

View File

@@ -1,6 +1,7 @@
package ckks
import (
"encoding/base64"
"encoding/json"
"flag"
"fmt"
@@ -10,6 +11,7 @@ import (
"testing"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/blake2b"
"github.com/tuneinsight/lattigo/v6/core/rlwe"
"github.com/tuneinsight/lattigo/v6/ring"
@@ -798,6 +800,49 @@ func testBridge(tc *TestContext, t *testing.T) {
})
}
// TestCKKSParamsConstSerialization test detects (fails) if the serialization of [Parameters] has changed.
// If such a modification is intended, this test must be updated and users notified s.t.
// old serialized parameters can be converted to the new format.
func TestCKKSParamsConstSerialization(t *testing.T) {
const expected = "Bo962QjkASlly6oMAojaEYOIGTh5v0nhzWvu93XgVRk="
var err error
distribs := []ring.DistributionParameters{rlwe.DefaultXe, rlwe.DefaultXs, ring.Ternary{H: 192}}
hash, err := blake2b.New(32, nil)
if err != nil {
t.Fatal(err)
}
// Test with different CKKS params, including different ringtypes and distributions
for _, paramsLit := range testParametersLiteral[:] {
for _, ringType := range []ring.Type{ring.Standard, ring.ConjugateInvariant}[:] {
for _, distXe := range distribs {
for _, distXs := range distribs {
paramsLit.RingType = ringType
paramsLit.Xe = distXe
paramsLit.Xs = distXs
var params Parameters
if params, err = NewParametersFromLiteral(paramsLit); err != nil {
t.Fatal(err)
}
paramsBytes, err := params.MarshalBinary()
require.Nil(t, err)
hash.Write(paramsBytes)
paramsBytes, err = params.MarshalJSON()
require.Nil(t, err)
hash.Write(paramsBytes)
}
}
}
}
digest := base64.StdEncoding.EncodeToString(hash.Sum(nil))
// In case the value expected must be updated, uncomment to print the new expected value:
// fmt.Println(digest)
require.Equal(t, expected, digest)
}
func name(opname string, tc *TestContext) string {
var precMode string