mirror of
https://github.com/tuneinsight/lattigo.git
synced 2025-09-13 03:27:14 +00:00
improvements on bfv/params.go
This commit is contained in:
committed by
ChristianMct
parent
1f3d2e829b
commit
925c1de364
@@ -13,7 +13,7 @@ type BfvContext struct {
|
||||
// Plaintext Modulus
|
||||
t uint64
|
||||
|
||||
// floor(Q/t) mod each Qi in montgomeryform
|
||||
// floor(Q/T) mod each Qi in montgomeryform
|
||||
DeltaMont []uint64
|
||||
Delta []uint64
|
||||
|
||||
@@ -39,7 +39,7 @@ type BfvContext struct {
|
||||
galElRotColLeft []uint64
|
||||
galElRotColRight []uint64
|
||||
|
||||
// Checksum of [n, [modulies]]
|
||||
// Checksum of [N, [modulies]]
|
||||
checksum []byte
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
func BenchmarkBFVScheme(b *testing.B) {
|
||||
|
||||
paramSets := ParamSets60
|
||||
paramSets := DefaultParams
|
||||
|
||||
bitDecomps := []uint64{60}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ func Test_BFV(t *testing.T) {
|
||||
|
||||
var err error
|
||||
|
||||
paramSets := ParamSets60[1:2]
|
||||
paramSets := DefaultParams[1:2]
|
||||
|
||||
bitDecomps := []uint64{16}
|
||||
|
||||
|
||||
@@ -1,19 +1,39 @@
|
||||
package bfv
|
||||
|
||||
import "github.com/lca1/lattigo/ring"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/lca1/lattigo/ring"
|
||||
"github.com/lca1/lattigo/utils"
|
||||
"math"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
//https://projects.csail.mit.edu/HEWorkshop/HomomorphicEncryptionStandard2018.pdf
|
||||
// MaxN is the largest supported polynomial modulus degree
|
||||
const MaxN = 1 << 15
|
||||
|
||||
// MaxModuliCount is the largest supported number of 60 moduli in the RNS representation
|
||||
const MaxModuliCount = 256
|
||||
|
||||
// Power of 2 plaintext modulus
|
||||
var Tpow2 = []uint64{2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648, 4294967296}
|
||||
var Tpow2 = []uint64{2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,
|
||||
524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912,
|
||||
1073741824, 2147483648, 4294967296}
|
||||
|
||||
// Plaintext modulus allowing batching for the corresponding N in ascending bitsize.
|
||||
var TBatching4096 = []uint64{40961, 114689, 188417, 417793, 1032193, 2056193, 4169729, 8380417, 16760833, 33538049, 67084289, 134176769, 268369921, 536813569, 1073692673, 2147377153, 4294828033}
|
||||
var TBatching8192 = []uint64{65537, 114689, 163841, 1032193, 1785857, 4079617, 8273921, 16760833, 33538049, 67043329, 133857281, 268369921, 536690689, 1073692673, 2147352577, 4294475777}
|
||||
var TBatching16384 = []uint64{65537, 163841, 786433, 1769473, 3735553, 8257537, 16580609, 33292289, 67043329, 133857281, 268369921, 536641537, 1073643521, 2147352577, 4294475777}
|
||||
var TBatching32768 = []uint64{65537, 786433, 1769473, 3735553, 8257537, 16580609, 33292289, 67043329, 132710401, 268369921, 536608769, 1073479681, 2147352577, 4293918721}
|
||||
var TBatching = map[uint64][]uint64{
|
||||
4096: {40961, 114689, 188417, 417793, 1032193, 2056193, 4169729, 8380417, 16760833, 33538049, 67084289, 134176769,
|
||||
268369921, 536813569, 1073692673, 2147377153, 4294828033},
|
||||
8192: {65537, 114689, 163841, 1032193, 1785857, 4079617, 8273921, 16760833, 33538049, 67043329, 133857281,
|
||||
268369921, 536690689, 1073692673, 2147352577, 4294475777},
|
||||
16384: {65537, 163841, 786433, 1769473, 3735553, 8257537, 16580609, 33292289, 67043329, 133857281, 268369921,
|
||||
536641537, 1073643521, 2147352577, 4294475777},
|
||||
32768: {65537, 786433, 1769473, 3735553, 8257537, 16580609, 33292289, 67043329, 132710401, 268369921, 536608769,
|
||||
1073479681, 2147352577, 4293918721},
|
||||
}
|
||||
|
||||
type Params struct {
|
||||
// Parameters represents a given parameter set for the BFV cryptosystem.
|
||||
type Parameters struct {
|
||||
N uint64
|
||||
T uint64
|
||||
Qi []uint64
|
||||
@@ -21,10 +41,63 @@ type Params struct {
|
||||
Sigma float64
|
||||
}
|
||||
|
||||
// ~128 bit security with sigma = 3.19 and secret with ternary distribution
|
||||
var ParamSets60 = []Params{
|
||||
// DefaultParams is an array default parameters with increasing homomorphic capacity.
|
||||
// These parameters correspond to 128 bit security level for secret keys in the ternary distribution
|
||||
// (see //https://projects.csail.mit.edu/HEWorkshop/HomomorphicEncryptionStandard2018.pdf).
|
||||
var DefaultParams = []Parameters{
|
||||
{4096, 65537, ring.Qi60[len(ring.Qi60)-2:], ring.Pi60[len(ring.Pi60)-3:], 3.19},
|
||||
{8192, 65537, ring.Qi60[len(ring.Qi60)-4:], ring.Pi60[len(ring.Pi60)-5:], 3.19},
|
||||
{16384, 65537, ring.Qi60[len(ring.Qi60)-8:], ring.Pi60[len(ring.Pi60)-9:], 3.19},
|
||||
{32768, 65537, ring.Qi60[len(ring.Qi60)-16:], ring.Pi60[len(ring.Pi60)-17:], 3.19},
|
||||
}
|
||||
|
||||
// Equals compares two sets of parameters for equality
|
||||
func (p *Parameters) Equals(other *Parameters) bool {
|
||||
if p == other {
|
||||
return true
|
||||
}
|
||||
return p.N == other.N && EqualSlice(p.Qi, other.Qi) && EqualSlice(p.Pi, other.Pi) && p.Sigma == other.Sigma
|
||||
}
|
||||
|
||||
// MarshalBinary returns a []byte representation of the parameter set
|
||||
func (p *Parameters) MarshalBinary() ([]byte, error) {
|
||||
if p.N == 0 { // if N is 0, then p is the zero value
|
||||
return []byte{}, nil
|
||||
}
|
||||
b := utils.NewBuffer(make([]byte, 0, 3+((2+len(p.Qi)+len(p.Pi))<<3)))
|
||||
b.WriteUint8(uint8(bits.Len64(p.N) - 1))
|
||||
b.WriteUint8(uint8(len(p.Qi)))
|
||||
b.WriteUint8(uint8(len(p.Pi)))
|
||||
b.WriteUint64(p.T)
|
||||
b.WriteUint64(uint64(p.Sigma * (1 << 32)))
|
||||
b.WriteUint64Slice(p.Qi)
|
||||
b.WriteUint64Slice(p.Pi)
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnMarshalBinary decodes a []byte into a parameter set struct
|
||||
func (p *Parameters) UnMarshalBinary(data []byte) error {
|
||||
if len(data) < 3 {
|
||||
return errors.New("invalid parameters encoding")
|
||||
}
|
||||
b := utils.NewBuffer(data)
|
||||
p.N = 1 << uint64(b.ReadUint8())
|
||||
if p.N > MaxN {
|
||||
return errors.New("polynomial degree is too large")
|
||||
}
|
||||
lenQi := uint64(b.ReadUint8())
|
||||
if lenQi > MaxModuliCount {
|
||||
return fmt.Errorf("len(Qi) is larger than %d", MaxModuliCount)
|
||||
}
|
||||
lenPi := uint64(b.ReadUint8())
|
||||
if lenPi > MaxModuliCount {
|
||||
return fmt.Errorf("len(Pi) is larger than %d", MaxModuliCount)
|
||||
}
|
||||
p.T = b.ReadUint64()
|
||||
p.Sigma = math.Round((float64(b.ReadUint64())/float64(1<<32))*100) / 100
|
||||
p.Qi = make([]uint64, lenQi, lenQi)
|
||||
p.Pi = make([]uint64, lenPi, lenPi)
|
||||
b.ReadUint64Slice(p.Qi)
|
||||
b.ReadUint64Slice(p.Pi)
|
||||
return nil
|
||||
}
|
||||
|
||||
27
bfv/params_test.go
Normal file
27
bfv/params_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package bfv
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParams_BinaryMarshaller(t *testing.T) {
|
||||
t.Run("ZeroValue", func(t *testing.T) {
|
||||
bytes, err := (&Parameters{}).MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []byte{}, bytes)
|
||||
var p Parameters
|
||||
err = p.UnMarshalBinary(bytes)
|
||||
assert.NotNil(t, err)
|
||||
})
|
||||
t.Run("SupportedParams", func(t *testing.T) {
|
||||
for _, params := range DefaultParams {
|
||||
bytes, err := params.MarshalBinary()
|
||||
assert.Nil(t, err)
|
||||
var p Parameters
|
||||
err = p.UnMarshalBinary(bytes)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, params, p)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
func Benchmark_DBFVScheme(b *testing.B) {
|
||||
|
||||
paramSets := bfv.ParamSets60[3:4]
|
||||
paramSets := bfv.DefaultParams[3:4]
|
||||
bitDecomps := []uint64{60}
|
||||
nParties := []int{2}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
func Test_DBFVScheme(t *testing.T) {
|
||||
|
||||
paramSets := bfv.ParamSets60[0:1]
|
||||
paramSets := bfv.DefaultParams[0:1]
|
||||
bitDecomps := []uint64{60}
|
||||
nParties := []int{5}
|
||||
|
||||
|
||||
9
go.mod
9
go.mod
@@ -2,7 +2,8 @@ module github.com/lca1/lattigo
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422 // indirect
|
||||
)
|
||||
require golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
||||
|
||||
require golang.org/x/lint v0.0.0-20190409202823-959b441ac422
|
||||
|
||||
require github.com/stretchr/testify v0.0.0-20190311161405-34c6fa2dc709
|
||||
|
||||
10
go.sum
10
go.sum
@@ -1,7 +1,14 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v0.0.0-20190311161405-34c6fa2dc709 h1:zN7m1FsHm1PeW8oJ3JvZPC5Cc1lWnEiHtS1i6DpXcm0=
|
||||
github.com/stretchr/testify v0.0.0-20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422 h1:QzoH/1pFpZguR8NrRHLcO6jKqfv2zpuSqZLgdm7ZmjI=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -9,5 +16,4 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
|
||||
56
utils/buffer.go
Normal file
56
utils/buffer.go
Normal file
@@ -0,0 +1,56 @@
|
||||
// Package containing helper structures and function
|
||||
package utils
|
||||
|
||||
// Buffer is a simple wrapper around a []byte to facilitate efficient marshaling of lattigo's objects
|
||||
type Buffer struct {
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// NewBuffer creates a new buffer from the provided backing slice
|
||||
func NewBuffer(s []byte) *Buffer {
|
||||
return &Buffer{s}
|
||||
}
|
||||
|
||||
func (b *Buffer) WriteUint8(c byte) {
|
||||
b.buf = append(b.buf, c)
|
||||
}
|
||||
|
||||
func (b *Buffer) WriteUint64(v uint64) {
|
||||
b.buf = append(b.buf, byte(v>>56),
|
||||
byte(v>>48),
|
||||
byte(v>>40),
|
||||
byte(v>>32),
|
||||
byte(v>>24),
|
||||
byte(v>>16),
|
||||
byte(v>>8),
|
||||
byte(v))
|
||||
}
|
||||
|
||||
func (b *Buffer) WriteUint64Slice(s []uint64) {
|
||||
for _, v := range s {
|
||||
b.WriteUint64(v)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Buffer) ReadUint8() byte {
|
||||
v := b.buf[0]
|
||||
b.buf = b.buf[1:]
|
||||
return v
|
||||
}
|
||||
|
||||
func (b *Buffer) ReadUint64() uint64 {
|
||||
v := b.buf[:8]
|
||||
b.buf = b.buf[8:]
|
||||
return uint64(v[7]) | uint64(v[6])<<8 | uint64(v[5])<<16 | uint64(v[4])<<24 |
|
||||
uint64(v[3])<<32 | uint64(v[2])<<40 | uint64(v[1])<<48 | uint64(v[0])<<56
|
||||
}
|
||||
|
||||
func (b *Buffer) ReadUint64Slice(rec []uint64) {
|
||||
for i := range rec {
|
||||
rec[i] = b.ReadUint64()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Buffer) Bytes() []byte {
|
||||
return b.buf
|
||||
}
|
||||
39
utils/buffer_test.go
Normal file
39
utils/buffer_test.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// Package containing helper structures and function
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewBuffer(t *testing.T) {
|
||||
assert.Equal(t, []byte(nil), NewBuffer(nil).Bytes())
|
||||
assert.Equal(t, []byte{}, NewBuffer([]byte{}).Bytes())
|
||||
assert.Equal(t, []byte{1, 2, 3}, NewBuffer([]byte{1, 2, 3}).Bytes())
|
||||
}
|
||||
|
||||
func TestBuffer_WriteReadUint8(t *testing.T) {
|
||||
b := NewBuffer(make([]byte, 0, 1))
|
||||
b.WriteUint8(0xff)
|
||||
assert.Equal(t, []byte{0xff}, b.Bytes())
|
||||
assert.Equal(t, byte(0xff), b.ReadUint8())
|
||||
assert.Equal(t, []byte{}, b.Bytes())
|
||||
}
|
||||
|
||||
func TestBuffer_WriteReadUint64(t *testing.T) {
|
||||
b := NewBuffer(make([]byte, 0, 8))
|
||||
b.WriteUint64(0x1122334455667788)
|
||||
assert.Equal(t, []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, b.Bytes())
|
||||
assert.Equal(t, uint64(0x1122334455667788), b.ReadUint64())
|
||||
assert.Equal(t, []byte{}, b.Bytes())
|
||||
}
|
||||
|
||||
func TestBuffer_WriteReadUint64Slice(t *testing.T) {
|
||||
b := NewBuffer(make([]byte, 0, 8))
|
||||
b.WriteUint64Slice([]uint64{0x1122334455667788})
|
||||
assert.Equal(t, []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, b.Bytes())
|
||||
s := make([]uint64, 1, 1)
|
||||
b.ReadUint64Slice(s)
|
||||
assert.Equal(t, []uint64{0x1122334455667788}, s)
|
||||
assert.Equal(t, []byte{}, b.Bytes())
|
||||
}
|
||||
Reference in New Issue
Block a user