Merge pull request #11 from keep-network/master

Pass a public key bit length when creating a threshold key generator
This commit was merged in pull request #11.
This commit is contained in:
didier amyot authored and GitHub committed 2018-08-10 06:50:46 -04:00
commit 753322e473
6 files changed
+281 -70

No files matched your search

+4
View File
@@ -22,3 +22,7 @@ _testmain.go
*.exe
*.test
*.prof
# IDEs
.vscode/
.idea/
+1 -1
View File
@@ -60,7 +60,7 @@ func TestAsyncGenerator(t *testing.T) {
t.Fatal(err)
}
AreSafePrimes(p, q, test.bitLen, t)
IsSafePrime(p, q, test.bitLen, t)
}
})
}
+44 -22
View File
@@ -2,6 +2,7 @@ package paillier
import (
"crypto/rand"
"errors"
"io"
"math/big"
"time"
@@ -19,18 +20,18 @@ import (
// with Applications to Electronic Voting
// Aarhus University, Dept. of Computer Science, BRICS
type ThresholdKeyGenerator struct {
nbits int
PublicKeyBitLength int
TotalNumberOfDecryptionServers int
Threshold int
Random io.Reader
random io.Reader
// Both p1 and q1 are primes of length nbits - 1
p1 *big.Int
q1 *big.Int
p *big.Int // p is prime of `PublicKeyBitLength/2` bits and `p = 2*p1 + 1`
q *big.Int // q is prime of `PublicKeyBitLength/2` bits and `q = 2*q1 + 1`
p *big.Int // p is prime and p=2*p1+1
q *big.Int // q is prime and q=2*q1+1
n *big.Int // n=p*q
p1 *big.Int // p1 is prime of `PublicKeyBitLength/2 - 1` bits
q1 *big.Int // q1 is prime of `PublicKeyBitLength/2 - 1` bits
n *big.Int // n=p*q and is of `PublicKeyBitLength` bits
m *big.Int // m = p1*q1
nSquare *big.Int // nSquare = n*n
nm *big.Int // nm = n*m
@@ -45,23 +46,44 @@ type ThresholdKeyGenerator struct {
polynomialCoefficients []*big.Int
}
// Preferable way to construct the ThresholdKeyGenerator. No verification
// is done on the input values. You need to be sure that nbits is big enough
// and that Threshold > TotalNumberOfDecryptionServers / 2.
// The plaintext space for the key will be Z_n.
func GetThresholdKeyGenerator(nbits, TotalNumberOfDecryptionServers, Threshold int, random io.Reader) *ThresholdKeyGenerator {
ret := new(ThresholdKeyGenerator)
ret.nbits = nbits
ret.TotalNumberOfDecryptionServers = TotalNumberOfDecryptionServers
ret.Threshold = Threshold
ret.Random = random
return ret
// GetThresholdKeyGenerator is a preferable way to construct the
// ThresholdKeyGenerator.
// Due to the various properties that must be met for the threshold key to be
// considered valid, the minimum public key `N` bit length is 18 bits and the
// public key bit length should be an even number.
// The plaintext space for the key will be `Z_N`.
func GetThresholdKeyGenerator(
publicKeyBitLength int,
totalNumberOfDecryptionServers int,
threshold int,
random io.Reader,
) (*ThresholdKeyGenerator, error) {
if publicKeyBitLength%2 == 1 {
// For an odd n-bit number, we can't find two n/2-bit numbers with two
// the most significant bits set on which multiplied gives an n-bit
// number.
return nil, errors.New("Public key bit length must be an even number")
}
if publicKeyBitLength < 18 {
// We need to find two n/2-bit safe primes, P and Q which are not equal.
// This is not possible for n<18.
return nil, errors.New("Public key bit length must be at least 18 bits")
}
return &ThresholdKeyGenerator{
PublicKeyBitLength: publicKeyBitLength,
TotalNumberOfDecryptionServers: totalNumberOfDecryptionServers,
Threshold: threshold,
random: random,
}, nil
}
func (tkg *ThresholdKeyGenerator) generateSafePrimes() (*big.Int, *big.Int, error) {
concurrencyLevel := 4
timeout := 120 * time.Second
return GenerateSafePrime(tkg.nbits, concurrencyLevel, timeout, tkg.Random)
safePrimeBitLength := tkg.PublicKeyBitLength / 2
return GenerateSafePrime(safePrimeBitLength, concurrencyLevel, timeout, tkg.random)
}
func (tkg *ThresholdKeyGenerator) initPandP1() error {
@@ -112,7 +134,7 @@ func (tkg *ThresholdKeyGenerator) initPsAndQs() error {
// v generates a cyclic group of squares in Zn^2.
func (tkg *ThresholdKeyGenerator) computeV() error {
var err error
tkg.v, err = GetRandomGeneratorOfTheQuadraticResidue(tkg.nSquare, tkg.Random)
tkg.v, err = GetRandomGeneratorOfTheQuadraticResidue(tkg.nSquare, tkg.random)
return err
}
@@ -165,7 +187,7 @@ func (tkg *ThresholdKeyGenerator) generateHidingPolynomial() error {
tkg.polynomialCoefficients[0] = tkg.d
var err error
for i := 1; i < tkg.Threshold; i++ {
tkg.polynomialCoefficients[i], err = rand.Int(tkg.Random, tkg.nm)
tkg.polynomialCoefficients[i], err = rand.Int(tkg.random, tkg.nm)
if err != nil {
return err
}
+194 -39
View File
@@ -2,6 +2,7 @@ package paillier
import (
"crypto/rand"
"errors"
"math/big"
"reflect"
"testing"
@@ -11,44 +12,183 @@ var MockGenerateSafePrimes = func() (*big.Int, *big.Int, error) {
return big.NewInt(887), big.NewInt(443), nil
}
func TestGenerateSafePrimesOfThresholdKeyGenerator(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Random = rand.Reader
p, q, err := tkh.generateSafePrimes()
func TestCreateThresholdKeyGenerator(t *testing.T) {
var tests = map[string]struct {
publicKeyBitLength int
totalNumberOfDecryptionServers int
threshold int
expectedError error
}{
"generator successfully created for 20 bit key length": {
publicKeyBitLength: 20,
totalNumberOfDecryptionServers: 6,
threshold: 5,
},
"generator can't be created for 19 bit key length": {
publicKeyBitLength: 19,
totalNumberOfDecryptionServers: 4,
threshold: 3,
expectedError: errors.New("Public key bit length must be an even number"),
},
"generator successfully created for 18 bit key length": {
publicKeyBitLength: 18,
totalNumberOfDecryptionServers: 4,
threshold: 3,
},
"generator can't be created for 17 bit key length": {
publicKeyBitLength: 17,
totalNumberOfDecryptionServers: 4,
threshold: 3,
expectedError: errors.New("Public key bit length must be an even number"),
},
"generator can't be created for 16 bit key length": {
publicKeyBitLength: 16,
totalNumberOfDecryptionServers: 4,
threshold: 3,
expectedError: errors.New("Public key bit length must be at least 18 bits"),
},
}
for testName, test := range tests {
t.Run(testName, func(t *testing.T) {
gen, err := GetThresholdKeyGenerator(
test.publicKeyBitLength,
test.totalNumberOfDecryptionServers,
test.threshold,
rand.Reader,
)
if !reflect.DeepEqual(test.expectedError, err) {
t.Fatalf(
"Unexpected error\nActual: %v\nExpected: %v",
err,
test.expectedError,
)
}
if test.expectedError == nil {
if gen == nil {
t.Fatal(
"Got nil generator, it should be successfully created",
)
}
if test.publicKeyBitLength != gen.PublicKeyBitLength {
t.Fatalf(
"Unexpected public key length\nExpected: %v\nActual: %v",
test.publicKeyBitLength,
gen.PublicKeyBitLength,
)
}
if test.threshold != gen.Threshold {
t.Fatalf(
"Unexpected threshold\nExpected: %v\nActual: %v",
test.threshold,
gen.Threshold,
)
}
if test.totalNumberOfDecryptionServers != gen.TotalNumberOfDecryptionServers {
t.Fatalf(
"Unexpected number of decryption servers\nExpected: %v\nActual: %v",
test.totalNumberOfDecryptionServers,
gen.TotalNumberOfDecryptionServers,
)
}
}
})
}
}
func TestGenerateNumbersOfCorrectBitLength(t *testing.T) {
var tests = map[string]struct {
publicKeyLength int
expectedPrimeLength int
}{
"public key bit length = 32, prime bit length = 16": {
publicKeyLength: 32,
expectedPrimeLength: 16,
},
"public key bit length = 64, prime bit length = 32": {
publicKeyLength: 64,
expectedPrimeLength: 32,
},
}
for testName, test := range tests {
t.Run(testName, func(t *testing.T) {
gen, err := GetThresholdKeyGenerator(test.publicKeyLength, 10, 6, rand.Reader)
if err != nil {
t.Error(err)
t.Fatal(err)
}
err = gen.initNumerialValues()
if err != nil {
t.Fatal(err)
}
if gen.p.BitLen() != test.expectedPrimeLength {
t.Fatalf(
"Unexpected prime bit length\nExpected %v\n Actual %v",
test.expectedPrimeLength,
gen.p.BitLen(),
)
}
if gen.q.BitLen() != test.expectedPrimeLength {
t.Fatalf(
"Unexpected prime bit length\nExpected %v\n Actual %v",
test.expectedPrimeLength,
gen.q.BitLen(),
)
}
if gen.n.BitLen() != test.publicKeyLength {
t.Fatalf(
"Unexpected modulus bit length\nExpected %v\n Actual %v",
test.publicKeyLength,
gen.n.BitLen(),
)
}
if new(big.Int).Mul(gen.p, gen.q).Cmp(gen.n) != 0 {
t.Fatal("n != pq")
}
})
}
AreSafePrimes(p, q, 10, t)
}
func TestInitPandP1(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Random = rand.Reader
tkh, err := GetThresholdKeyGenerator(32, 4, 3, rand.Reader)
if err != nil {
t.Fatal(err)
}
tkh.initPandP1()
AreSafePrimes(tkh.p, tkh.p1, 10, t)
IsSafePrime(tkh.p, tkh.p1, 16, t)
}
func TestInitQandQ1(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Random = rand.Reader
tkh, err := GetThresholdKeyGenerator(32, 4, 3, rand.Reader)
if err != nil {
t.Fatal(err)
}
tkh.initQandQ1()
AreSafePrimes(tkh.q, tkh.q1, 10, t)
IsSafePrime(tkh.q, tkh.q1, 16, t)
}
func TestInitPsAndQs(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Random = rand.Reader
tkh, err := GetThresholdKeyGenerator(32, 4, 3, rand.Reader)
if err != nil {
t.Fatal(err)
}
tkh.initPsAndQs()
AreSafePrimes(tkh.p, tkh.p1, 10, t)
AreSafePrimes(tkh.q, tkh.q1, 10, t)
IsSafePrime(tkh.p, tkh.p1, 16, t)
IsSafePrime(tkh.q, tkh.q1, 16, t)
}
func TestArePsAndQsGood(t *testing.T) {
@@ -102,9 +242,10 @@ func TestInitD(t *testing.T) {
}
func TestInitNumerialValues(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Random = rand.Reader
tkh, err := GetThresholdKeyGenerator(32, 4, 3, rand.Reader)
if err != nil {
t.Fatal(err)
}
if err := tkh.initNumerialValues(); err != nil {
t.Error(err)
@@ -112,10 +253,11 @@ func TestInitNumerialValues(t *testing.T) {
}
func TestGenerateHidingPolynomial(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Threshold = 10
tkh.Random = rand.Reader
tkh, err := GetThresholdKeyGenerator(32, 15, 10, rand.Reader)
if err != nil {
t.Fatal(err)
}
if err := tkh.initNumerialValues(); err != nil {
t.Error(err)
}
@@ -137,10 +279,11 @@ func TestGenerateHidingPolynomial(t *testing.T) {
}
func TestComputeShare(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Threshold = 3
tkh.TotalNumberOfDecryptionServers = 5
tkh, err := GetThresholdKeyGenerator(32, 5, 3, rand.Reader)
if err != nil {
t.Fatal(err)
}
tkh.nm = b(103)
tkh.polynomialCoefficients = []*big.Int{b(29), b(88), b(51)}
share := tkh.computeShare(2)
@@ -150,11 +293,11 @@ func TestComputeShare(t *testing.T) {
}
func TestCreateShares(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Threshold = 10
tkh.TotalNumberOfDecryptionServers = 100
tkh.Random = rand.Reader
tkh, err := GetThresholdKeyGenerator(32, 100, 10, rand.Reader)
if err != nil {
t.Fatal(err)
}
if err := tkh.initNumerialValues(); err != nil {
t.Error(err)
}
@@ -180,14 +323,22 @@ func TestCreateViArray(t *testing.T) {
}
func TestGetThresholdKeyGenerator(t *testing.T) {
tkh := GetThresholdKeyGenerator(50, 10, 6, rand.Reader)
tkh, err := GetThresholdKeyGenerator(50, 10, 6, rand.Reader)
if err != nil {
t.Fatal(err)
}
if err := tkh.initNumerialValues(); err != nil {
t.Error(nil)
}
}
func TestGenerate(t *testing.T) {
tkh := GetThresholdKeyGenerator(32, 10, 6, rand.Reader)
tkh, err := GetThresholdKeyGenerator(32, 10, 6, rand.Reader)
if err != nil {
t.Fatal(err)
}
tpks, err := tkh.Generate()
if err != nil {
t.Error(err)
@@ -213,7 +364,11 @@ func TestGenerate(t *testing.T) {
}
func TestComputeV(t *testing.T) {
tkh := GetThresholdKeyGenerator(32, 10, 6, rand.Reader)
tkh, err := GetThresholdKeyGenerator(32, 10, 6, rand.Reader)
if err != nil {
t.Fatal(err)
}
tkh.n = b(1907 * 1823)
tkh.nSquare = new(big.Int).Mul(tkh.n, tkh.n)
for i := 0; i < 100; i++ {
+35 -7
View File
@@ -8,7 +8,11 @@ import (
)
func getThresholdPrivateKey() *ThresholdPrivateKey {
tkh := GetThresholdKeyGenerator(32, 10, 6, rand.Reader)
tkh, err := GetThresholdKeyGenerator(32, 10, 6, rand.Reader)
if err != nil {
panic(err)
}
tpks, err := tkh.Generate()
if err != nil {
panic(err)
@@ -184,7 +188,11 @@ func TestupdateCprime(t *testing.T) {
}
func TestEncryptingDecryptingSimple(t *testing.T) {
tkh := GetThresholdKeyGenerator(10, 2, 1, rand.Reader)
tkh, err := GetThresholdKeyGenerator(32, 2, 1, rand.Reader)
if err != nil {
t.Fatal(err)
}
tpks, err := tkh.Generate()
if err != nil {
t.Error(err)
@@ -205,7 +213,11 @@ func TestEncryptingDecryptingSimple(t *testing.T) {
}
func TestEncryptingDecrypting(t *testing.T) {
tkh := GetThresholdKeyGenerator(10, 2, 2, rand.Reader)
tkh, err := GetThresholdKeyGenerator(32, 2, 2, rand.Reader)
if err != nil {
t.Fatal(err)
}
tpks, err := tkh.Generate()
if err != nil {
t.Error(err)
@@ -227,7 +239,11 @@ func TestEncryptingDecrypting(t *testing.T) {
}
func TestHomomorphicThresholdEncryption(t *testing.T) {
tkh := GetThresholdKeyGenerator(10, 2, 2, rand.Reader)
tkh, err := GetThresholdKeyGenerator(32, 2, 2, rand.Reader)
if err != nil {
t.Fatal(err)
}
tpks, _ := tkh.Generate()
plainText1 := b(13)
@@ -278,7 +294,11 @@ func TestValidate(t *testing.T) {
}
func TestCombinePartialDecryptionsZKP(t *testing.T) {
tkh := GetThresholdKeyGenerator(10, 2, 2, rand.Reader)
tkh, err := GetThresholdKeyGenerator(32, 2, 2, rand.Reader)
if err != nil {
t.Fatal(err)
}
tpks, err := tkh.Generate()
if err != nil {
t.Error(err)
@@ -311,7 +331,11 @@ func TestCombinePartialDecryptionsZKP(t *testing.T) {
}
func TestCombinePartialDecryptionsWith100Shares(t *testing.T) {
tkh := GetThresholdKeyGenerator(10, 100, 50, rand.Reader)
tkh, err := GetThresholdKeyGenerator(32, 100, 50, rand.Reader)
if err != nil {
t.Fatal(err)
}
tpks, err := tkh.Generate()
if err != nil {
t.Error(err)
@@ -338,7 +362,11 @@ func TestCombinePartialDecryptionsWith100Shares(t *testing.T) {
}
func TestVerifyDecryption(t *testing.T) {
tkh := GetThresholdKeyGenerator(10, 2, 2, rand.Reader)
tkh, err := GetThresholdKeyGenerator(32, 2, 2, rand.Reader)
if err != nil {
t.Fatal(err)
}
tpks, err := tkh.Generate()
pk := &tpks[0].ThresholdPublicKey
+3 -1
View File
@@ -59,7 +59,9 @@ func TestFactorial(t *testing.T) {
}
}
func AreSafePrimes(p, q *big.Int, expectedLength int, t *testing.T) {
// IsSafePrime checks whether `p` is a safe prime. A safe prime is a prime
// number of the form `2q + 1`, where `q` is also a prime.
func IsSafePrime(p, q *big.Int, expectedLength int, t *testing.T) {
if l := p.BitLen(); l != expectedLength {
t.Error("p does not have the good length. ", l)
}