From 5da9d799fa3e0deb58efbd6e660d870c1a59b031 Mon Sep 17 00:00:00 2001 From: lehugueni Date: Mon, 14 Oct 2024 08:51:31 +0200 Subject: [PATCH 1/3] detect serialization changes --- core/rlwe/encryptor.go | 23 ++++++++ core/rlwe/rlwe_test.go | 117 ++++++++++++++++++++++++++++++++++++++ schemes/bgv/bgv_test.go | 42 ++++++++++++++ schemes/ckks/ckks_test.go | 42 ++++++++++++++ 4 files changed, 224 insertions(+) diff --git a/core/rlwe/encryptor.go b/core/rlwe/encryptor.go index fa59990b..a3b06744 100644 --- a/core/rlwe/encryptor.go +++ b/core/rlwe/encryptor.go @@ -99,6 +99,29 @@ func newEncryptor(params Parameters) *Encryptor { } } +// NewEncryptorWithPRNG creates a new [Encryptor] that uses the provided prng for randomness. +// CAUTION: THIS FUNCTION SHOULD BE USED FOR TESTING PURPOSES ONLY. +func NewEncryptorWithPRNG(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 } diff --git a/core/rlwe/rlwe_test.go b/core/rlwe/rlwe_test.go index 8ce2201d..10951979 100644 --- a/core/rlwe/rlwe_test.go +++ b/core/rlwe/rlwe_test.go @@ -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< Date: Tue, 15 Oct 2024 14:53:26 +0200 Subject: [PATCH 2/3] staticcheck --- schemes/bgv/bgv_test.go | 7 +++++-- schemes/ckks/ckks_test.go | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/schemes/bgv/bgv_test.go b/schemes/bgv/bgv_test.go index 2e4bbccd..0dca91dd 100644 --- a/schemes/bgv/bgv_test.go +++ b/schemes/bgv/bgv_test.go @@ -881,6 +881,9 @@ func TestBGVParamsConstSerialization(t *testing.T) { 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}[:] { @@ -896,11 +899,11 @@ func TestBGVParamsConstSerialization(t *testing.T) { t.Fatal(err) } paramsBytes, err := params.MarshalBinary() - hash.Write(paramsBytes) require.Nil(t, err) + hash.Write(paramsBytes) paramsBytes, err = params.MarshalJSON() - hash.Write(paramsBytes) require.Nil(t, err) + hash.Write(paramsBytes) } } } diff --git a/schemes/ckks/ckks_test.go b/schemes/ckks/ckks_test.go index a89316fb..48a42808 100644 --- a/schemes/ckks/ckks_test.go +++ b/schemes/ckks/ckks_test.go @@ -808,6 +808,9 @@ func TestCKKSParamsConstSerialization(t *testing.T) { 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[:] { @@ -823,11 +826,11 @@ func TestCKKSParamsConstSerialization(t *testing.T) { t.Fatal(err) } paramsBytes, err := params.MarshalBinary() - hash.Write(paramsBytes) require.Nil(t, err) + hash.Write(paramsBytes) paramsBytes, err = params.MarshalJSON() - hash.Write(paramsBytes) require.Nil(t, err) + hash.Write(paramsBytes) } } } From 698dd7b36b01b5fae92827b2f2f1f47e7c22da09 Mon Sep 17 00:00:00 2001 From: lehugueni Date: Wed, 16 Oct 2024 15:33:21 +0200 Subject: [PATCH 3/3] renamed NewEncryptorWithPRNG --- core/rlwe/encryptor.go | 4 ++-- core/rlwe/rlwe_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/rlwe/encryptor.go b/core/rlwe/encryptor.go index a3b06744..8421189d 100644 --- a/core/rlwe/encryptor.go +++ b/core/rlwe/encryptor.go @@ -99,9 +99,9 @@ func newEncryptor(params Parameters) *Encryptor { } } -// NewEncryptorWithPRNG creates a new [Encryptor] that uses the provided prng for randomness. +// NewTestEncryptorWithPRNG creates a new [Encryptor] that uses the provided prng for randomness. // CAUTION: THIS FUNCTION SHOULD BE USED FOR TESTING PURPOSES ONLY. -func NewEncryptorWithPRNG(params ParameterProvider, key EncryptionKey, prng sampling.PRNG) *Encryptor { +func NewTestEncryptorWithPRNG(params ParameterProvider, key EncryptionKey, prng sampling.PRNG) *Encryptor { p := *params.GetRLWEParameters() enc := NewEncryptor(params, key) diff --git a/core/rlwe/rlwe_test.go b/core/rlwe/rlwe_test.go index 10951979..f76dddf3 100644 --- a/core/rlwe/rlwe_test.go +++ b/core/rlwe/rlwe_test.go @@ -312,7 +312,7 @@ func NewDeterministicTestContext(params Parameters, seedKeyGen, seedEnc []byte) panic(fmt.Errorf("NewDeterministicTestContext: failed to make prngEnc %w", err)) } kgen := NewKeyGenerator(params) - kgenEncryptor := NewEncryptorWithPRNG(params, nil, prngKGen) + kgenEncryptor := NewTestEncryptorWithPRNG(params, nil, prngKGen) kgen.Encryptor = kgenEncryptor sk := kgen.GenSecretKeyNew() @@ -321,7 +321,7 @@ func NewDeterministicTestContext(params Parameters, seedKeyGen, seedEnc []byte) eval := NewEvaluator(params, nil) - enc := NewEncryptorWithPRNG(params, sk, prngEnc) + enc := NewTestEncryptorWithPRNG(params, sk, prngEnc) dec := NewDecryptor(params, sk)