From 786fe99bdbbf78b68ccba21e8dab21a08094bc05 Mon Sep 17 00:00:00 2001 From: Christian M Date: Sun, 1 Dec 2019 00:25:30 +0100 Subject: [PATCH] unexported bfvContext and finished updating DBFV --- bfv/bfv.go | 105 +------------ bfv/bfv_benchmark_test.go | 2 +- bfv/bfv_test.go | 4 +- bfv/decryptor.go | 4 +- bfv/encoder.go | 4 +- bfv/encryptor.go | 4 +- bfv/evaluator.go | 4 +- bfv/keygen.go | 6 +- dbfv/{context.go => dbfv.go} | 5 + dbfv/dbfv_benchmark_test.go | 47 +++--- dbfv/dbfv_test.go | 285 +++++++++++++++++------------------ examples/bfv/examples_bfv.go | 6 +- examples/dbfv/pir/pir.go | 3 +- examples/dbfv/psi/psi.go | 2 +- 14 files changed, 185 insertions(+), 296 deletions(-) rename dbfv/{context.go => dbfv.go} (91%) diff --git a/bfv/bfv.go b/bfv/bfv.go index fc94db5e..ddd4e999 100644 --- a/bfv/bfv.go +++ b/bfv/bfv.go @@ -9,9 +9,9 @@ import ( // GaloisGen is ... [FIXME] const GaloisGen uint64 = 5 -// Context is a struct which contains all the elements required to instantiate the BFV Scheme. This includes the parameters (N, plaintext modulus, ciphertext modulus, +// bfvContext is a struct which contains all the elements required to instantiate the BFV Scheme. This includes the parameters (N, plaintext modulus, ciphertext modulus, // sampling, polynomial contexts and other parameters required for the homomorphic operations). -type Context struct { +type bfvContext struct { params *Parameters // Polynomial degree @@ -41,42 +41,8 @@ type Context struct { galElRotColRight []uint64 } -// NewContext creates a new Context with the given parameters. Returns an error if one of the parameters would not ensure the -// correctness of the scheme (however it doesn't check for security). -// -// Parameters : -// -// - N : the ring degree (must be a power of 2). -// -// - t : the plaintext modulus (must be a prime congruent to 1 mod 2N to enable batching). -// -// - ModuliQ1 : the ciphertext modulus composed primes congruent to 1 mod 2N. -// -// - ModuliP : the secondary ciphertext modulus used during the multiplication, composed of primes congruent to 1 mod 2N. Must be bigger than ModuliQ1 by a margin of ~20 bits. -// -// - sigma : the variance of the gaussian sampling. -func NewContext(params *Parameters) (newContext *Context) { - newContext = new(Context) - newContext.SetParameters(params) - return -} - -// SetParameters populates a new Context with the given parameters. Returns an error if one of the parameters would not ensure the -// correctness of the scheme (however it doesn't check for security). -// -// Parameters : -// -// - N : the ring degree (must be a power of 2). -// -// - t : the plaintext modulus (must be a prime congruent to 1 mod 2N to enable batching). -// -// - ModuliQ1 : the ciphertext modulus composed primes congruent to 1 mod 2N. -// -// - ModuliP : the secondary ciphertext modulus used during the multiplication, composed of primes congruent to 1 mod 2N. Must be bigger than ModuliQ1 by a margin of ~20 bits. -// -// - sigma : the variance of the gaussian sampling. -func (context *Context) SetParameters(params *Parameters) { - +func newBFVContext(params *Parameters) (context *bfvContext) { + context = new(bfvContext) var err error LogN := params.LogN @@ -121,64 +87,5 @@ func (context *Context) SetParameters(params *Parameters) { context.galElRotColLeft = ring.GenGaloisParams(context.n, GaloisGen) context.galElRotColRight = ring.GenGaloisParams(context.n, ring.ModExp(GaloisGen, 2*context.n-1, 2*context.n)) context.galElRotRow = 2*context.n - 1 -} - -// N returns N which is the degree of the ring, of the target context. -func (context *Context) N() uint64 { - return context.n -} - -// LogQ returns logQ which is the total bitzise of the ciphertext modulus. -func (context *Context) LogQ() uint64 { - return context.logQ -} - -// T returns the plaintext modulus of the target context. -func (context *Context) T() uint64 { - return context.t -} - -// Sigma returns sigma, which is the variance used for the gaussian sampling of the target context. -func (context *Context) Sigma() float64 { - return context.sigma -} - -// ContextT returns the polynomial (ring) context of the plaintext modulus, of the target context. -func (context *Context) ContextT() *ring.Context { - return context.contextT -} - -// ContextQ1 returns the polynomial (ring) context of the ciphertext modulus, of the target context. -func (context *Context) ContextQ1() *ring.Context { - return context.contextQ1 -} - -// ContextQ2 returns the polynomial (ring) context of the secondary ciphertext modulus, of the target context. -func (context *Context) ContextQ2() *ring.Context { - return context.contextQ2 -} - -// ContextKeys returns the polynomial (ring) context used for the key-generation. -func (context *Context) ContextKeys() *ring.Context { - return context.contextQ1P -} - -// ContextP returns the ring Context of the KeySwitchPrimes. -func (context *Context) ContextP() *ring.Context { - return context.contextP -} - -// Alpha returns #Pi. -func (context *Context) Alpha() uint64 { - return context.alpha -} - -// Beta returns ceil(#Qi/#Pi). -func (context *Context) Beta() uint64 { - return context.beta -} - -// GaussianSampler returns the context's gaussian sampler instance -func (context *Context) GaussianSampler() *ring.KYSampler { - return context.gaussianSampler -} + return +} \ No newline at end of file diff --git a/bfv/bfv_benchmark_test.go b/bfv/bfv_benchmark_test.go index bb3afb6f..f7238ecc 100755 --- a/bfv/bfv_benchmark_test.go +++ b/bfv/bfv_benchmark_test.go @@ -11,7 +11,7 @@ func Benchmark_BFV(b *testing.B) { for _, params := range paramSets { - bfvContext := NewContext(params) + bfvContext := newBFVContext(params) var sk *SecretKey var pk *PublicKey diff --git a/bfv/bfv_test.go b/bfv/bfv_test.go index cf17c0ef..fda8b76a 100644 --- a/bfv/bfv_test.go +++ b/bfv/bfv_test.go @@ -23,7 +23,7 @@ func testString2(opname string, params *bfvParams) string { type bfvParams struct { params *Parameters - bfvContext *Context + bfvContext *bfvContext encoder *Encoder kgen *KeyGenerator sk *SecretKey @@ -246,7 +246,7 @@ func genBfvParams(contextParameters *Parameters) (params *bfvParams) { params.params = contextParameters.Copy() - params.bfvContext = NewContext(contextParameters) + params.bfvContext = newBFVContext(contextParameters) params.kgen = NewKeyGenerator(contextParameters) diff --git a/bfv/decryptor.go b/bfv/decryptor.go index 282cd530..effb8e76 100644 --- a/bfv/decryptor.go +++ b/bfv/decryptor.go @@ -7,7 +7,7 @@ import ( // Decryptor is a structure used to decrypt ciphertext. It stores the secret-key. type Decryptor struct { params *Parameters - bfvContext *Context + bfvContext *bfvContext sk *SecretKey polypool *ring.Poly } @@ -23,7 +23,7 @@ func NewDecryptor(params *Parameters, sk *SecretKey) (decryptor *Decryptor) { decryptor.params = params.Copy() - decryptor.bfvContext = NewContext(params) + decryptor.bfvContext = newBFVContext(params) decryptor.sk = sk diff --git a/bfv/encoder.go b/bfv/encoder.go index 680d0feb..535fc35e 100644 --- a/bfv/encoder.go +++ b/bfv/encoder.go @@ -9,7 +9,7 @@ import ( // Encoder is a structure storing the parameters encode values on a plaintext in a SIMD fashion. type Encoder struct { params *Parameters - bfvContext *Context + bfvContext *bfvContext indexMatrix []uint64 simplescaler *ring.SimpleScaler polypool *ring.Poly @@ -24,7 +24,7 @@ func NewEncoder(params *Parameters) (encoder *Encoder) { encoder = new(Encoder) encoder.params = params.Copy() - encoder.bfvContext = NewContext(params) + encoder.bfvContext = newBFVContext(params) slots := encoder.bfvContext.n diff --git a/bfv/encryptor.go b/bfv/encryptor.go index 4d28d2bf..b4def73f 100644 --- a/bfv/encryptor.go +++ b/bfv/encryptor.go @@ -7,7 +7,7 @@ import ( // Encryptor is a structure holding the parameters needed to encrypt plaintexts. type Encryptor struct { params *Parameters - bfvContext *Context + bfvContext *bfvContext pk *PublicKey sk *SecretKey polypool [3]*ring.Poly @@ -39,7 +39,7 @@ func newEncryptor(params *Parameters, pk *PublicKey, sk *SecretKey) (encryptor * encryptor = new(Encryptor) encryptor.params = params.Copy() - encryptor.bfvContext = NewContext(params) + encryptor.bfvContext = newBFVContext(params) encryptor.pk = pk encryptor.sk = sk diff --git a/bfv/evaluator.go b/bfv/evaluator.go index 6bd9e85f..cd392c3a 100644 --- a/bfv/evaluator.go +++ b/bfv/evaluator.go @@ -11,7 +11,7 @@ import ( type Evaluator struct { params *Parameters - bfvContext *Context + bfvContext *bfvContext baseconverterQ1Q2 *ring.FastBasisExtender @@ -34,7 +34,7 @@ func NewEvaluator(params *Parameters) (evaluator *Evaluator) { evaluator = new(Evaluator) evaluator.params = params.Copy() - evaluator.bfvContext = NewContext(params) + evaluator.bfvContext = newBFVContext(params) evaluator.baseconverterQ1Q2 = ring.NewFastBasisExtender(evaluator.bfvContext.contextQ1, evaluator.bfvContext.contextQ2) evaluator.baseconverterQ1P = ring.NewFastBasisExtender(evaluator.bfvContext.contextQ1, evaluator.bfvContext.contextP) diff --git a/bfv/keygen.go b/bfv/keygen.go index 806d67ff..d1cf2a36 100644 --- a/bfv/keygen.go +++ b/bfv/keygen.go @@ -9,7 +9,7 @@ import ( // as well as a small memory pool for intermediate values. type KeyGenerator struct { params *Parameters - bfvContext *Context + bfvContext *bfvContext polypool *ring.Poly } @@ -60,7 +60,7 @@ func (swk *SwitchingKey) Get() [][2]*ring.Poly { func NewKeyGenerator(params *Parameters) (keygen *KeyGenerator) { keygen = new(KeyGenerator) params = params.Copy() - keygen.bfvContext = NewContext(params) + keygen.bfvContext = newBFVContext(params) keygen.polypool = keygen.bfvContext.contextQ1P.NewPoly() return } @@ -238,7 +238,7 @@ func NewSwitchingKey(params *Parameters) (evakey *SwitchingKey) { return } -func newswitchintkey(bfvContext *Context, skIn, skOut *ring.Poly) (switchkey *SwitchingKey) { +func newswitchintkey(bfvContext *bfvContext, skIn, skOut *ring.Poly) (switchkey *SwitchingKey) { switchkey = new(SwitchingKey) diff --git a/dbfv/context.go b/dbfv/dbfv.go similarity index 91% rename from dbfv/context.go rename to dbfv/dbfv.go index 42744578..3973818f 100644 --- a/dbfv/context.go +++ b/dbfv/dbfv.go @@ -86,3 +86,8 @@ func newDbfvContext(params *bfv.Parameters) *dbfvContext { beta: beta, } } + +func NewCRPGenerator(params *bfv.Parameters, key []byte) *ring.CRPGenerator { + ctx := newDbfvContext(params) + return ring.NewCRPGenerator(key, ctx.contextQ1P) +} \ No newline at end of file diff --git a/dbfv/dbfv_benchmark_test.go b/dbfv/dbfv_benchmark_test.go index 5f23a437..a63cd66d 100644 --- a/dbfv/dbfv_benchmark_test.go +++ b/dbfv/dbfv_benchmark_test.go @@ -21,13 +21,11 @@ func benchPublicKeyGen(b *testing.B) { for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - contextKeys := bfvContext.ContextKeys() - sk0Shards := params.sk0Shards + sk0Shards := testCtx.sk0Shards - crpGenerator := ring.NewCRPGenerator(nil, contextKeys) + crpGenerator := ring.NewCRPGenerator(nil, testCtx.contextQ1P) crpGenerator.Seed([]byte{}) crp := crpGenerator.ClockNew() @@ -71,10 +69,9 @@ func benchRelinKeyGen(b *testing.B) { for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - sk0Shards := params.sk0Shards + sk0Shards := testCtx.sk0Shards type Party struct { *RKGProtocol @@ -94,12 +91,12 @@ func benchRelinKeyGen(b *testing.B) { p.share1, p.share2, p.share3 = p.RKGProtocol.AllocateShares() p.rlk = bfv.NewRelinKey(parameters, 2) - crpGenerator := ring.NewCRPGenerator(nil, bfvContext.ContextKeys()) + crpGenerator := ring.NewCRPGenerator(nil, testCtx.contextQ1P) crpGenerator.Seed([]byte{}) - crp := make([]*ring.Poly, bfvContext.Beta()) + crp := make([]*ring.Poly, testCtx.beta) - for i := uint64(0); i < bfvContext.Beta(); i++ { + for i := uint64(0); i < testCtx.beta; i++ { crp[i] = crpGenerator.ClockNew() } @@ -151,7 +148,7 @@ func benchRelinKeyGenNaive(b *testing.B) { for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + params := genDBFVTestContext(parameters) pk0 := params.pk0 sk0Shards := params.sk0Shards @@ -212,7 +209,7 @@ func benchKeyswitching(b *testing.B) { for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + params := genDBFVTestContext(parameters) sk0Shards := params.sk0Shards sk1Shards := params.sk1Shards @@ -259,7 +256,7 @@ func benchPublicKeySwitching(b *testing.B) { for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + params := genDBFVTestContext(parameters) sk0Shards := params.sk0Shards pk1 := params.pk1 @@ -305,11 +302,9 @@ func benchRotKeyGen(b *testing.B) { for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - contextKeys := bfvContext.ContextKeys() - sk0Shards := params.sk0Shards + sk0Shards := testCtx.sk0Shards type Party struct { *RTGProtocol @@ -322,15 +317,15 @@ func benchRotKeyGen(b *testing.B) { p.s = sk0Shards[0].Get() p.share = p.AllocateShare() - crpGenerator := ring.NewCRPGenerator(nil, bfvContext.ContextKeys()) + crpGenerator := ring.NewCRPGenerator(nil, testCtx.contextQ1P) crpGenerator.Seed([]byte{}) - crp := make([]*ring.Poly, bfvContext.Beta()) + crp := make([]*ring.Poly, testCtx.beta) - for i := uint64(0); i < bfvContext.Beta(); i++ { + for i := uint64(0); i < testCtx.beta; i++ { crp[i] = crpGenerator.ClockNew() } - mask := uint64((contextKeys.N >> 1) - 1) + mask := (testCtx.n >> 1) - 1 b.Run(testString("Round1/Gen", parameters), func(b *testing.B) { @@ -362,11 +357,9 @@ func benchRefresh(b *testing.B) { for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - contextKeys := bfvContext.ContextKeys() - sk0Shards := params.sk0Shards + sk0Shards := testCtx.sk0Shards type Party struct { *RefreshProtocol @@ -379,7 +372,7 @@ func benchRefresh(b *testing.B) { p.s = sk0Shards[0].Get() p.share = p.AllocateShares() - crpGenerator := ring.NewCRPGenerator(nil, contextKeys) + crpGenerator := ring.NewCRPGenerator(nil, testCtx.contextQ1P) crpGenerator.Seed([]byte{}) crp := crpGenerator.ClockNew() diff --git a/dbfv/dbfv_test.go b/dbfv/dbfv_test.go index d605c99e..f5cbe52e 100644 --- a/dbfv/dbfv_test.go +++ b/dbfv/dbfv_test.go @@ -17,9 +17,10 @@ func check(t *testing.T, err error) { } type dbfvTestContext struct { + *dbfvContext + params *bfv.Parameters - bfvContext *bfv.Context encoder *bfv.Encoder kgen *bfv.KeyGenerator @@ -65,44 +66,46 @@ func Test_DBFV(t *testing.T) { } -func genDBFVContext(contextParameters *bfv.Parameters) (params *dbfvTestContext) { +func genDBFVTestContext(params *bfv.Parameters) (testCtx *dbfvTestContext) { - params = new(dbfvTestContext) + testCtx = new(dbfvTestContext) - params.params = contextParameters - params.bfvContext = bfv.NewContext(contextParameters) + testCtx.params = params + testCtx.dbfvContext = newDbfvContext(params) + + testCtx.encoder = bfv.NewEncoder(params) + testCtx.evaluator = bfv.NewEvaluator(params) + + kgen := bfv.NewKeyGenerator(params) - params.encoder = bfv.NewEncoder(contextParameters) - params.evaluator = bfv.NewEvaluator(contextParameters) - kgen := bfv.NewKeyGenerator(contextParameters) // SecretKeys - params.sk0Shards = make([]*bfv.SecretKey, testParams.parties) - params.sk1Shards = make([]*bfv.SecretKey, testParams.parties) - tmp0 := params.bfvContext.ContextKeys().NewPoly() - tmp1 := params.bfvContext.ContextKeys().NewPoly() + testCtx.sk0Shards = make([]*bfv.SecretKey, testParams.parties) + testCtx.sk1Shards = make([]*bfv.SecretKey, testParams.parties) + tmp0 := testCtx.contextQ1P.NewPoly() + tmp1 := testCtx.contextQ1P.NewPoly() for j := uint64(0); j < testParams.parties; j++ { - params.sk0Shards[j] = kgen.NewSecretKey() - params.sk1Shards[j] = kgen.NewSecretKey() - params.bfvContext.ContextKeys().Add(tmp0, params.sk0Shards[j].Get(), tmp0) - params.bfvContext.ContextKeys().Add(tmp1, params.sk1Shards[j].Get(), tmp1) + testCtx.sk0Shards[j] = kgen.NewSecretKey() + testCtx.sk1Shards[j] = kgen.NewSecretKey() + testCtx.contextQ1P.Add(tmp0, testCtx.sk0Shards[j].Get(), tmp0) + testCtx.contextQ1P.Add(tmp1, testCtx.sk1Shards[j].Get(), tmp1) } - params.sk0 = new(bfv.SecretKey) - params.sk1 = new(bfv.SecretKey) + testCtx.sk0 = new(bfv.SecretKey) + testCtx.sk1 = new(bfv.SecretKey) - params.sk0.Set(tmp0) - params.sk1.Set(tmp1) + testCtx.sk0.Set(tmp0) + testCtx.sk1.Set(tmp1) // Publickeys - params.pk0 = kgen.NewPublicKey(params.sk0) - params.pk1 = kgen.NewPublicKey(params.sk1) + testCtx.pk0 = kgen.NewPublicKey(testCtx.sk0) + testCtx.pk1 = kgen.NewPublicKey(testCtx.sk1) - params.encryptorPk0 = bfv.NewEncryptorFromPk(contextParameters, params.pk0) - params.decryptorSk0 = bfv.NewDecryptor(contextParameters, params.sk0) - params.decryptorSk1 = bfv.NewDecryptor(contextParameters, params.sk1) + testCtx.encryptorPk0 = bfv.NewEncryptorFromPk(params, testCtx.pk0) + testCtx.decryptorSk0 = bfv.NewDecryptor(params, testCtx.sk0) + testCtx.decryptorSk1 = bfv.NewDecryptor(params, testCtx.sk1) return } @@ -113,16 +116,14 @@ func testPublicKeyGen(t *testing.T) { for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - contextKeys := bfvContext.ContextKeys() - sk0Shards := params.sk0Shards - decryptorSk0 := params.decryptorSk0 + sk0Shards := testCtx.sk0Shards + decryptorSk0 := testCtx.decryptorSk0 - t.Run(fmt.Sprintf("N=%d/logQ=%d", contextKeys.N, contextKeys.ModulusBigint.BitLen()), func(t *testing.T) { + t.Run(fmt.Sprintf("N=%d/logQ=%d", testCtx.n, testCtx.contextQ1P.ModulusBigint.BitLen()), func(t *testing.T) { - crpGenerator := ring.NewCRPGenerator(nil, contextKeys) + crpGenerator := ring.NewCRPGenerator(nil, testCtx.contextQ1P) crpGenerator.Seed([]byte{}) crp := crpGenerator.ClockNew() @@ -156,9 +157,9 @@ func testPublicKeyGen(t *testing.T) { // Verifies that decrypt((encryptp(collectiveSk, m), collectivePk) = m encryptorTest := bfv.NewEncryptorFromPk(parameters, pk) - coeffs, _, ciphertext := newTestVectors(params, encryptorTest, t) + coeffs, _, ciphertext := newTestVectors(testCtx, encryptorTest, t) - verifyTestVectors(params, decryptorSk0, coeffs, ciphertext, t) + verifyTestVectors(testCtx, decryptorSk0, coeffs, ciphertext, t) }) } } @@ -168,16 +169,14 @@ func testRelinKeyGen(t *testing.T) { parties := testParams.parties for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - contextKeys := bfvContext.ContextKeys() - sk0Shards := params.sk0Shards - encryptorPk0 := params.encryptorPk0 - decryptorSk0 := params.decryptorSk0 - evaluator := params.evaluator + sk0Shards := testCtx.sk0Shards + encryptorPk0 := testCtx.encryptorPk0 + decryptorSk0 := testCtx.decryptorSk0 + evaluator := testCtx.evaluator - t.Run(fmt.Sprintf("N=%d/logQ=%d", contextKeys.N, contextKeys.ModulusBigint.BitLen()), func(t *testing.T) { + t.Run(fmt.Sprintf("N=%d/logQ=%d", testCtx.n, testCtx.contextQ1P.ModulusBigint.BitLen()), func(t *testing.T) { type Party struct { *RKGProtocol @@ -201,11 +200,11 @@ func testRelinKeyGen(t *testing.T) { P0 := rkgParties[0] - crpGenerator := ring.NewCRPGenerator(nil, bfvContext.ContextKeys()) + crpGenerator := ring.NewCRPGenerator(nil, testCtx.contextQ1P) crpGenerator.Seed([]byte{}) - crp := make([]*ring.Poly, bfvContext.Beta()) + crp := make([]*ring.Poly, testCtx.beta) - for i := uint64(0); i < bfvContext.Beta(); i++ { + for i := uint64(0); i < testCtx.beta; i++ { crp[i] = crpGenerator.ClockNew() } @@ -236,11 +235,11 @@ func testRelinKeyGen(t *testing.T) { evk := bfv.NewRelinKey(parameters, 1) P0.GenRelinearizationKey(P0.share2, P0.share3, evk) - coeffs, _, ciphertext := newTestVectors(params, encryptorPk0, t) + coeffs, _, ciphertext := newTestVectors(testCtx, encryptorPk0, t) for i := range coeffs { coeffs[i] *= coeffs[i] - coeffs[i] %= bfvContext.ContextT().Modulus[0] + coeffs[i] %= testCtx.contextT.Modulus[0] } ciphertextMul := bfv.NewCiphertext(parameters, ciphertext.Degree()*2) @@ -249,7 +248,7 @@ func testRelinKeyGen(t *testing.T) { res := bfv.NewCiphertext(parameters, 1) evaluator.Relinearize(ciphertextMul, evk, res) - verifyTestVectors(params, decryptorSk0, coeffs, ciphertextMul, t) + verifyTestVectors(testCtx, decryptorSk0, coeffs, ciphertextMul, t) }) } } @@ -259,17 +258,15 @@ func testRelinKeyGenNaive(t *testing.T) { parties := testParams.parties for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - contextKeys := bfvContext.ContextKeys() - evaluator := params.evaluator - pk0 := params.pk0 - encryptorPk0 := params.encryptorPk0 - decryptorSk0 := params.decryptorSk0 - sk0Shards := params.sk0Shards + evaluator := testCtx.evaluator + pk0 := testCtx.pk0 + encryptorPk0 := testCtx.encryptorPk0 + decryptorSk0 := testCtx.decryptorSk0 + sk0Shards := testCtx.sk0Shards - t.Run(fmt.Sprintf("N=%d/logQ=%d", contextKeys.N, contextKeys.ModulusBigint.BitLen()), func(t *testing.T) { + t.Run(fmt.Sprintf("N=%d/logQ=%d", testCtx.n, testCtx.contextQ1P.ModulusBigint.BitLen()), func(t *testing.T) { type Party struct { *RKGProtocolNaive @@ -310,11 +307,11 @@ func testRelinKeyGenNaive(t *testing.T) { evk := bfv.NewRelinKey(parameters, 1) P0.GenRelinearizationKey(P0.share2, evk) - coeffs, _, ciphertext := newTestVectors(params, encryptorPk0, t) + coeffs, _, ciphertext := newTestVectors(testCtx, encryptorPk0, t) for i := range coeffs { coeffs[i] *= coeffs[i] - coeffs[i] %= bfvContext.ContextT().Modulus[0] + coeffs[i] %= testCtx.contextT.Modulus[0] } ciphertextMul := bfv.NewCiphertext(parameters, ciphertext.Degree()*2) @@ -323,7 +320,7 @@ func testRelinKeyGenNaive(t *testing.T) { res := bfv.NewCiphertext(parameters, 1) evaluator.Relinearize(ciphertextMul, evk, res) - verifyTestVectors(params, decryptorSk0, coeffs, ciphertextMul, t) + verifyTestVectors(testCtx, decryptorSk0, coeffs, ciphertextMul, t) }) } } @@ -333,16 +330,14 @@ func testKeyswitching(t *testing.T) { parties := testParams.parties for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - contextKeys := bfvContext.ContextKeys() - sk0Shards := params.sk0Shards - sk1Shards := params.sk1Shards - encryptorPk0 := params.encryptorPk0 - decryptorSk1 := params.decryptorSk1 + sk0Shards := testCtx.sk0Shards + sk1Shards := testCtx.sk1Shards + encryptorPk0 := testCtx.encryptorPk0 + decryptorSk1 := testCtx.decryptorSk1 - t.Run(fmt.Sprintf("N=%d/logQ=%d", contextKeys.N, contextKeys.ModulusBigint.BitLen()), func(t *testing.T) { + t.Run(fmt.Sprintf("N=%d/logQ=%d", testCtx.n, testCtx.contextQ1P.ModulusBigint.BitLen()), func(t *testing.T) { type Party struct { *CKSProtocol @@ -362,7 +357,7 @@ func testKeyswitching(t *testing.T) { } P0 := cksParties[0] - coeffs, _, ciphertext := newTestVectors(params, encryptorPk0, t) + coeffs, _, ciphertext := newTestVectors(testCtx, encryptorPk0, t) // Each party creates its CKSProtocol instance with tmp = si-si' for i, p := range cksParties { @@ -375,11 +370,11 @@ func testKeyswitching(t *testing.T) { ksCiphertext := bfv.NewCiphertext(parameters, 1) P0.KeySwitch(P0.share, ciphertext, ksCiphertext) - verifyTestVectors(params, decryptorSk1, coeffs, ksCiphertext, t) + verifyTestVectors(testCtx, decryptorSk1, coeffs, ksCiphertext, t) P0.KeySwitch(P0.share, ciphertext, ciphertext) - verifyTestVectors(params, decryptorSk1, coeffs, ciphertext, t) + verifyTestVectors(testCtx, decryptorSk1, coeffs, ciphertext, t) }) } @@ -390,16 +385,14 @@ func testPublicKeySwitching(t *testing.T) { parties := testParams.parties for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - contextKeys := bfvContext.ContextKeys() - sk0Shards := params.sk0Shards - pk1 := params.pk1 - encryptorPk0 := params.encryptorPk0 - decryptorSk1 := params.decryptorSk1 + sk0Shards := testCtx.sk0Shards + pk1 := testCtx.pk1 + encryptorPk0 := testCtx.encryptorPk0 + decryptorSk1 := testCtx.decryptorSk1 - t.Run(fmt.Sprintf("N=%d/logQ=%d", contextKeys.N, contextKeys.ModulusBigint.BitLen()), func(t *testing.T) { + t.Run(fmt.Sprintf("N=%d/logQ=%d", testCtx.n, testCtx.contextQ1P.ModulusBigint.BitLen()), func(t *testing.T) { type Party struct { *PCKSProtocol @@ -417,7 +410,7 @@ func testPublicKeySwitching(t *testing.T) { } P0 := pcksParties[0] - coeffs, _, ciphertext := newTestVectors(params, encryptorPk0, t) + coeffs, _, ciphertext := newTestVectors(testCtx, encryptorPk0, t) ciphertextSwitched := bfv.NewCiphertext(parameters, 1) @@ -430,7 +423,7 @@ func testPublicKeySwitching(t *testing.T) { P0.KeySwitch(P0.share, ciphertext, ciphertextSwitched) - verifyTestVectors(params, decryptorSk1, coeffs, ciphertextSwitched, t) + verifyTestVectors(testCtx, decryptorSk1, coeffs, ciphertextSwitched, t) }) } } @@ -441,16 +434,14 @@ func testRotKeyGenRotRows(t *testing.T) { for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - contextKeys := bfvContext.ContextKeys() - evaluator := params.evaluator - encryptorPk0 := params.encryptorPk0 - decryptorSk0 := params.decryptorSk0 - sk0Shards := params.sk0Shards + evaluator := testCtx.evaluator + encryptorPk0 := testCtx.encryptorPk0 + decryptorSk0 := testCtx.decryptorSk0 + sk0Shards := testCtx.sk0Shards - t.Run(fmt.Sprintf("N=%d/logQ=%d", contextKeys.N, contextKeys.ModulusBigint.BitLen()), func(t *testing.T) { + t.Run(fmt.Sprintf("N=%d/logQ=%d", testCtx.n, testCtx.contextQ1P.ModulusBigint.BitLen()), func(t *testing.T) { type Party struct { *RTGProtocol @@ -468,11 +459,11 @@ func testRotKeyGenRotRows(t *testing.T) { } P0 := pcksParties[0] - crpGenerator := ring.NewCRPGenerator(nil, bfvContext.ContextKeys()) + crpGenerator := ring.NewCRPGenerator(nil, testCtx.contextQ1P) crpGenerator.Seed([]byte{}) - crp := make([]*ring.Poly, bfvContext.Beta()) + crp := make([]*ring.Poly, testCtx.beta) - for i := uint64(0); i < bfvContext.Beta(); i++ { + for i := uint64(0); i < testCtx.beta; i++ { crp[i] = crpGenerator.ClockNew() } @@ -486,13 +477,13 @@ func testRotKeyGenRotRows(t *testing.T) { rotkey := bfv.NewRotationKeys() P0.Finalize(P0.share, crp, rotkey) - coeffs, _, ciphertext := newTestVectors(params, encryptorPk0, t) + coeffs, _, ciphertext := newTestVectors(testCtx, encryptorPk0, t) evaluator.RotateRows(ciphertext, rotkey, ciphertext) - coeffs = append(coeffs[contextKeys.N>>1:], coeffs[:contextKeys.N>>1]...) + coeffs = append(coeffs[testCtx.n>>1:], coeffs[:testCtx.n>>1]...) - verifyTestVectors(params, decryptorSk0, coeffs, ciphertext, t) + verifyTestVectors(testCtx, decryptorSk0, coeffs, ciphertext, t) }) } @@ -504,16 +495,14 @@ func testRotKeyGenRotCols(t *testing.T) { parties := testParams.parties for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - contextKeys := bfvContext.ContextKeys() - evaluator := params.evaluator - encryptorPk0 := params.encryptorPk0 - decryptorSk0 := params.decryptorSk0 - sk0Shards := params.sk0Shards + evaluator := testCtx.evaluator + encryptorPk0 := testCtx.encryptorPk0 + decryptorSk0 := testCtx.decryptorSk0 + sk0Shards := testCtx.sk0Shards - t.Run(fmt.Sprintf("N=%d/logQ=%d", contextKeys.N, contextKeys.ModulusBigint.BitLen()), func(t *testing.T) { + t.Run(fmt.Sprintf("N=%d/logQ=%d", testCtx.n, testCtx.contextQ1P.ModulusBigint.BitLen()), func(t *testing.T) { type Party struct { *RTGProtocol @@ -532,21 +521,21 @@ func testRotKeyGenRotCols(t *testing.T) { P0 := pcksParties[0] - crpGenerator := ring.NewCRPGenerator(nil, contextKeys) + crpGenerator := ring.NewCRPGenerator(nil, testCtx.contextQ1P) crpGenerator.Seed([]byte{}) - crp := make([]*ring.Poly, bfvContext.Beta()) + crp := make([]*ring.Poly, testCtx.beta) - for i := uint64(0); i < bfvContext.Beta(); i++ { + for i := uint64(0); i < testCtx.beta; i++ { crp[i] = crpGenerator.ClockNew() } - mask := (contextKeys.N >> 1) - 1 + mask := (testCtx.n >> 1) - 1 - coeffs, _, ciphertext := newTestVectors(params, encryptorPk0, t) + coeffs, _, ciphertext := newTestVectors(testCtx, encryptorPk0, t) receiver := bfv.NewCiphertext(parameters, ciphertext.Degree()) - for k := uint64(1); k < contextKeys.N>>1; k <<= 1 { + for k := uint64(1); k < testCtx.n>>1; k <<= 1 { for i, p := range pcksParties { p.GenShare(bfv.RotationLeft, k, p.s, crp, &p.share) @@ -560,14 +549,14 @@ func testRotKeyGenRotCols(t *testing.T) { evaluator.RotateColumns(ciphertext, k, rotkey, receiver) - coeffsWant := make([]uint64, contextKeys.N) + coeffsWant := make([]uint64, testCtx.n) - for i := uint64(0); i < contextKeys.N>>1; i++ { + for i := uint64(0); i < testCtx.n>>1; i++ { coeffsWant[i] = coeffs[(i+k)&mask] - coeffsWant[i+(contextKeys.N>>1)] = coeffs[((i+k)&mask)+(contextKeys.N>>1)] + coeffsWant[i+(testCtx.n>>1)] = coeffs[((i+k)&mask)+(testCtx.n>>1)] } - verifyTestVectors(params, decryptorSk0, coeffsWant, receiver, t) + verifyTestVectors(testCtx, decryptorSk0, coeffsWant, receiver, t) } }) } @@ -578,20 +567,18 @@ func testRefresh(t *testing.T) { parties := testParams.parties for _, parameters := range testParams.contexts { - params := genDBFVContext(parameters) + testCtx := genDBFVTestContext(parameters) - bfvContext := params.bfvContext - contextKeys := params.bfvContext.ContextKeys() - encryptorPk0 := params.encryptorPk0 - sk0Shards := params.sk0Shards - encoder := params.encoder - decryptorSk0 := params.decryptorSk0 + encryptorPk0 := testCtx.encryptorPk0 + sk0Shards := testCtx.sk0Shards + encoder := testCtx.encoder + decryptorSk0 := testCtx.decryptorSk0 kgen := bfv.NewKeyGenerator(parameters) - rlk := kgen.NewRelinKey(params.sk0, 2) + rlk := kgen.NewRelinKey(testCtx.sk0, 2) - t.Run(fmt.Sprintf("N=%d/logQ=%d/Refresh", contextKeys.N, contextKeys.ModulusBigint.BitLen()), func(t *testing.T) { + t.Run(fmt.Sprintf("N=%d/logQ=%d/Refresh", testCtx.n, testCtx.contextQ1P.ModulusBigint.BitLen()), func(t *testing.T) { type Party struct { *RefreshProtocol @@ -612,11 +599,11 @@ func testRefresh(t *testing.T) { P0 := RefreshParties[0] - crpGenerator := ring.NewCRPGenerator(nil, bfvContext.ContextKeys()) + crpGenerator := ring.NewCRPGenerator(nil, testCtx.contextQ1P) crpGenerator.Seed([]byte{}) crp := crpGenerator.ClockNew() - coeffs, _, ciphertext := newTestVectors(params, encryptorPk0, t) + coeffs, _, ciphertext := newTestVectors(testCtx, encryptorPk0, t) maxDepth := 0 @@ -630,10 +617,10 @@ func testRefresh(t *testing.T) { // Finds the maximum multiplicative depth for true { - params.evaluator.Relinearize(params.evaluator.MulNew(ciphertextTmp, ciphertextTmp), rlk, ciphertextTmp) + testCtx.evaluator.Relinearize(testCtx.evaluator.MulNew(ciphertextTmp, ciphertextTmp), rlk, ciphertextTmp) for j := range coeffsTmp { - coeffsTmp[j] = ring.BRed(coeffsTmp[j], coeffsTmp[j], bfvContext.ContextT().Modulus[0], bfvContext.ContextT().GetBredParams()[0]) + coeffsTmp[j] = ring.BRed(coeffsTmp[j], coeffsTmp[j], testCtx.contextT.Modulus[0], testCtx.contextT.GetBredParams()[0]) } if utils.EqualSliceUint64(coeffsTmp, encoder.DecodeUint(decryptorSk0.DecryptNew(ciphertextTmp))) { @@ -644,18 +631,18 @@ func testRefresh(t *testing.T) { } // Simulated added error of size Q/(T^2) and add it to the fresh ciphertext - coeffsBigint := make([]*big.Int, bfvContext.N()) - bfvContext.ContextQ1().PolyToBigint(ciphertext.Value()[0], coeffsBigint) + coeffsBigint := make([]*big.Int, testCtx.n) + testCtx.contextQ1.PolyToBigint(ciphertext.Value()[0], coeffsBigint) - errorRange := new(big.Int).Set(bfvContext.ContextQ1().ModulusBigint) - errorRange.Quo(errorRange, bfvContext.ContextT().ModulusBigint) - errorRange.Quo(errorRange, bfvContext.ContextT().ModulusBigint) + errorRange := new(big.Int).Set(testCtx.contextQ1.ModulusBigint) + errorRange.Quo(errorRange, testCtx.contextT.ModulusBigint) + errorRange.Quo(errorRange, testCtx.contextT.ModulusBigint) - for i := uint64(0); i < bfvContext.N(); i++ { + for i := uint64(0); i < testCtx.n; i++ { coeffsBigint[i].Add(coeffsBigint[i], ring.RandInt(errorRange)) } - bfvContext.ContextQ1().SetCoefficientsBigint(coeffsBigint, ciphertext.Value()[0]) + testCtx.contextQ1.SetCoefficientsBigint(coeffsBigint, ciphertext.Value()[0]) for i, p := range RefreshParties { p.GenShares(p.s, ciphertext, crp, p.share) @@ -674,10 +661,10 @@ func testRefresh(t *testing.T) { // Square the refreshed ciphertext up to the maximum depth-1 for i := 0; i < maxDepth-1; i++ { - params.evaluator.Relinearize(params.evaluator.MulNew(ciphertext, ciphertext), rlk, ciphertext) + testCtx.evaluator.Relinearize(testCtx.evaluator.MulNew(ciphertext, ciphertext), rlk, ciphertext) for j := range coeffs { - coeffs[j] = ring.BRed(coeffs[j], coeffs[j], bfvContext.ContextT().Modulus[0], bfvContext.ContextT().GetBredParams()[0]) + coeffs[j] = ring.BRed(coeffs[j], coeffs[j], testCtx.contextT.Modulus[0], testCtx.contextT.GetBredParams()[0]) } } @@ -690,7 +677,7 @@ func testRefresh(t *testing.T) { } func newTestVectors(contextParams *dbfvTestContext, encryptor *bfv.Encryptor, t *testing.T) (coeffs []uint64, plaintext *bfv.Plaintext, ciphertext *bfv.Ciphertext) { - coeffsPol := contextParams.bfvContext.ContextT().NewUniformPoly() + coeffsPol := contextParams.contextT.NewUniformPoly() plaintext = bfv.NewPlaintext(contextParams.params) contextParams.encoder.EncodeUint(coeffsPol.Coeffs[0], plaintext) ciphertext = encryptor.EncryptNew(plaintext) @@ -707,13 +694,13 @@ func Test_Marshalling(t *testing.T) { params := bfv.DefaultParams[14] //verify if the un.marshalling works properly - bfvCtx := bfv.NewContext(params) + dbfvCtx := newDbfvContext(params) KeyGenerator := bfv.NewKeyGenerator(params) - crsGen := ring.NewCRPGenerator([]byte{'l', 'a', 't', 't', 'i', 'g', 'o'}, bfvCtx.ContextKeys()) + crsGen := ring.NewCRPGenerator([]byte{'l', 'a', 't', 't', 'i', 'g', 'o'}, dbfvCtx.contextQ1P) sk := KeyGenerator.NewSecretKey() crs := crsGen.ClockNew() - contextQ := bfvCtx.ContextQ1() - contextPKeys := bfvCtx.ContextP() + contextQ := dbfvCtx.contextQ1 + contextPKeys := dbfvCtx.contextP Ciphertext := bfv.NewCiphertextRandom(params, 1) @@ -756,7 +743,7 @@ func Test_Marshalling(t *testing.T) { t.Run(fmt.Sprintf("PCKS/N=%d/limbQ=%d/limbsP=%d", contextQ.N, len(contextQ.Modulus), len(contextPKeys.Modulus)), func(t *testing.T) { //Check marshalling for the PCKS - KeySwitchProtocol := NewPCKSProtocol(params, bfvCtx.Sigma()) + KeySwitchProtocol := NewPCKSProtocol(params, dbfvCtx.params.Sigma) SwitchShare := KeySwitchProtocol.AllocateShares() pk := KeyGenerator.NewPublicKey(sk) KeySwitchProtocol.GenShare(sk.Get(), pk, Ciphertext, SwitchShare) @@ -795,7 +782,7 @@ func Test_Marshalling(t *testing.T) { t.Run(fmt.Sprintf("CKS/N=%d/limbQ=%d/limbsP=%d", contextQ.N, len(contextQ.Modulus), len(contextPKeys.Modulus)), func(t *testing.T) { //Now for CKSShare ~ its similar to PKSShare - cksp := NewCKSProtocol(params, bfvCtx.Sigma()) + cksp := NewCKSProtocol(params, dbfvCtx.params.Sigma) cksshare := cksp.AllocateShare() skIn := KeyGenerator.NewSecretKey() skOut := KeyGenerator.NewSecretKey() @@ -865,8 +852,8 @@ func Test_Marshalling(t *testing.T) { t.Run(fmt.Sprintf("RTG/N=%d/limbQ=%d/limbsP=%d", contextQ.N, len(contextQ.Modulus), len(contextPKeys.Modulus)), func(t *testing.T) { //check RTGShare - crpGenerator := ring.NewCRPGenerator(nil, bfvCtx.ContextKeys()) - modulus := (bfvCtx.ContextQ1().Modulus) + crpGenerator := ring.NewCRPGenerator(nil, dbfvCtx.contextQ1P) + modulus := (dbfvCtx.contextQ1.Modulus) crp := make([]*ring.Poly, len(modulus)) for j := 0; j < len(modulus); j++ { crp[j] = crpGenerator.ClockNew() //make([]*ring.Poly, bitLog) @@ -915,12 +902,12 @@ func Test_Marshalling(t *testing.T) { func Test_Relin_Marshalling(t *testing.T) { params := bfv.DefaultParams[14] - bfvCtx := bfv.NewContext(params) - contextQ := bfvCtx.ContextQ1() - contextPKeys := bfvCtx.ContextP() - modulus := bfvCtx.ContextQ1().Modulus + dbfvCtx := newDbfvContext(params) + contextQ := dbfvCtx.contextQ1 + contextPKeys := dbfvCtx.contextP + modulus := dbfvCtx.contextQ1.Modulus - crpGenerator := ring.NewCRPGenerator(nil, bfvCtx.ContextKeys()) + crpGenerator := ring.NewCRPGenerator(nil, dbfvCtx.contextQ1P) crp := make([]*ring.Poly, len(modulus)) for j := 0; j < len(modulus); j++ { diff --git a/examples/bfv/examples_bfv.go b/examples/bfv/examples_bfv.go index 624d1534..295c5491 100644 --- a/examples/bfv/examples_bfv.go +++ b/examples/bfv/examples_bfv.go @@ -54,8 +54,6 @@ func obliviousRiding() { encoder := bfv.NewEncoder(params) - bfvContext := bfv.NewContext(params) - // Rider's keygen kgen := bfv.NewKeyGenerator(params) @@ -73,8 +71,8 @@ func obliviousRiding() { fmt.Println("Homomorphic computations on batched integers") fmt.Println("============================================") fmt.Println() - fmt.Printf("Parameters : N=%d, T=%d, logQ = %d (%d limbs), sigma = %f \n", - bfvContext.N(), bfvContext.T(), bfvContext.LogQ(), len(params.Q1), bfvContext.Sigma()) + fmt.Printf("Parameters : N=%d, T=%d, Q = %d limbs, sigma = %f \n", + 1 << params.LogN, params.T, len(params.Q1)+len(params.P), params.Sigma) fmt.Println() maxvalue := uint64(math.Sqrt(float64(params.T))) // max values = floor(sqrt(plaintext modulus)) diff --git a/examples/dbfv/pir/pir.go b/examples/dbfv/pir/pir.go index add9d227..786443e4 100644 --- a/examples/dbfv/pir/pir.go +++ b/examples/dbfv/pir/pir.go @@ -79,11 +79,10 @@ func main() { params := bfv.DefaultParams[13] // default params with N=8192 params.T = 65537 - bfvctx := bfv.NewContext(params) // Common reference polynomial generator keyed with // "lattigo" and seeded with "pir example". - crsGen := ring.NewCRPGenerator([]byte{'l', 'a', 't', 't', 'i', 'g', 'o'}, bfvctx.ContextKeys()) + crsGen := dbfv.NewCRPGenerator(params, []byte{'l', 'a', 't', 't', 'i', 'g', 'o'}) crsGen.Seed([]byte{'p', 'i', 'r', ' ', 'e', 'x', 'a', 'm', 'p', 'l', 'e'}) // Generation of the common reference polynomials diff --git a/examples/dbfv/psi/psi.go b/examples/dbfv/psi/psi.go index 60cd75de..1d3df518 100644 --- a/examples/dbfv/psi/psi.go +++ b/examples/dbfv/psi/psi.go @@ -63,7 +63,7 @@ func main() { params := bfv.DefaultParams[14] params.T = 65537 - bfvctx := bfv.NewContext(params) + bfvctx := bfv.newBFVContect(params) crsGen := ring.NewCRPGenerator([]byte{'l', 'a', 't', 't', 'i', 'g', 'o'}, bfvctx.ContextKeys()) crs := crsGen.ClockNew()