Merge pull request #2 from keep-network/master-with-bson
Documentation improvements, code cleaned up
This commit was merged in pull request #2.
This commit is contained in:
8 files changed
+519
-386
No files matched your search
+13
-33
@@ -57,28 +57,25 @@ type dbThresholdKey struct {
|
||||
V string
|
||||
Vi []string
|
||||
N string
|
||||
G string
|
||||
}
|
||||
|
||||
func (this *dbThresholdKey) FromThresholdKey(key *ThresholdKey) {
|
||||
func (this *dbThresholdKey) FromThresholdPublicKey(key *ThresholdPublicKey) {
|
||||
this.TotalNumberOfDecryptionServers = key.TotalNumberOfDecryptionServers
|
||||
this.Threshold = key.Threshold
|
||||
this.V = fmt.Sprintf("%x", key.V)
|
||||
this.N = fmt.Sprintf("%x", key.N)
|
||||
this.G = fmt.Sprintf("%x", key.G)
|
||||
this.Vi = make([]string, len(key.Vi))
|
||||
for i, vi := range key.Vi {
|
||||
this.Vi[i] = fmt.Sprintf("%x", vi)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *dbThresholdKey) ToThresholdKey(key *ThresholdKey) error {
|
||||
func (this *dbThresholdKey) ToThresholdPublicKey(key *ThresholdPublicKey) error {
|
||||
key.TotalNumberOfDecryptionServers = this.TotalNumberOfDecryptionServers
|
||||
key.Threshold = this.Threshold
|
||||
oks := make([]bool, 3)
|
||||
oks := make([]bool, 2)
|
||||
key.V, oks[0] = new(big.Int).SetString(this.V, 16)
|
||||
key.N, oks[1] = new(big.Int).SetString(this.N, 16)
|
||||
key.G, oks[2] = new(big.Int).SetString(this.G, 16)
|
||||
if !all(oks) {
|
||||
return errors.New("not hexadecimal")
|
||||
}
|
||||
@@ -94,41 +91,35 @@ func (this *dbThresholdKey) ToThresholdKey(key *ThresholdKey) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *ThresholdKey) GetBSON() (interface{}, error) {
|
||||
func (this *ThresholdPublicKey) GetBSON() (interface{}, error) {
|
||||
r := new(dbThresholdKey)
|
||||
r.FromThresholdKey(this)
|
||||
r.FromThresholdPublicKey(this)
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (this *ThresholdKey) SetBSON(raw bson.Raw) error {
|
||||
func (this *ThresholdPublicKey) SetBSON(raw bson.Raw) error {
|
||||
r := new(dbThresholdKey)
|
||||
if err := raw.Unmarshal(r); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.ToThresholdKey(this)
|
||||
return r.ToThresholdPublicKey(this)
|
||||
}
|
||||
|
||||
type dbPrivateKey struct {
|
||||
N string `bson:",omitempty"`
|
||||
G string `bson:",omitempty"`
|
||||
Lambda string `bson:",omitempty"`
|
||||
Mu string `bson:",omitempty"`
|
||||
}
|
||||
|
||||
func (this *PrivateKey) GetBSON() (interface{}, error) {
|
||||
m := make(map[string]string)
|
||||
if this.G != nil {
|
||||
m["g"] = fmt.Sprintf("%x", this.G)
|
||||
}
|
||||
|
||||
if this.N != nil {
|
||||
m["n"] = fmt.Sprintf("%x", this.N)
|
||||
}
|
||||
if this.Lambda != nil {
|
||||
m["lambda"] = fmt.Sprintf("%x", this.Lambda)
|
||||
}
|
||||
if this.Mu != nil {
|
||||
m["mu"] = fmt.Sprintf("%x", this.Mu)
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
@@ -143,21 +134,13 @@ func (this *PrivateKey) SetBSON(raw bson.Raw) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if c.G != "" {
|
||||
this.G, err = fromHex(c.G)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if c.Lambda != "" {
|
||||
this.Lambda, err = fromHex(c.Lambda)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if c.Mu != "" {
|
||||
this.Mu, err = fromHex(c.Mu)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -167,7 +150,6 @@ type dbPartialDecryptionZKP struct {
|
||||
E string `json:"e"`
|
||||
C string `json:"c"`
|
||||
V string `json:"v"`
|
||||
G string `json:"g"`
|
||||
N string `json:"n"`
|
||||
Vi []string `json:"vi"`
|
||||
Decryption string `json:"decryption"`
|
||||
@@ -182,7 +164,6 @@ func (this *dbPartialDecryptionZKP) FromPartialDecryptionZKP(pd *PartialDecrypti
|
||||
this.Threshold = pd.Key.Threshold
|
||||
this.Z = fmt.Sprintf("%x", pd.Z)
|
||||
this.E = fmt.Sprintf("%x", pd.E)
|
||||
this.G = fmt.Sprintf("%x", pd.Key.G)
|
||||
this.N = fmt.Sprintf("%x", pd.Key.N)
|
||||
this.C = fmt.Sprintf("%x", pd.C)
|
||||
this.V = fmt.Sprintf("%x", pd.Key.V)
|
||||
@@ -194,9 +175,9 @@ func (this *dbPartialDecryptionZKP) FromPartialDecryptionZKP(pd *PartialDecrypti
|
||||
}
|
||||
|
||||
func (this *dbPartialDecryptionZKP) ToPartialDecryptionZKP(pd *PartialDecryptionZKP) error {
|
||||
pd.Key = new(ThresholdKey)
|
||||
pd.Key = new(ThresholdPublicKey)
|
||||
|
||||
var oks = make([]bool, 7)
|
||||
var oks = make([]bool, 6)
|
||||
|
||||
pd.Id = this.Id
|
||||
pd.Key.TotalNumberOfDecryptionServers = this.TotalNumberOfDecryptionServers
|
||||
@@ -205,9 +186,8 @@ func (this *dbPartialDecryptionZKP) ToPartialDecryptionZKP(pd *PartialDecryption
|
||||
pd.E, oks[1] = new(big.Int).SetString(this.E, 16)
|
||||
pd.C, oks[2] = new(big.Int).SetString(this.C, 16)
|
||||
pd.Key.V, oks[3] = new(big.Int).SetString(this.V, 16)
|
||||
pd.Key.G, oks[4] = new(big.Int).SetString(this.G, 16)
|
||||
pd.Key.N, oks[5] = new(big.Int).SetString(this.N, 16)
|
||||
pd.Decryption, oks[6] = new(big.Int).SetString(this.Decryption, 16)
|
||||
pd.Key.N, oks[4] = new(big.Int).SetString(this.N, 16)
|
||||
pd.Decryption, oks[5] = new(big.Int).SetString(this.Decryption, 16)
|
||||
|
||||
if !all(oks) {
|
||||
fmt.Println(oks)
|
||||
|
||||
+11
-7
@@ -81,18 +81,17 @@ func TestGetBSONEmptyKey(t *testing.T) {
|
||||
|
||||
func TestPartialDecryptionZKPJsonification(t *testing.T) {
|
||||
pd := new(PartialDecryptionZKP)
|
||||
pd.Key = new(ThresholdKey)
|
||||
pd.Key = new(ThresholdPublicKey)
|
||||
pd.Key.Threshold = 98
|
||||
pd.Key.TotalNumberOfDecryptionServers = 230
|
||||
pd.Id = 1
|
||||
pd.Key.Vi = []*big.Int{b(77), b(67)} // vi is 67
|
||||
pd.Key.Vi = []*big.Int{b(77), b(67)}
|
||||
pd.Key.N = b(131)
|
||||
pd.Key.V = b(101)
|
||||
pd.Decryption = b(171)
|
||||
pd.E = b(112)
|
||||
pd.C = b(99)
|
||||
pd.Key.N = b(345)
|
||||
pd.Key.G = b(99)
|
||||
pd.Z = b(88)
|
||||
|
||||
AssertJSONIsGood(pd, new(PartialDecryptionZKP), t)
|
||||
@@ -100,7 +99,7 @@ func TestPartialDecryptionZKPJsonification(t *testing.T) {
|
||||
|
||||
func TestPartialDecryptionZKPBSONification(t *testing.T) {
|
||||
pd := new(PartialDecryptionZKP)
|
||||
pd.Key = new(ThresholdKey)
|
||||
pd.Key = new(ThresholdPublicKey)
|
||||
pd.Key.Threshold = 98
|
||||
pd.Key.TotalNumberOfDecryptionServers = 230
|
||||
pd.Id = 1
|
||||
@@ -111,13 +110,18 @@ func TestPartialDecryptionZKPBSONification(t *testing.T) {
|
||||
pd.E = b(112)
|
||||
pd.C = b(99)
|
||||
pd.Key.N = b(345)
|
||||
pd.Key.G = b(99)
|
||||
pd.Z = b(88)
|
||||
|
||||
AssertBSONIsGood(pd, new(PartialDecryptionZKP), t)
|
||||
}
|
||||
|
||||
func TestThresholdKeyBSON(t *testing.T) {
|
||||
key := &ThresholdKey{PublicKey{b(9), b(8), nil}, 7, 6, b(3), []*big.Int{b(2), b(34)}}
|
||||
AssertBSONIsGood(key, new(ThresholdKey), t)
|
||||
key := &ThresholdPublicKey{
|
||||
PublicKey: PublicKey{b(9)},
|
||||
TotalNumberOfDecryptionServers: 7,
|
||||
Threshold: 6,
|
||||
V: b(3),
|
||||
Vi: []*big.Int{b(2), b(34)},
|
||||
}
|
||||
AssertBSONIsGood(key, new(ThresholdPublicKey), t)
|
||||
}
|
||||
+48
-38
@@ -7,29 +7,28 @@ import (
|
||||
)
|
||||
|
||||
type PublicKey struct {
|
||||
N, G *big.Int // usually G is set to N+1
|
||||
n2 *big.Int // the cache value of N^2
|
||||
N *big.Int
|
||||
}
|
||||
|
||||
func (this *PublicKey) GetBSON() (interface{}, error) {
|
||||
m := make(map[string]string)
|
||||
m["g"] = fmt.Sprintf("%x", this.G)
|
||||
m["n"] = fmt.Sprintf("%x", this.N)
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (this *PublicKey) GetNSquare() *big.Int {
|
||||
if this.n2 != nil {
|
||||
return this.n2
|
||||
}
|
||||
this.n2 = new(big.Int).Mul(this.N, this.N)
|
||||
return this.n2
|
||||
return new(big.Int).Mul(this.N, this.N)
|
||||
}
|
||||
|
||||
// Encode a plain text in a cypher one. The plain text must be smaller that
|
||||
// N and bigger or equal than zero. random is usually rand.Reader from the
|
||||
// Encode a plaintext in a cypher one. The plain text must be smaller that
|
||||
// N and bigger or equal than zero. random is usually rand.Reader from the
|
||||
// package crypto/rand.
|
||||
//
|
||||
// m - plaintext to encrypt
|
||||
// E(m, r) = [(1 + N) r^N] mod N^2
|
||||
//
|
||||
// See [KL 08] construction 11.32, page 414.
|
||||
//
|
||||
// Returns an error if an error has be returned by io.Reader.
|
||||
func (pub *PublicKey) Encrypt(m *big.Int, random io.Reader) (*Cypher, error) {
|
||||
r, err := GetRandomNumberInMultiplicativeGroup(pub.N, random)
|
||||
@@ -38,13 +37,20 @@ func (pub *PublicKey) Encrypt(m *big.Int, random io.Reader) (*Cypher, error) {
|
||||
}
|
||||
nSquare := pub.GetNSquare()
|
||||
|
||||
gm := new(big.Int).Exp(pub.G, m, nSquare)
|
||||
// g is _always_ equal n+1
|
||||
// Threshold encryption is safe only for g=n+1 choice.
|
||||
// See [DJN 10], section 5.1
|
||||
g := new(big.Int).Add(pub.N, big.NewInt(1))
|
||||
gm := new(big.Int).Exp(g, m, nSquare)
|
||||
rn := new(big.Int).Exp(r, pub.N, nSquare)
|
||||
return &Cypher{new(big.Int).Mod(new(big.Int).Mul(rn, gm), nSquare)}, nil
|
||||
}
|
||||
|
||||
// Takes two cypher texts and returns a 3rd one that encode
|
||||
// the sum of the two plain texts.
|
||||
//
|
||||
// It's possible because Paillier is a homomorphic encryption scheme, where
|
||||
// E(m1) * E(m2) = E(m1 + m2)
|
||||
func (this *PublicKey) Add(cypher1, cypher2 *Cypher) *Cypher {
|
||||
m := new(big.Int).Mul(cypher1.C, cypher2.C)
|
||||
return &Cypher{new(big.Int).Mod(m, this.GetNSquare())}
|
||||
@@ -52,20 +58,21 @@ func (this *PublicKey) Add(cypher1, cypher2 *Cypher) *Cypher {
|
||||
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
Lambda, Mu *big.Int
|
||||
}
|
||||
|
||||
func (this *PrivateKey) String() string {
|
||||
ret := fmt.Sprintf("g : %x", this.G)
|
||||
ret += fmt.Sprintf("n : %x", this.N)
|
||||
ret += fmt.Sprintf("lambda: %x", this.Lambda)
|
||||
ret += fmt.Sprintf("mu : %x", this.Mu)
|
||||
return ret
|
||||
Lambda *big.Int
|
||||
}
|
||||
|
||||
// Decodes ciphertext into a plaintext message.
|
||||
//
|
||||
// c - cyphertext to decrypt
|
||||
// N, lambda - key attributes
|
||||
//
|
||||
// D(c) = [ ((c^lambda) mod N^2) - 1) / N ] lambda^-1 mod N
|
||||
//
|
||||
// See [KL 08] construction 11.32, page 414.
|
||||
func (priv *PrivateKey) Decrypt(cypher *Cypher) (msg *big.Int) {
|
||||
mu := new(big.Int).ModInverse(priv.Lambda, priv.N)
|
||||
tmp := new(big.Int).Exp(cypher.C, priv.Lambda, priv.GetNSquare())
|
||||
msg = new(big.Int).Mod(new(big.Int).Mul(L(tmp, priv.N), priv.Mu), priv.N)
|
||||
msg = new(big.Int).Mod(new(big.Int).Mul(L(tmp, priv.N), mu), priv.N)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -82,35 +89,38 @@ func L(u, n *big.Int) *big.Int {
|
||||
return new(big.Int).Div(t, n)
|
||||
}
|
||||
|
||||
func LCM(x, y *big.Int) *big.Int {
|
||||
return new(big.Int).Mul(new(big.Int).Div(x, new(big.Int).GCD(nil, nil, x, y)), y)
|
||||
}
|
||||
|
||||
func minusOne(x *big.Int) *big.Int {
|
||||
return new(big.Int).Add(x, big.NewInt(-1))
|
||||
}
|
||||
|
||||
func computeMu(g, lambda, n *big.Int) *big.Int {
|
||||
n2 := new(big.Int).Mul(n, n)
|
||||
u := new(big.Int).Exp(g, lambda, n2)
|
||||
return new(big.Int).ModInverse(L(u, n), n)
|
||||
}
|
||||
|
||||
func computeLamda(p, q *big.Int) *big.Int {
|
||||
return LCM(minusOne(p), minusOne(q))
|
||||
func computePhi(p, q *big.Int) *big.Int {
|
||||
return new(big.Int).Mul(minusOne(p), minusOne(q))
|
||||
}
|
||||
|
||||
// CreatePrivateKey generates a Paillier private key accepting two large prime
|
||||
// numbers of equal length or other such that gcd(pq, (p-1)(q-1)) = 1.
|
||||
//
|
||||
// Algorithm is based on approach described in [KL 08], construction 11.32,
|
||||
// page 414 which is compatible with one described in [DJN 10], section 3.2
|
||||
// except that instead of generating Lambda private key component from LCM
|
||||
// of p and q we use Euler's totient function as suggested in [KL 08].
|
||||
//
|
||||
// [KL 08]: Jonathan Katz, Yehuda Lindell, (2008)
|
||||
// Introduction to Modern Cryptography: Principles and Protocols,
|
||||
// Chapman & Hall/CRC
|
||||
//
|
||||
// [DJN 10]: Ivan Damgard, Mads Jurik, Jesper Buus Nielsen, (2010)
|
||||
// A Generalization of Paillier’s Public-Key System
|
||||
// with Applications to Electronic Voting
|
||||
// Aarhus University, Dept. of Computer Science, BRICS
|
||||
func CreatePrivateKey(p, q *big.Int) *PrivateKey {
|
||||
n := new(big.Int).Mul(p, q)
|
||||
lambda := new(big.Int).Mul(minusOne(p), minusOne(q))
|
||||
g := new(big.Int).Add(n, big.NewInt(1))
|
||||
mu := new(big.Int).ModInverse(lambda, n)
|
||||
lambda := computePhi(p, q)
|
||||
|
||||
return &PrivateKey{
|
||||
PublicKey: PublicKey{
|
||||
N: n,
|
||||
G: g,
|
||||
},
|
||||
Lambda: lambda,
|
||||
Mu: mu,
|
||||
}
|
||||
}
|
||||
+30
-24
@@ -7,35 +7,42 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLCM(t *testing.T) {
|
||||
a := big.NewInt(2 * 3 * 3 * 3 * 5 * 5)
|
||||
b := big.NewInt(3 * 3 * 5 * 5 * 57 * 11)
|
||||
exp := big.NewInt(3 * 3 * 5 * 5)
|
||||
if reflect.DeepEqual(exp, LCM(a, b)) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestL(t *testing.T) {
|
||||
func TestComputeL(t *testing.T) {
|
||||
u := big.NewInt(21)
|
||||
n := big.NewInt(3)
|
||||
exp := big.NewInt(6)
|
||||
if !reflect.DeepEqual(exp, L(u, n)) {
|
||||
t.Error("L function is not good")
|
||||
|
||||
expected := big.NewInt(6)
|
||||
actual := L(u, n)
|
||||
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("Unexpected L function result [%v]", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComputeMu(t *testing.T) {
|
||||
p := big.NewInt(13)
|
||||
q := big.NewInt(11)
|
||||
func TestComputePhi(t *testing.T) {
|
||||
a := big.NewInt(5)
|
||||
b := big.NewInt(7)
|
||||
|
||||
lambda := computeLamda(p, q)
|
||||
g := big.NewInt(5000)
|
||||
n := new(big.Int).Mul(p, q)
|
||||
expected := big.NewInt(24)
|
||||
actual := computePhi(a, b)
|
||||
|
||||
exp := big.NewInt(3)
|
||||
if !reflect.DeepEqual(computeMu(g, lambda, n), exp) {
|
||||
t.Error("lambda is not well computed")
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("Unexpected phi value [%v]", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatePrivateKey(t *testing.T) {
|
||||
p := big.NewInt(463)
|
||||
q := big.NewInt(631)
|
||||
|
||||
privateKey := CreatePrivateKey(p, q)
|
||||
|
||||
if !reflect.DeepEqual(privateKey.N, big.NewInt(292153)) {
|
||||
t.Errorf("Unexpected N PublicKey value [%v]", privateKey.N)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(privateKey.Lambda, big.NewInt(291060)) {
|
||||
t.Errorf("Unexpected Lambda Public key value [%v]", privateKey.Lambda)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,10 +59,9 @@ func TestEncryptDecryptSmall(t *testing.T) {
|
||||
}
|
||||
returnedValue := privateKey.Decrypt(cypher)
|
||||
if !reflect.DeepEqual(inicialValue, returnedValue) {
|
||||
t.Error("wrond decryption ", returnedValue, " is not ", inicialValue)
|
||||
t.Error("wrong decryption ", returnedValue, " is not ", inicialValue)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAddCypher(t *testing.T) {
|
||||
|
||||
+199
-115
@@ -8,27 +8,48 @@ import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type ThresholdKey struct {
|
||||
// Public key for a threshold Paillier scheme.
|
||||
//
|
||||
// `V` is a generator in the cyclic group of squares Z_n^2 and is used to
|
||||
// execute a zero-knowledge proof of a received share decryption.
|
||||
//
|
||||
// `Vi` is an array of verification keys for each decryption server `i` used to
|
||||
// execute a zero-knowledge proof of a received share decryption.
|
||||
//
|
||||
// Key generation, encryption, share decryption and combining for the threshold
|
||||
// Paillier scheme has been described in [DJN 10], section 5.1.
|
||||
//
|
||||
// [DJN 10]: Ivan Damgard, Mads Jurik, Jesper Buus Nielsen, (2010)
|
||||
// A Generalization of Paillier’s Public-Key System
|
||||
// with Applications to Electronic Voting
|
||||
// Aarhus University, Dept. of Computer Science, BRICS
|
||||
type ThresholdPublicKey struct {
|
||||
PublicKey
|
||||
TotalNumberOfDecryptionServers int
|
||||
Threshold int
|
||||
V *big.Int
|
||||
Vi []*big.Int
|
||||
V *big.Int // needed for ZKP
|
||||
Vi []*big.Int // needed for ZKP
|
||||
}
|
||||
|
||||
// returns the value of (4*delta**2)** -1 mod n
|
||||
func (this *ThresholdKey) CombineSharesConstant() *big.Int {
|
||||
tmp := new(big.Int).Mul(FOUR, new(big.Int).Mul(this.Delta(), this.Delta()))
|
||||
return (&big.Int{}).ModInverse(tmp, this.N)
|
||||
// Returns the value of [(4*delta^2)]^-1 mod n.
|
||||
// It is a constant value for the given `ThresholdKey` and is used in the last
|
||||
// step of share combining.
|
||||
func (tk *ThresholdPublicKey) combineSharesConstant() *big.Int {
|
||||
tmp := new(big.Int).Mul(FOUR, new(big.Int).Mul(tk.delta(), tk.delta()))
|
||||
return (&big.Int{}).ModInverse(tmp, tk.N)
|
||||
}
|
||||
|
||||
// returns the factorial of the number of TotalNumberOfDecryptionServers
|
||||
func (this *ThresholdKey) Delta() *big.Int {
|
||||
return Factorial(this.TotalNumberOfDecryptionServers)
|
||||
// Returns the factorial of the number of `TotalNumberOfDecryptionServers`.
|
||||
// It is a contant value for the given `ThresholdKey`.
|
||||
func (tk *ThresholdPublicKey) delta() *big.Int {
|
||||
return Factorial(tk.TotalNumberOfDecryptionServers)
|
||||
}
|
||||
|
||||
func (this *ThresholdKey) MakeVerificationBeforeCombiningPartialDecryptions(shares []*PartialDecryption) error {
|
||||
if len(shares) < this.Threshold {
|
||||
// Checks if the number of received, unique shares is less than the
|
||||
// required threshold.
|
||||
// This method does not execute ZKP on received shares.
|
||||
func (tk *ThresholdPublicKey) verifyPartialDecryptions(shares []*PartialDecryption) error {
|
||||
if len(shares) < tk.Threshold {
|
||||
return errors.New("Threshold not meet")
|
||||
}
|
||||
tmp := make(map[int]bool)
|
||||
@@ -41,89 +62,106 @@ func (this *ThresholdKey) MakeVerificationBeforeCombiningPartialDecryptions(shar
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *ThresholdKey) UpdateLambda(share1, share2 *PartialDecryption, lambda *big.Int) *big.Int {
|
||||
func (tk *ThresholdPublicKey) updateLambda(share1, share2 *PartialDecryption, lambda *big.Int) *big.Int {
|
||||
num := new(big.Int).Mul(lambda, big.NewInt(int64(-share2.Id)))
|
||||
denom := big.NewInt(int64(share1.Id - share2.Id))
|
||||
return new(big.Int).Div(num, denom)
|
||||
}
|
||||
|
||||
func (this *ThresholdKey) ComputeLambda(share *PartialDecryption, shares []*PartialDecryption) *big.Int {
|
||||
lambda := this.Delta()
|
||||
// Evaluates lambda parameter for each decrypted share. See second figure in the
|
||||
// "Share combining" paragraph in [DJK 10], section 5.2.
|
||||
func (tk *ThresholdPublicKey) computeLambda(share *PartialDecryption, shares []*PartialDecryption) *big.Int {
|
||||
lambda := tk.delta()
|
||||
for _, share2 := range shares {
|
||||
if share2.Id != share.Id {
|
||||
lambda = this.UpdateLambda(share, share2, lambda)
|
||||
lambda = tk.updateLambda(share, share2, lambda)
|
||||
}
|
||||
}
|
||||
return lambda
|
||||
}
|
||||
|
||||
func (this *ThresholdKey) updateCprime(cprime, lambda *big.Int, share *PartialDecryption) *big.Int {
|
||||
// Used to evaluate c' parameter which combines individual share decryptions.
|
||||
//
|
||||
// Modulo division is performed on the computed exponent to avoid creating
|
||||
// large numbers. This is possible because of the following property of modulo:
|
||||
// A^B mod C = (A mod C)^B mod C
|
||||
//
|
||||
// Modulo division is performed on the computed coefficient because of the
|
||||
// following property of modulo:
|
||||
// (AB) mod C = (A mod C * B mod C) mod C
|
||||
// Note, we need to combine coefficients into single c'.
|
||||
func (tk *ThresholdPublicKey) updateCprime(cprime, lambda *big.Int, share *PartialDecryption) *big.Int {
|
||||
twoLambda := new(big.Int).Mul(TWO, lambda)
|
||||
ret := this.exp(share.Decryption, twoLambda, this.GetNSquare())
|
||||
ret := tk.exp(share.Decryption, twoLambda, tk.GetNSquare())
|
||||
ret = new(big.Int).Mul(cprime, ret)
|
||||
return new(big.Int).Mod(ret, this.GetNSquare())
|
||||
return new(big.Int).Mod(ret, tk.GetNSquare())
|
||||
}
|
||||
|
||||
func (this *ThresholdKey) divide(a, b *big.Int) *big.Int {
|
||||
if a.Cmp(ZERO) == -1 {
|
||||
if b.Cmp(ZERO) == -1 {
|
||||
return new(big.Int).Div(new(big.Int).Neg(a), new(big.Int).Neg(b))
|
||||
}
|
||||
return new(big.Int).Neg(new(big.Int).Div(new(big.Int).Neg(a), b))
|
||||
}
|
||||
return new(big.Int).Div(a, b)
|
||||
}
|
||||
|
||||
func (this *ThresholdKey) exp(a, b, c *big.Int) *big.Int {
|
||||
if b.Cmp(ZERO) == -1 {
|
||||
// We use `exp` from `updateCprime` to raise decryption share to the power of lambda
|
||||
// parameter. Since lambda can be a negative number and we do discrete math here,
|
||||
// we need to apply multiplicative inverse modulo in this case.
|
||||
//
|
||||
// For instance, for b = -18:
|
||||
// b^{−18} = (b^−1)^18, where b^{−1} is the multiplicative inverse modulo c.
|
||||
func (tk *ThresholdPublicKey) exp(a, b, c *big.Int) *big.Int {
|
||||
if b.Cmp(ZERO) == -1 { // b < 0 ?
|
||||
ret := new(big.Int).Exp(a, new(big.Int).Neg(b), c)
|
||||
return new(big.Int).ModInverse(ret, c)
|
||||
}
|
||||
return new(big.Int).Exp(a, b, c)
|
||||
|
||||
}
|
||||
|
||||
func (this *ThresholdKey) computeDecryption(cprime *big.Int) *big.Int {
|
||||
l := L(cprime, this.N)
|
||||
return new(big.Int).Mod(new(big.Int).Mul(this.CombineSharesConstant(), l), this.N)
|
||||
// Executes the last step of message decryption. Takes `cprime` value computed
|
||||
// from valid shares provided by decryption servers and multiplies this value
|
||||
// by `combineSharesContant` which is specific to the given public `ThresholdKey`.
|
||||
func (tk *ThresholdPublicKey) computeDecryption(cprime *big.Int) *big.Int {
|
||||
l := L(cprime, tk.N)
|
||||
return new(big.Int).Mod(new(big.Int).Mul(tk.combineSharesConstant(), l), tk.N)
|
||||
}
|
||||
|
||||
func (this *ThresholdKey) CombinePartialDecryptions(shares []*PartialDecryption) (*big.Int, error) {
|
||||
if err := this.MakeVerificationBeforeCombiningPartialDecryptions(shares); err != nil {
|
||||
// Combines partial decryptions provided by decryption servers and returns
|
||||
// decrypted message.
|
||||
// This function does not verify zero knowledge proofs. Returned message can be
|
||||
// incorrectly decrypted if an adversary corrupted partial decryption.
|
||||
func (tk *ThresholdPublicKey) CombinePartialDecryptions(shares []*PartialDecryption) (*big.Int, error) {
|
||||
if err := tk.verifyPartialDecryptions(shares); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cprime := ONE
|
||||
for _, share := range shares {
|
||||
lambda := this.ComputeLambda(share, shares)
|
||||
cprime = this.updateCprime(cprime, lambda, share)
|
||||
lambda := tk.computeLambda(share, shares)
|
||||
cprime = tk.updateCprime(cprime, lambda, share)
|
||||
}
|
||||
|
||||
return this.computeDecryption(cprime), nil
|
||||
return tk.computeDecryption(cprime), nil
|
||||
}
|
||||
|
||||
func (this *ThresholdKey) CombinePartialDecryptionsZKP(shares []*PartialDecryptionZKP) (*big.Int, error) {
|
||||
// Combines partial decryptions provided by decryption servers and returns
|
||||
// full decrypted message.
|
||||
// Function verifies zero knowledge proofs and filters out all shares that failed
|
||||
// verification.
|
||||
func (tk *ThresholdPublicKey) CombinePartialDecryptionsZKP(shares []*PartialDecryptionZKP) (*big.Int, error) {
|
||||
ret := make([]*PartialDecryption, 0)
|
||||
for _, share := range shares {
|
||||
if share.Verify() {
|
||||
ret = append(ret, &share.PartialDecryption)
|
||||
}
|
||||
}
|
||||
return this.CombinePartialDecryptions(ret)
|
||||
return tk.CombinePartialDecryptions(ret)
|
||||
}
|
||||
|
||||
// Verify if the decryption of `encryptedMessage` has well been done.
|
||||
// It verifies all the zero-knoledge proofs, the value of the decrypted
|
||||
// and decrypted message.
|
||||
// The method returns `nil` if everything is good. Otherwise it returns an
|
||||
// explicative message
|
||||
func (this *ThresholdKey) VerifyDecryption(encryptedMessage, decryptedMessage *big.Int, shares []*PartialDecryptionZKP) error {
|
||||
// Verifies if the decryption of `encryptedMessage` has been done properly.
|
||||
// It verifies all the zero-knoledge proofs, the value of the encrypted
|
||||
// and decrypted message. The method returns `nil` if everything is fine.
|
||||
// Otherwise, it returns an explicative message.
|
||||
func (tk *ThresholdPublicKey) VerifyDecryption(encryptedMessage, decryptedMessage *big.Int, shares []*PartialDecryptionZKP) error {
|
||||
for _, share := range shares {
|
||||
if share.C.Cmp(encryptedMessage) != 0 {
|
||||
return errors.New("The encrypted message is not the same than the one in the shares")
|
||||
}
|
||||
}
|
||||
res, err := this.CombinePartialDecryptionsZKP(shares)
|
||||
res, err := tk.CombinePartialDecryptionsZKP(shares)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -133,99 +171,100 @@ func (this *ThresholdKey) VerifyDecryption(encryptedMessage, decryptedMessage *b
|
||||
return nil
|
||||
}
|
||||
|
||||
// Private key for a threshold Paillier scheme. Holds private information
|
||||
// for the given decryption server.
|
||||
// `Id` is the unique identifier of a decryption server and `Share` is a secret
|
||||
// share generated from hiding polynomial and is used for a partial share decryption.
|
||||
type ThresholdPrivateKey struct {
|
||||
ThresholdKey
|
||||
ThresholdPublicKey
|
||||
Id int
|
||||
Share *big.Int
|
||||
}
|
||||
|
||||
// Decrypt the cypher text and returns the partial decryption
|
||||
func (this *ThresholdPrivateKey) Decrypt(c *big.Int) *PartialDecryption {
|
||||
// Decrypts the cypher text and returns the partial decryption
|
||||
func (tpk *ThresholdPrivateKey) Decrypt(c *big.Int) *PartialDecryption {
|
||||
ret := new(PartialDecryption)
|
||||
ret.Id = this.Id
|
||||
exp := new(big.Int).Mul(this.Share, new(big.Int).Mul(TWO, this.Delta()))
|
||||
ret.Decryption = new(big.Int).Exp(c, exp, this.GetNSquare())
|
||||
ret.Id = tpk.Id
|
||||
exp := new(big.Int).Mul(tpk.Share, new(big.Int).Mul(TWO, tpk.delta()))
|
||||
ret.Decryption = new(big.Int).Exp(c, exp, tpk.GetNSquare())
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (this *ThresholdPrivateKey) copyVi() []*big.Int {
|
||||
ret := make([]*big.Int, len(this.Vi))
|
||||
for i, vi := range this.Vi {
|
||||
func (tpk *ThresholdPrivateKey) copyVi() []*big.Int {
|
||||
ret := make([]*big.Int, len(tpk.Vi))
|
||||
for i, vi := range tpk.Vi {
|
||||
ret[i] = new(big.Int).Add(vi, big.NewInt(0))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (this *ThresholdPrivateKey) GetThresholdKey() *ThresholdKey {
|
||||
ret := new(ThresholdKey)
|
||||
ret.Threshold = this.Threshold
|
||||
ret.TotalNumberOfDecryptionServers = this.TotalNumberOfDecryptionServers
|
||||
ret.V = new(big.Int).Add(this.V, big.NewInt(0))
|
||||
ret.Vi = this.copyVi()
|
||||
ret.N = new(big.Int).Add(this.N, big.NewInt(0))
|
||||
ret.G = new(big.Int).Add(this.N, big.NewInt(1))
|
||||
func (tpk *ThresholdPrivateKey) getThresholdKey() *ThresholdPublicKey {
|
||||
ret := new(ThresholdPublicKey)
|
||||
ret.Threshold = tpk.Threshold
|
||||
ret.TotalNumberOfDecryptionServers = tpk.TotalNumberOfDecryptionServers
|
||||
ret.V = new(big.Int).Add(tpk.V, big.NewInt(0))
|
||||
ret.Vi = tpk.copyVi()
|
||||
ret.N = new(big.Int).Add(tpk.N, big.NewInt(0))
|
||||
return ret
|
||||
}
|
||||
|
||||
func (this *ThresholdPrivateKey) ComputeZ(r, e *big.Int) *big.Int {
|
||||
tmp := new(big.Int).Mul(e, this.Delta())
|
||||
tmp = new(big.Int).Mul(tmp, this.Share)
|
||||
func (tpk *ThresholdPrivateKey) computeZ(r, e *big.Int) *big.Int {
|
||||
tmp := new(big.Int).Mul(e, tpk.delta())
|
||||
tmp = new(big.Int).Mul(tmp, tpk.Share)
|
||||
return new(big.Int).Add(r, tmp)
|
||||
|
||||
}
|
||||
|
||||
func (this *ThresholdPrivateKey) computeHash(a, b, c4, ci2 *big.Int) *big.Int {
|
||||
func (tpk *ThresholdPrivateKey) computeHash(a, b, c4, ci2 *big.Int) *big.Int {
|
||||
hash := sha256.New()
|
||||
hash.Write(a.Bytes())
|
||||
hash.Write(b.Bytes())
|
||||
hash.Write(c4.Bytes())
|
||||
hash.Write(ci2.Bytes())
|
||||
return new(big.Int).SetBytes(hash.Sum([]byte{}))
|
||||
|
||||
}
|
||||
|
||||
func (this *ThresholdPrivateKey) DecryptAndProduceZNP(c *big.Int, random io.Reader) (*PartialDecryptionZKP, error) {
|
||||
func (tpk *ThresholdPrivateKey) DecryptAndProduceZNP(c *big.Int, random io.Reader) (*PartialDecryptionZKP, error) {
|
||||
pd := new(PartialDecryptionZKP)
|
||||
pd.Key = this.GetThresholdKey()
|
||||
pd.Key = tpk.getThresholdKey()
|
||||
pd.C = c
|
||||
pd.Id = this.Id
|
||||
pd.Decryption = this.Decrypt(c).Decryption
|
||||
pd.Id = tpk.Id
|
||||
pd.Decryption = tpk.Decrypt(c).Decryption
|
||||
|
||||
// choose random number
|
||||
r, err := rand.Int(random, this.GetNSquare())
|
||||
r, err := rand.Int(random, tpk.GetNSquare())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// compute a
|
||||
c4 := new(big.Int).Exp(c, FOUR, nil)
|
||||
a := new(big.Int).Exp(c4, r, this.GetNSquare())
|
||||
a := new(big.Int).Exp(c4, r, tpk.GetNSquare())
|
||||
|
||||
// compute b
|
||||
b := new(big.Int).Exp(this.V, r, this.GetNSquare())
|
||||
b := new(big.Int).Exp(tpk.V, r, tpk.GetNSquare())
|
||||
|
||||
// compute hash
|
||||
ci2 := new(big.Int).Exp(pd.Decryption, big.NewInt(2), nil)
|
||||
|
||||
pd.E = this.computeHash(a, b, c4, ci2)
|
||||
pd.E = tpk.computeHash(a, b, c4, ci2)
|
||||
|
||||
pd.Z = this.ComputeZ(r, pd.E)
|
||||
pd.Z = tpk.computeZ(r, pd.E)
|
||||
|
||||
return pd, nil
|
||||
}
|
||||
|
||||
// Verify if the partial decryption key is well formed. If well formed,
|
||||
// the method return nil else an explicative error is returned.
|
||||
func (this *ThresholdPrivateKey) Validate(random io.Reader) error {
|
||||
m, err := rand.Int(random, this.N)
|
||||
// Verifies if the partial decryption key is well formed. If well formed,
|
||||
// the method return nil else an explicative error is returned.
|
||||
func (tpk *ThresholdPrivateKey) Validate(random io.Reader) error {
|
||||
m, err := rand.Int(random, tpk.N)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c, err := this.Encrypt(m, random)
|
||||
c, err := tpk.Encrypt(m, random)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
proof, err := this.DecryptAndProduceZNP(c.C, random)
|
||||
proof, err := tpk.DecryptAndProduceZNP(c.C, random)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -240,50 +279,95 @@ type PartialDecryption struct {
|
||||
Decryption *big.Int
|
||||
}
|
||||
|
||||
// A non-interactive ZKP based on the Fiat–Shamir heuristic. This algorithm
|
||||
// proves that the decryption server indeed raised secret to his secret exponent
|
||||
// (`ThresholdPrivateKey.Share`) by comparison with the public verification key
|
||||
// (`ThresholdKey.Vi`). Recall that v_i = v^(delta s_i).
|
||||
//
|
||||
// The Fiat-Shamir is a non-interactive proof of knowledge heuristic.
|
||||
// The general algorithm is as follows:
|
||||
//
|
||||
// - Alice wants to prove that she knows x: the discrete logarithm of y = g^x
|
||||
// to the base g
|
||||
// - Alice picks a random r from Z_q and computes t = g^r
|
||||
// - Alice computes E = H(t, g, y), where H is a cryptographic hash function
|
||||
// - Alice computes Z = Ex + r.
|
||||
// The resulting proof is the pair (t, Z).
|
||||
// - Anyone can check whether t = g^Z y^E (mod q)
|
||||
//
|
||||
// In our case:
|
||||
//
|
||||
// Decryption server i wants to prove that he indeed raised the cyphertext to
|
||||
// his secret exponent s_i during partial decryption.
|
||||
// This is essentialy a protocol for the equality of discrete logs,
|
||||
// log_{c^4}(c_i^2) = log_v(v_i).
|
||||
//
|
||||
// ZKP construction
|
||||
//
|
||||
// - Pick random r mod n
|
||||
// - Compute E as:
|
||||
// E = HASH(a, b, c^4, c_i^2), where
|
||||
// a = (c^4)^r mod n^2
|
||||
// b = V^r mod n^2
|
||||
// c is a cyphertext,
|
||||
// V is a generator from ThresholdKey.V
|
||||
// c_i is a partial decryption for this server
|
||||
// - Compute Z as:
|
||||
// delta * E * s_i + r, where
|
||||
// delta is the factorial of the number of decryption servers
|
||||
// s_i is a secret share for this server
|
||||
//
|
||||
// ZKP verification
|
||||
//
|
||||
// - Compute the original a from
|
||||
// a = a1 * a2 mod n^2
|
||||
// a1 = (c^4)^Z
|
||||
// a2 = [ (c_i^2)^E ]^-1 mod n^2
|
||||
// - Compute the original b from
|
||||
// b = b1 * b2 mod n^2
|
||||
// b1 = V^Z
|
||||
// b2 = [ v_i^E ] -1 mod n^2
|
||||
// - Rehash H(a, b, c^4, c_i^2)
|
||||
// - Compare ZKP hash with the one just computed
|
||||
type PartialDecryptionZKP struct {
|
||||
PartialDecryption
|
||||
Key *ThresholdKey // the public key used to encrypt
|
||||
E *big.Int // the challenge
|
||||
Z *big.Int // the value needed to check to verify the decryption
|
||||
C *big.Int // the input cypher text
|
||||
|
||||
Key *ThresholdPublicKey // the public key used to encrypt
|
||||
E *big.Int // the challenge
|
||||
Z *big.Int // the value needed to check to verify the decryption
|
||||
C *big.Int // the input cypher text
|
||||
}
|
||||
|
||||
func (this *PartialDecryptionZKP) verifyPart1() *big.Int {
|
||||
c4 := new(big.Int).Exp(this.C, FOUR, nil)
|
||||
decryption2 := new(big.Int).Exp(this.Decryption, TWO, nil)
|
||||
func (pd *PartialDecryptionZKP) verifyPart1() *big.Int {
|
||||
c4 := new(big.Int).Exp(pd.C, FOUR, nil) // c^4
|
||||
decryption2 := new(big.Int).Exp(pd.Decryption, TWO, nil) // c_i^2
|
||||
|
||||
a1 := new(big.Int).Exp(c4, this.Z, this.Key.GetNSquare())
|
||||
a2 := new(big.Int).Exp(decryption2, this.E, this.Key.GetNSquare())
|
||||
a2 = new(big.Int).ModInverse(a2, this.Key.GetNSquare())
|
||||
a := new(big.Int).Mod(new(big.Int).Mul(a1, a2), this.Key.GetNSquare())
|
||||
a1 := new(big.Int).Exp(c4, pd.Z, pd.Key.GetNSquare()) // (c^4)^Z
|
||||
a2 := new(big.Int).Exp(decryption2, pd.E, pd.Key.GetNSquare()) // (c_i^2)^E
|
||||
a2 = new(big.Int).ModInverse(a2, pd.Key.GetNSquare())
|
||||
a := new(big.Int).Mod(new(big.Int).Mul(a1, a2), pd.Key.GetNSquare())
|
||||
return a
|
||||
}
|
||||
|
||||
func (this *PartialDecryptionZKP) neg(n *big.Int) *big.Int {
|
||||
return new(big.Int).Neg(n)
|
||||
}
|
||||
|
||||
func (this *PartialDecryptionZKP) verifyPart2() *big.Int {
|
||||
vi := this.Key.Vi[this.Id-1]
|
||||
b1 := new(big.Int).Exp(this.Key.V, this.Z, this.Key.GetNSquare())
|
||||
b2 := new(big.Int).Exp(vi, this.E, this.Key.GetNSquare())
|
||||
b2 = new(big.Int).ModInverse(b2, this.Key.GetNSquare())
|
||||
b := new(big.Int).Mod(new(big.Int).Mul(b1, b2), this.Key.GetNSquare())
|
||||
func (pd *PartialDecryptionZKP) verifyPart2() *big.Int {
|
||||
vi := pd.Key.Vi[pd.Id-1] // servers are indexed from 1
|
||||
b1 := new(big.Int).Exp(pd.Key.V, pd.Z, pd.Key.GetNSquare()) // V^Z
|
||||
b2 := new(big.Int).Exp(vi, pd.E, pd.Key.GetNSquare()) // (v_i)^E
|
||||
b2 = new(big.Int).ModInverse(b2, pd.Key.GetNSquare())
|
||||
b := new(big.Int).Mod(new(big.Int).Mul(b1, b2), pd.Key.GetNSquare())
|
||||
return b
|
||||
}
|
||||
|
||||
func (this *PartialDecryptionZKP) Verify() bool {
|
||||
a := this.verifyPart1()
|
||||
b := this.verifyPart2()
|
||||
func (pd *PartialDecryptionZKP) Verify() bool {
|
||||
a := pd.verifyPart1()
|
||||
b := pd.verifyPart2()
|
||||
hash := sha256.New()
|
||||
hash.Write(a.Bytes())
|
||||
hash.Write(b.Bytes())
|
||||
c4 := new(big.Int).Exp(this.C, FOUR, nil)
|
||||
c4 := new(big.Int).Exp(pd.C, FOUR, nil)
|
||||
hash.Write(c4.Bytes())
|
||||
ci2 := new(big.Int).Exp(this.Decryption, TWO, nil)
|
||||
ci2 := new(big.Int).Exp(pd.Decryption, TWO, nil)
|
||||
hash.Write(ci2.Bytes())
|
||||
|
||||
expectedE := new(big.Int).SetBytes(hash.Sum([]byte{}))
|
||||
return this.E.Cmp(expectedE) == 0
|
||||
return pd.E.Cmp(expectedE) == 0
|
||||
}
|
||||
+127
-76
@@ -6,21 +6,32 @@ import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// Generates a threshold Paillier key with an algorithm based on [DJN 10],
|
||||
// section 5.1, "Key generation".
|
||||
//
|
||||
// Bear in mind that the algorithm assumes an existence of a trusted dealer
|
||||
// to generate and distribute the keys.
|
||||
//
|
||||
//
|
||||
// [DJN 10]: Ivan Damgard, Mads Jurik, Jesper Buus Nielsen, (2010)
|
||||
// A Generalization of Paillier’s Public-Key System
|
||||
// with Applications to Electronic Voting
|
||||
// Aarhus University, Dept. of Computer Science, BRICS
|
||||
type ThresholdKeyGenerator struct {
|
||||
nbits int
|
||||
TotalNumberOfDecryptionServers int
|
||||
Threshold int
|
||||
Random io.Reader
|
||||
|
||||
//Both p1 and q1 are primes of length nbits - 1
|
||||
// Both p1 and q1 are primes of length nbits - 1
|
||||
p1 *big.Int
|
||||
q1 *big.Int
|
||||
|
||||
p *big.Int //p is prime and p=2*p1+1
|
||||
q *big.Int //q is prime 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
|
||||
m *big.Int //m = p1*q1
|
||||
nSquare *big.Int //nSquare = n*n
|
||||
m *big.Int // m = p1*q1
|
||||
nSquare *big.Int // nSquare = n*n
|
||||
nm *big.Int // nm = n*m
|
||||
|
||||
// As specified in the paper, d must satify d=1 mod n and d=0 mod m
|
||||
@@ -29,13 +40,14 @@ type ThresholdKeyGenerator struct {
|
||||
// A generator of QR in Z_{n^2}
|
||||
v *big.Int
|
||||
|
||||
// the polynomial coefficients to hide a secret. See Shamir.
|
||||
// The polynomial coefficients to hide a secret. See Shamir.
|
||||
polynomialCoefficients []*big.Int
|
||||
}
|
||||
|
||||
// preferable way to counstruct the ThresholdKeyGenerator. No verification
|
||||
// is done on the input values. You need to bu sure that nbits is big enough
|
||||
// and that Threshold > TotalNumberOfDecryptionServers / 2
|
||||
// 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
|
||||
@@ -45,84 +57,112 @@ func GetThresholdKeyGenerator(nbits, TotalNumberOfDecryptionServers, Threshold i
|
||||
return ret
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) GenerateSafePrimes() (*big.Int, *big.Int, error) {
|
||||
return GenerateSafePrimes(this.nbits, this.Random)
|
||||
func (tkg *ThresholdKeyGenerator) generateSafePrimes() (*big.Int, *big.Int, error) {
|
||||
return GenerateSafePrimes(tkg.nbits, tkg.Random)
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) InitPandP1() error {
|
||||
func (tkg *ThresholdKeyGenerator) initPandP1() error {
|
||||
var err error
|
||||
this.p, this.p1, err = this.GenerateSafePrimes()
|
||||
tkg.p, tkg.p1, err = tkg.generateSafePrimes()
|
||||
return err
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) InitQandQ1() error {
|
||||
func (tkg *ThresholdKeyGenerator) initQandQ1() error {
|
||||
var err error
|
||||
this.q, this.q1, err = this.GenerateSafePrimes()
|
||||
tkg.q, tkg.q1, err = tkg.generateSafePrimes()
|
||||
return err
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) InitShortcuts() {
|
||||
this.n = new(big.Int).Mul(this.p, this.q)
|
||||
this.m = new(big.Int).Mul(this.p1, this.q1)
|
||||
this.nSquare = new(big.Int).Mul(this.n, this.n)
|
||||
this.nm = new(big.Int).Mul(this.n, this.m)
|
||||
|
||||
func (tkg *ThresholdKeyGenerator) initShortcuts() {
|
||||
tkg.n = new(big.Int).Mul(tkg.p, tkg.q)
|
||||
tkg.m = new(big.Int).Mul(tkg.p1, tkg.q1)
|
||||
tkg.nSquare = new(big.Int).Mul(tkg.n, tkg.n)
|
||||
tkg.nm = new(big.Int).Mul(tkg.n, tkg.m)
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) ArePsAndQsGood() bool {
|
||||
if this.p.Cmp(this.q) == 0 {
|
||||
func (tkg *ThresholdKeyGenerator) arePsAndQsGood() bool {
|
||||
if tkg.p.Cmp(tkg.q) == 0 {
|
||||
return false
|
||||
}
|
||||
if this.p.Cmp(this.q1) == 0 {
|
||||
if tkg.p.Cmp(tkg.q1) == 0 {
|
||||
return false
|
||||
}
|
||||
if this.p1.Cmp(this.q) == 0 {
|
||||
if tkg.p1.Cmp(tkg.q) == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) InitPsAndQs() error {
|
||||
if err := this.InitPandP1(); err != nil {
|
||||
func (tkg *ThresholdKeyGenerator) initPsAndQs() error {
|
||||
if err := tkg.initPandP1(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := this.InitQandQ1(); err != nil {
|
||||
if err := tkg.initQandQ1(); err != nil {
|
||||
return err
|
||||
}
|
||||
if !this.ArePsAndQsGood() {
|
||||
return this.InitPsAndQs()
|
||||
if !tkg.arePsAndQsGood() {
|
||||
return tkg.initPsAndQs()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) ComputeV() error {
|
||||
// v generates a cyclic group of squares in Zn^2.
|
||||
func (tkg *ThresholdKeyGenerator) computeV() error {
|
||||
var err error
|
||||
this.v, err = GetRandomGeneratorOfTheQuadraticResidue(this.nSquare, this.Random)
|
||||
tkg.v, err = GetRandomGeneratorOfTheQuadraticResidue(tkg.nSquare, tkg.Random)
|
||||
return err
|
||||
}
|
||||
|
||||
// Choose d such that d=0 mod m and d=1 mod n, using Chinese remainder thm
|
||||
// we can find d using Chinese remainder thm note that $d=(m. (m^-1 mod n))$
|
||||
func (this *ThresholdKeyGenerator) InitD() {
|
||||
mInverse := new(big.Int).ModInverse(this.m, this.n)
|
||||
this.d = new(big.Int).Mul(mInverse, this.m)
|
||||
// Choose d such that d=0 (mod m) and d=1 (mod n).
|
||||
//
|
||||
// From Chinese Remainder Theorem:
|
||||
// x = a1 (mod n1)
|
||||
// x = a2 (mod n2)
|
||||
//
|
||||
// N = n1*n2
|
||||
// y1 = N/n1
|
||||
// y2 = N/n2
|
||||
// z1 = y1^-1 mod n1
|
||||
// z2 = y2^-1 mod n2
|
||||
// Solution is x = a1*y1*z1 + a2*y2*z2
|
||||
//
|
||||
// In our case:
|
||||
// x = 0 (mod m)
|
||||
// x = 1 (mod n)
|
||||
//
|
||||
// Since a1 = 0, it's enough to compute a2*y2*z2 to get x.
|
||||
//
|
||||
// a2 = 1
|
||||
// y2 = mn/n = m
|
||||
// z2 = m^-1 mod n
|
||||
//
|
||||
// x = a2*y2*z2 = 1 * m * [m^-1 mod n]
|
||||
func (tkg *ThresholdKeyGenerator) initD() {
|
||||
mInverse := new(big.Int).ModInverse(tkg.m, tkg.n)
|
||||
tkg.d = new(big.Int).Mul(mInverse, tkg.m)
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) InitNumerialValues() error {
|
||||
if err := this.InitPsAndQs(); err != nil {
|
||||
func (tkg *ThresholdKeyGenerator) initNumerialValues() error {
|
||||
if err := tkg.initPsAndQs(); err != nil {
|
||||
return err
|
||||
}
|
||||
this.InitShortcuts()
|
||||
this.InitD()
|
||||
return this.ComputeV()
|
||||
tkg.initShortcuts()
|
||||
tkg.initD()
|
||||
return tkg.computeV()
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) GenerateHidingPolynomial() error {
|
||||
this.polynomialCoefficients = make([]*big.Int, this.Threshold)
|
||||
this.polynomialCoefficients[0] = this.d
|
||||
// f(X) = a_0 X^0 + a_1 X^1 + ... + a_(w-1) X^(w-1)
|
||||
//
|
||||
// where:
|
||||
// `w` - threshold
|
||||
// `a_i` - random value from {0, ... nm - 1} for 0<i<w
|
||||
// `a_0` is always equal `d`
|
||||
func (tkg *ThresholdKeyGenerator) generateHidingPolynomial() error {
|
||||
tkg.polynomialCoefficients = make([]*big.Int, tkg.Threshold)
|
||||
tkg.polynomialCoefficients[0] = tkg.d
|
||||
var err error
|
||||
for i := 1; i < this.Threshold; i++ {
|
||||
this.polynomialCoefficients[i], err = rand.Int(this.Random, this.nm)
|
||||
for i := 1; i < tkg.Threshold; i++ {
|
||||
tkg.polynomialCoefficients[i], err = rand.Int(tkg.Random, tkg.nm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -130,69 +170,80 @@ func (this *ThresholdKeyGenerator) GenerateHidingPolynomial() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) ComputeShare(index int) *big.Int {
|
||||
// The secred share of the i'th authority is `f(i) mod nm`, where `f` is
|
||||
// the polynomial we generated in `GenerateHidingPolynomial` function.
|
||||
func (tkg *ThresholdKeyGenerator) computeShare(index int) *big.Int {
|
||||
share := big.NewInt(0)
|
||||
for i := 0; i < this.Threshold; i++ {
|
||||
a := this.polynomialCoefficients[i]
|
||||
for i := 0; i < tkg.Threshold; i++ {
|
||||
a := tkg.polynomialCoefficients[i]
|
||||
// we index authorities from 1, that's why we do index+1 here
|
||||
b := new(big.Int).Exp(big.NewInt(int64(index+1)), big.NewInt(int64(i)), nil)
|
||||
tmp := new(big.Int).Mul(a, b)
|
||||
share = new(big.Int).Add(share, tmp)
|
||||
}
|
||||
return new(big.Int).Mod(share, this.nm)
|
||||
return new(big.Int).Mod(share, tkg.nm)
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) CreateShares() []*big.Int {
|
||||
shares := make([]*big.Int, this.TotalNumberOfDecryptionServers)
|
||||
for i := 0; i < this.TotalNumberOfDecryptionServers; i++ {
|
||||
shares[i] = this.ComputeShare(i)
|
||||
func (tkg *ThresholdKeyGenerator) createShares() []*big.Int {
|
||||
shares := make([]*big.Int, tkg.TotalNumberOfDecryptionServers)
|
||||
for i := 0; i < tkg.TotalNumberOfDecryptionServers; i++ {
|
||||
shares[i] = tkg.computeShare(i)
|
||||
}
|
||||
return shares
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) Delta() *big.Int {
|
||||
return Factorial(this.TotalNumberOfDecryptionServers)
|
||||
func (tkg *ThresholdKeyGenerator) delta() *big.Int {
|
||||
return Factorial(tkg.TotalNumberOfDecryptionServers)
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) CreateViArray(shares []*big.Int) (viArray []*big.Int) {
|
||||
// Generates verification keys for actions of decryption servers.
|
||||
//
|
||||
// For each decryption server `i`, we generate
|
||||
// v_i = v^(l! s_i) mod n^2
|
||||
//
|
||||
// where:
|
||||
// `l` is the number of decryption servers
|
||||
// `s_i` is a secret share for server `i`.
|
||||
// Secret shares were previously generated in the `CrateShares` function.
|
||||
func (tkg *ThresholdKeyGenerator) createViArray(shares []*big.Int) (viArray []*big.Int) {
|
||||
viArray = make([]*big.Int, len(shares))
|
||||
delta := this.Delta()
|
||||
delta := tkg.delta()
|
||||
for i, share := range shares {
|
||||
tmp := new(big.Int).Mul(share, delta)
|
||||
viArray[i] = new(big.Int).Exp(this.v, tmp, this.nSquare)
|
||||
viArray[i] = new(big.Int).Exp(tkg.v, tmp, tkg.nSquare)
|
||||
}
|
||||
return viArray
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) CreatePrivateKey(i int, share *big.Int, viArray []*big.Int) *ThresholdPrivateKey {
|
||||
func (tkg *ThresholdKeyGenerator) createPrivateKey(i int, share *big.Int, viArray []*big.Int) *ThresholdPrivateKey {
|
||||
ret := new(ThresholdPrivateKey)
|
||||
ret.N = this.n
|
||||
ret.G = new(big.Int).Add(ret.N, ONE)
|
||||
ret.V = this.v
|
||||
ret.N = tkg.n
|
||||
ret.V = tkg.v
|
||||
|
||||
ret.TotalNumberOfDecryptionServers = this.TotalNumberOfDecryptionServers
|
||||
ret.Threshold = this.Threshold
|
||||
ret.TotalNumberOfDecryptionServers = tkg.TotalNumberOfDecryptionServers
|
||||
ret.Threshold = tkg.Threshold
|
||||
ret.Share = share
|
||||
ret.Id = i + 1
|
||||
ret.Vi = viArray
|
||||
return ret
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) CreatePrivateKeys() []*ThresholdPrivateKey {
|
||||
shares := this.CreateShares()
|
||||
viArray := this.CreateViArray(shares)
|
||||
ret := make([]*ThresholdPrivateKey, this.TotalNumberOfDecryptionServers)
|
||||
for i := 0; i < this.TotalNumberOfDecryptionServers; i++ {
|
||||
ret[i] = this.CreatePrivateKey(i, shares[i], viArray)
|
||||
func (tkg *ThresholdKeyGenerator) createPrivateKeys() []*ThresholdPrivateKey {
|
||||
shares := tkg.createShares()
|
||||
viArray := tkg.createViArray(shares)
|
||||
ret := make([]*ThresholdPrivateKey, tkg.TotalNumberOfDecryptionServers)
|
||||
for i := 0; i < tkg.TotalNumberOfDecryptionServers; i++ {
|
||||
ret[i] = tkg.createPrivateKey(i, shares[i], viArray)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (this *ThresholdKeyGenerator) Generate() ([]*ThresholdPrivateKey, error) {
|
||||
if err := this.InitNumerialValues(); err != nil {
|
||||
func (tkg *ThresholdKeyGenerator) Generate() ([]*ThresholdPrivateKey, error) {
|
||||
if err := tkg.initNumerialValues(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := this.GenerateHidingPolynomial(); err != nil {
|
||||
if err := tkg.generateHidingPolynomial(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.CreatePrivateKeys(), nil
|
||||
return tkg.createPrivateKeys(), nil
|
||||
}
|
||||
@@ -15,13 +15,11 @@ func TestGenerateSafePrimesOfThresholdKeyGenerator(t *testing.T) {
|
||||
tkh := new(ThresholdKeyGenerator)
|
||||
tkh.nbits = 10
|
||||
tkh.Random = rand.Reader
|
||||
p, q, err := tkh.GenerateSafePrimes()
|
||||
p, q, err := tkh.generateSafePrimes()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
AreSafePrimes(p, q, 10, t)
|
||||
|
||||
}
|
||||
|
||||
func TestInitPandP1(t *testing.T) {
|
||||
@@ -29,9 +27,8 @@ func TestInitPandP1(t *testing.T) {
|
||||
tkh.nbits = 10
|
||||
tkh.Random = rand.Reader
|
||||
|
||||
tkh.InitPandP1()
|
||||
tkh.initPandP1()
|
||||
AreSafePrimes(tkh.p, tkh.p1, 10, t)
|
||||
|
||||
}
|
||||
|
||||
func TestInitQandQ1(t *testing.T) {
|
||||
@@ -39,7 +36,7 @@ func TestInitQandQ1(t *testing.T) {
|
||||
tkh.nbits = 10
|
||||
tkh.Random = rand.Reader
|
||||
|
||||
tkh.InitQandQ1()
|
||||
tkh.initQandQ1()
|
||||
AreSafePrimes(tkh.q, tkh.q1, 10, t)
|
||||
}
|
||||
|
||||
@@ -48,44 +45,45 @@ func TestInitPsAndQs(t *testing.T) {
|
||||
tkh.nbits = 10
|
||||
tkh.Random = rand.Reader
|
||||
|
||||
tkh.InitPsAndQs()
|
||||
AreSafePrimes(tkh.q, tkh.q1, 10, t)
|
||||
tkh.initPsAndQs()
|
||||
|
||||
AreSafePrimes(tkh.p, tkh.p1, 10, t)
|
||||
AreSafePrimes(tkh.q, tkh.q1, 10, t)
|
||||
}
|
||||
|
||||
func TestArePsAndQsGood(t *testing.T) {
|
||||
tkh := new(ThresholdKeyGenerator)
|
||||
tkh.p, tkh.p1, tkh.q, tkh.q1 = b(6), b(5), b(4), b(3)
|
||||
if !tkh.ArePsAndQsGood() {
|
||||
tkh.p, tkh.p1, tkh.q, tkh.q1 = b(887), b(443), b(839), b(419)
|
||||
if !tkh.arePsAndQsGood() {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
tkh.p, tkh.p1, tkh.q, tkh.q1 = b(6), b(5), b(6), b(3)
|
||||
if tkh.ArePsAndQsGood() {
|
||||
tkh.p, tkh.p1, tkh.q, tkh.q1 = b(887), b(443), b(887), b(443)
|
||||
if tkh.arePsAndQsGood() {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
tkh.p, tkh.p1, tkh.q, tkh.q1 = b(6), b(5), b(5), b(3)
|
||||
if tkh.ArePsAndQsGood() {
|
||||
tkh.p, tkh.p1, tkh.q, tkh.q1 = b(887), b(443), b(443), b(221)
|
||||
if tkh.arePsAndQsGood() {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitShortcuts(t *testing.T) {
|
||||
tkh := new(ThresholdKeyGenerator)
|
||||
tkh.p, tkh.p1, tkh.q, tkh.q1 = b(11), b(7), b(5), b(3)
|
||||
tkh.InitShortcuts()
|
||||
tkh.p, tkh.p1, tkh.q, tkh.q1 = b(839), b(419), b(887), b(443)
|
||||
tkh.initShortcuts()
|
||||
|
||||
if n(tkh.n) != 11*5 {
|
||||
if !reflect.DeepEqual(tkh.n, b(744193)) {
|
||||
t.Error("wrong n", tkh.n)
|
||||
}
|
||||
if n(tkh.m) != 7*3 {
|
||||
if !reflect.DeepEqual(tkh.m, b(185617)) {
|
||||
t.Error("wrong m", tkh.m)
|
||||
}
|
||||
if n(tkh.nm) != 11*5*7*3 {
|
||||
if !reflect.DeepEqual(tkh.nm, new(big.Int).Mul(b(744193), b(185617))) {
|
||||
t.Error("wrong nm", tkh.nm)
|
||||
}
|
||||
if n(tkh.nSquare) != 11*5*11*5 {
|
||||
if !reflect.DeepEqual(tkh.nSquare, new(big.Int).Mul(b(744193), b(744193))) {
|
||||
t.Error("wrong nSquare", tkh.nSquare)
|
||||
}
|
||||
}
|
||||
@@ -93,8 +91,8 @@ func TestInitShortcuts(t *testing.T) {
|
||||
func TestInitD(t *testing.T) {
|
||||
tkh := new(ThresholdKeyGenerator)
|
||||
tkh.p, tkh.p1, tkh.q, tkh.q1 = b(863), b(431), b(839), b(419)
|
||||
tkh.InitShortcuts()
|
||||
tkh.InitD()
|
||||
tkh.initShortcuts()
|
||||
tkh.initD()
|
||||
if n(tkh.d)%n(tkh.m) != 0 {
|
||||
t.Fail()
|
||||
}
|
||||
@@ -108,7 +106,7 @@ func TestInitNumerialValues(t *testing.T) {
|
||||
tkh.nbits = 10
|
||||
tkh.Random = rand.Reader
|
||||
|
||||
if err := tkh.InitNumerialValues(); err != nil {
|
||||
if err := tkh.initNumerialValues(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -118,17 +116,15 @@ func TestGenerateHidingPolynomial(t *testing.T) {
|
||||
tkh.nbits = 10
|
||||
tkh.Threshold = 10
|
||||
tkh.Random = rand.Reader
|
||||
if err := tkh.InitNumerialValues(); err != nil {
|
||||
if err := tkh.initNumerialValues(); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := tkh.GenerateHidingPolynomial(); err != nil {
|
||||
if err := tkh.generateHidingPolynomial(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
p := tkh.polynomialCoefficients
|
||||
if len(p) != tkh.Threshold {
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
if n(p[0]) != n(tkh.d) {
|
||||
t.Fail()
|
||||
@@ -147,7 +143,7 @@ func TestComputeShare(t *testing.T) {
|
||||
tkh.TotalNumberOfDecryptionServers = 5
|
||||
tkh.nm = b(103)
|
||||
tkh.polynomialCoefficients = []*big.Int{b(29), b(88), b(51)}
|
||||
share := tkh.ComputeShare(2)
|
||||
share := tkh.computeShare(2)
|
||||
if n(share) != 31 {
|
||||
t.Error("error computing a share. ", share)
|
||||
}
|
||||
@@ -159,16 +155,14 @@ func TestCreateShares(t *testing.T) {
|
||||
tkh.Threshold = 10
|
||||
tkh.TotalNumberOfDecryptionServers = 100
|
||||
tkh.Random = rand.Reader
|
||||
if err := tkh.InitNumerialValues(); err != nil {
|
||||
if err := tkh.initNumerialValues(); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if err := tkh.GenerateHidingPolynomial(); err != nil {
|
||||
if err := tkh.generateHidingPolynomial(); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if shares := tkh.CreateShares(); len(shares) != 100 {
|
||||
if shares := tkh.createShares(); len(shares) != 100 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@@ -178,7 +172,7 @@ func TestCreateViArray(t *testing.T) {
|
||||
tkh.TotalNumberOfDecryptionServers = 10
|
||||
tkh.v = b(54)
|
||||
tkh.nSquare = b(101 * 101)
|
||||
vArr := tkh.CreateViArray([]*big.Int{b(12), b(90), b(103)})
|
||||
vArr := tkh.createViArray([]*big.Int{b(12), b(90), b(103)})
|
||||
exp := []*big.Int{b(6162), b(304), b(2728)}
|
||||
if !reflect.DeepEqual(vArr, exp) {
|
||||
t.Fail()
|
||||
@@ -187,7 +181,7 @@ func TestCreateViArray(t *testing.T) {
|
||||
|
||||
func TestGetThresholdKeyGenerator(t *testing.T) {
|
||||
tkh := GetThresholdKeyGenerator(50, 10, 6, rand.Reader)
|
||||
if err := tkh.InitNumerialValues(); err != nil {
|
||||
if err := tkh.initNumerialValues(); err != nil {
|
||||
t.Error(nil)
|
||||
}
|
||||
}
|
||||
@@ -209,7 +203,7 @@ func TestGenerate(t *testing.T) {
|
||||
if len(tpk.Vi) != 10 {
|
||||
t.Fail()
|
||||
}
|
||||
if tpk.G == nil || tpk.N == nil {
|
||||
if tpk.N == nil {
|
||||
t.Fail()
|
||||
}
|
||||
if tpk.Threshold != 6 || tpk.TotalNumberOfDecryptionServers != 10 {
|
||||
@@ -223,9 +217,8 @@ func TestComputeV(t *testing.T) {
|
||||
tkh.n = b(1907 * 1823)
|
||||
tkh.nSquare = new(big.Int).Mul(tkh.n, tkh.n)
|
||||
for i := 0; i < 100; i++ {
|
||||
if err := tkh.ComputeV(); err != nil {
|
||||
if err := tkh.computeV(); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if tkh.v.Cmp(tkh.nSquare) > 0 {
|
||||
t.Error("v is too big")
|
||||
@@ -237,5 +230,4 @@ func TestComputeV(t *testing.T) {
|
||||
t.Error(`v has never been bigger than n. It is suspicious in the sense<
|
||||
than it was taken in the range 0...n**2 -1
|
||||
`)
|
||||
|
||||
}
|
||||
+60
-54
@@ -7,7 +7,7 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func GetThresholdPrivateKey() *ThresholdPrivateKey {
|
||||
func getThresholdPrivateKey() *ThresholdPrivateKey {
|
||||
tkh := GetThresholdKeyGenerator(32, 10, 6, rand.Reader)
|
||||
tpks, err := tkh.Generate()
|
||||
if err != nil {
|
||||
@@ -17,19 +17,35 @@ func GetThresholdPrivateKey() *ThresholdPrivateKey {
|
||||
}
|
||||
|
||||
func TestDelta(t *testing.T) {
|
||||
tk := new(ThresholdKey)
|
||||
tk := new(ThresholdPublicKey)
|
||||
tk.TotalNumberOfDecryptionServers = 6
|
||||
if delta := tk.Delta(); 720 != n(delta) {
|
||||
if delta := tk.delta(); 720 != n(delta) {
|
||||
t.Error("Delta is not 720 but", delta)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExp(t *testing.T) {
|
||||
tk := new(ThresholdPublicKey)
|
||||
|
||||
if exp := tk.exp(big.NewInt(720), big.NewInt(10), big.NewInt(49)); 43 != n(exp) {
|
||||
t.Error("Unexpected exponent. Expected 43 but got", exp)
|
||||
}
|
||||
|
||||
if exp := tk.exp(big.NewInt(720), big.NewInt(0), big.NewInt(49)); 1 != n(exp) {
|
||||
t.Error("Unexpected exponent. Expected 0 but got", exp)
|
||||
}
|
||||
|
||||
if exp := tk.exp(big.NewInt(720), big.NewInt(-10), big.NewInt(49)); 8 != n(exp) {
|
||||
t.Error("Unexpected exponent. Expected 8 but got", exp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCombineSharesConstant(t *testing.T) {
|
||||
tk := new(ThresholdKey)
|
||||
tk := new(ThresholdPublicKey)
|
||||
tk.N = big.NewInt(101 * 103)
|
||||
tk.TotalNumberOfDecryptionServers = 6
|
||||
|
||||
if c := tk.CombineSharesConstant(); !reflect.DeepEqual(big.NewInt(4558), c) {
|
||||
if c := tk.combineSharesConstant(); !reflect.DeepEqual(big.NewInt(4558), c) {
|
||||
t.Error("wrong combined key. ", c)
|
||||
}
|
||||
}
|
||||
@@ -66,7 +82,7 @@ func TestCopyVi(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEncryptWithThresholdKey(t *testing.T) {
|
||||
pd := GetThresholdPrivateKey()
|
||||
pd := getThresholdPrivateKey()
|
||||
_, err := pd.Encrypt(big.NewInt(876), rand.Reader)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
@@ -74,7 +90,7 @@ func TestEncryptWithThresholdKey(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDecryptWithThresholdKey(t *testing.T) {
|
||||
pd := GetThresholdPrivateKey()
|
||||
pd := getThresholdPrivateKey()
|
||||
c, err := pd.Encrypt(big.NewInt(876), rand.Reader)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
@@ -84,7 +100,7 @@ func TestDecryptWithThresholdKey(t *testing.T) {
|
||||
|
||||
func TestVerifyPart1(t *testing.T) {
|
||||
pd := new(PartialDecryptionZKP)
|
||||
pd.Key = new(ThresholdKey)
|
||||
pd.Key = new(ThresholdPublicKey)
|
||||
pd.Key.N = b(131)
|
||||
pd.Decryption = b(101)
|
||||
pd.C = b(99)
|
||||
@@ -98,7 +114,7 @@ func TestVerifyPart1(t *testing.T) {
|
||||
|
||||
func TestVerifyPart2(t *testing.T) {
|
||||
pd := new(PartialDecryptionZKP)
|
||||
pd.Key = new(ThresholdKey)
|
||||
pd.Key = new(ThresholdPublicKey)
|
||||
pd.Id = 1
|
||||
pd.Key.Vi = []*big.Int{b(77), b(67)} // vi is 67
|
||||
pd.Key.N = b(131)
|
||||
@@ -111,16 +127,14 @@ func TestVerifyPart2(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDecryptAndProduceZNP(t *testing.T) {
|
||||
pd := GetThresholdPrivateKey()
|
||||
pd := getThresholdPrivateKey()
|
||||
c, err := pd.Encrypt(big.NewInt(876), rand.Reader)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
znp, err := pd.DecryptAndProduceZNP(c.C, rand.Reader)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !znp.Verify() {
|
||||
@@ -129,35 +143,35 @@ func TestDecryptAndProduceZNP(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMakeVerificationBeforeCombiningPartialDecryptions(t *testing.T) {
|
||||
tk := new(ThresholdKey)
|
||||
tk := new(ThresholdPublicKey)
|
||||
tk.Threshold = 2
|
||||
if tk.MakeVerificationBeforeCombiningPartialDecryptions([]*PartialDecryption{}) == nil {
|
||||
if tk.verifyPartialDecryptions([]*PartialDecryption{}) == nil {
|
||||
t.Fail()
|
||||
}
|
||||
prms := []*PartialDecryption{new(PartialDecryption), new(PartialDecryption)}
|
||||
prms[1].Id = 1
|
||||
if tk.MakeVerificationBeforeCombiningPartialDecryptions(prms) != nil {
|
||||
if tk.verifyPartialDecryptions(prms) != nil {
|
||||
t.Fail()
|
||||
}
|
||||
prms[1].Id = 0
|
||||
if tk.MakeVerificationBeforeCombiningPartialDecryptions(prms) == nil {
|
||||
if tk.verifyPartialDecryptions(prms) == nil {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateLambda(t *testing.T) {
|
||||
tk := new(ThresholdKey)
|
||||
tk := new(ThresholdPublicKey)
|
||||
lambda := b(11)
|
||||
share1 := &PartialDecryption{3, b(5)}
|
||||
share2 := &PartialDecryption{7, b(3)}
|
||||
res := tk.UpdateLambda(share1, share2, lambda)
|
||||
res := tk.updateLambda(share1, share2, lambda)
|
||||
if n(res) != 20 {
|
||||
t.Error("wrong lambda", n(res))
|
||||
}
|
||||
}
|
||||
|
||||
func TestupdateCprime(t *testing.T) {
|
||||
tk := new(ThresholdKey)
|
||||
tk := new(ThresholdPublicKey)
|
||||
tk.N = b(99)
|
||||
cprime := b(77)
|
||||
lambda := b(52)
|
||||
@@ -174,13 +188,11 @@ func TestEncryptingDecryptingSimple(t *testing.T) {
|
||||
tpks, err := tkh.Generate()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
message := b(100)
|
||||
c, err := tpks[1].Encrypt(message, rand.Reader)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
share1 := tpks[0].Decrypt(c.C)
|
||||
message2, err := tpks[0].CombinePartialDecryptions([]*PartialDecryption{share1})
|
||||
@@ -197,13 +209,11 @@ func TestEncryptingDecrypting(t *testing.T) {
|
||||
tpks, err := tkh.Generate()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
message := b(100)
|
||||
c, err := tpks[1].Encrypt(message, rand.Reader)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
share1 := tpks[0].Decrypt(c.C)
|
||||
share2 := tpks[1].Decrypt(c.C)
|
||||
@@ -216,42 +226,48 @@ func TestEncryptingDecrypting(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHomomorphicThresholdEncryption(t *testing.T) {
|
||||
tkh := GetThresholdKeyGenerator(10, 2, 2, rand.Reader)
|
||||
tpks, _ := tkh.Generate()
|
||||
|
||||
plainText1 := b(13)
|
||||
plainText2 := b(19)
|
||||
|
||||
cypher1, _ := tpks[0].Encrypt(plainText1, rand.Reader)
|
||||
cypher2, _ := tpks[1].Encrypt(plainText2, rand.Reader)
|
||||
|
||||
cypher3 := tpks[0].Add(cypher1, cypher2)
|
||||
|
||||
share1 := tpks[0].Decrypt(cypher3.C)
|
||||
share2 := tpks[1].Decrypt(cypher3.C)
|
||||
|
||||
combined, _ := tpks[0].CombinePartialDecryptions([]*PartialDecryption{share1, share2})
|
||||
|
||||
expected := big.NewInt(32) // 13 + 19
|
||||
|
||||
if !reflect.DeepEqual(combined, expected) { // 13 + 19
|
||||
t.Errorf("Unexpected decryption result. Expected %v but got %v", expected, combined)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecryption(t *testing.T) {
|
||||
// test the correct decryption of '100'.
|
||||
share1 := &PartialDecryption{1, b(384111638639)}
|
||||
share2 := &PartialDecryption{2, b(235243761043)}
|
||||
tk := new(ThresholdKey)
|
||||
tk := new(ThresholdPublicKey)
|
||||
tk.Threshold = 2
|
||||
tk.TotalNumberOfDecryptionServers = 2
|
||||
tk.N = b(637753)
|
||||
tk.G = b(637754)
|
||||
tk.V = b(70661107826)
|
||||
if msg, err := tk.CombinePartialDecryptions([]*PartialDecryption{share1, share2}); err != nil {
|
||||
t.Error(err)
|
||||
} else if n(msg) != 100 {
|
||||
t.Error("decrypted message was not 100 but ", msg)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestDivide(t *testing.T) {
|
||||
tk := new(ThresholdKey)
|
||||
if r := tk.divide(b(77), b(4)); n(r) != 19 {
|
||||
t.Error("77 / 4 != 19 ( ", r, " )")
|
||||
}
|
||||
if r := tk.divide(b(-77), b(-4)); n(r) != 19 {
|
||||
t.Error("-77 / -4 != 19 ( ", r, " )")
|
||||
}
|
||||
if r := tk.divide(b(-77), b(4)); n(r) != -19 {
|
||||
t.Error("-77 / 4 != -19 ( ", r, " )")
|
||||
}
|
||||
if r := tk.divide(b(77), b(-4)); n(r) != -19 {
|
||||
t.Error("77 / -4 != -19 ( ", r, " )")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
pk := GetThresholdPrivateKey()
|
||||
pk := getThresholdPrivateKey()
|
||||
if err := pk.Validate(rand.Reader); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -266,23 +282,19 @@ func TestCombinePartialDecryptionsZKP(t *testing.T) {
|
||||
tpks, err := tkh.Generate()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
message := b(100)
|
||||
c, err := tpks[1].Encrypt(message, rand.Reader)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
share1, err := tpks[0].DecryptAndProduceZNP(c.C, rand.Reader)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
share2, err := tpks[1].DecryptAndProduceZNP(c.C, rand.Reader)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
message2, err := tpks[0].CombinePartialDecryptionsZKP([]*PartialDecryptionZKP{share1, share2})
|
||||
if err != nil {
|
||||
@@ -329,31 +341,26 @@ func TestVerifyDecryption(t *testing.T) {
|
||||
tkh := GetThresholdKeyGenerator(10, 2, 2, rand.Reader)
|
||||
tpks, err := tkh.Generate()
|
||||
|
||||
pk := &tpks[0].ThresholdKey
|
||||
pk := &tpks[0].ThresholdPublicKey
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
expt := b(101)
|
||||
cypher, err := tpks[0].Encrypt(expt, rand.Reader)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
pd1, err := tpks[0].DecryptAndProduceZNP(cypher.C, rand.Reader)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
pd2, err := tpks[1].DecryptAndProduceZNP(cypher.C, rand.Reader)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
pds := []*PartialDecryptionZKP{pd1, pd2}
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = pk.VerifyDecryption(cypher.C, b(101), pds); err != nil {
|
||||
@@ -365,5 +372,4 @@ func TestVerifyDecryption(t *testing.T) {
|
||||
if err = pk.VerifyDecryption(new(big.Int).Add(b(1), cypher.C), b(101), pds); err == nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user