This commit is contained in:
didier amyot committed 2014-11-29 22:40:35 -08:00
1 parent ca20730438
commit 8a9743f08e
11 files changed
+1805

No files matched your search

+38
View File
@@ -0,0 +1,38 @@
//The MIT License (MIT)
//Copyright (c) 2013 didier amyot
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
/*
Implementation of the paillier cryptosystem. See
http://en.wikipedia.org/wiki/Paillier_cryptosystem for an introduction.
The threshold paillier cryptosystem is a translation of the java version
that can be found at http://cs.utdallas.edu/dspl/cgi-bin/pailliertoolbox/ that
is an implementation of the algorithm defined in Damgård's paper
"A Generalization of Paillier's Public-Key System with Applications to
Electronic Voting".
Another important feature of the library is the ease of serilisation of all
the structs in JSON and BSON.
Implements the paillier cryptosystem and threshold paillier crytposystem.
*/
package paillier
+256
View File
@@ -0,0 +1,256 @@
package paillier
// all the methods relative to the set/get json/bson should be stored
// in this file.
import (
"encoding/json"
"errors"
"fmt"
"math/big"
"gopkg.in/mgo.v2/bson"
)
func fromHex(hex string) (*big.Int, error) {
n, err := new(big.Int).SetString(hex, 16)
if !err {
msg := fmt.Sprintf("Cannot convert %s to int as hexadecimal", hex)
return nil, errors.New(msg)
}
return n, nil
}
func all(oks []bool) bool {
for _, ok := range oks {
if !ok {
return false
}
}
return true
}
type dbCypher struct {
C string
}
func (this *Cypher) GetBSON() (interface{}, error) {
return &dbCypher{fmt.Sprintf("%x", this.C)}, nil
}
func (cypher *Cypher) SetBSON(raw bson.Raw) error {
c := dbCypher{}
if err := raw.Unmarshal(&c); err != nil {
return err
}
var ok bool
cypher.C, ok = new(big.Int).SetString(c.C, 16)
if !ok {
return errors.New("big int not in hexadecimal format")
}
return nil
}
type dbThresholdKey struct {
TotalNumberOfDecryptionServers int
Threshold int
V string
Vi []string
N string
G string
}
func (this *dbThresholdKey) FromThresholdKey(key *ThresholdKey) {
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 {
key.TotalNumberOfDecryptionServers = this.TotalNumberOfDecryptionServers
key.Threshold = this.Threshold
oks := make([]bool, 3)
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")
}
key.Vi = make([]*big.Int, len(this.Vi))
var ok bool
for i, vi := range this.Vi {
key.Vi[i], ok = new(big.Int).SetString(vi, 16)
if !ok {
return errors.New("not hexadecimal")
}
}
return nil
}
func (this *ThresholdKey) GetBSON() (interface{}, error) {
r := new(dbThresholdKey)
r.FromThresholdKey(this)
return r, nil
}
func (this *ThresholdKey) SetBSON(raw bson.Raw) error {
r := new(dbThresholdKey)
if err := raw.Unmarshal(r); err != nil {
return err
}
return r.ToThresholdKey(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
}
func (this *PrivateKey) SetBSON(raw bson.Raw) error {
var err error = nil
c := new(dbPrivateKey)
raw.Unmarshal(c)
if c.N != "" {
this.N, err = fromHex(c.N)
if err != nil {
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
}
type dbPartialDecryptionZKP struct {
Z string `json:"z"`
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"`
Id int `json:"id"`
TotalNumberOfDecryptionServers int `json:"total_number_of_decryption_servers"`
Threshold int `json:"threshold"`
}
func (this *dbPartialDecryptionZKP) FromPartialDecryptionZKP(pd *PartialDecryptionZKP) {
this.Id = pd.Id
this.TotalNumberOfDecryptionServers = pd.Key.TotalNumberOfDecryptionServers
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)
this.Decryption = fmt.Sprintf("%x", pd.Decryption)
this.Vi = make([]string, len(pd.Key.Vi))
for i, vi := range pd.Key.Vi {
this.Vi[i] = fmt.Sprintf("%x", vi)
}
}
func (this *dbPartialDecryptionZKP) ToPartialDecryptionZKP(pd *PartialDecryptionZKP) error {
pd.Key = new(ThresholdKey)
var oks = make([]bool, 7)
pd.Id = this.Id
pd.Key.TotalNumberOfDecryptionServers = this.TotalNumberOfDecryptionServers
pd.Key.Threshold = this.Threshold
pd.Z, oks[0] = new(big.Int).SetString(this.Z, 16)
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)
if !all(oks) {
fmt.Println(oks)
fmt.Println(this.E, "|", this.Z, "|", this.C, "|", this.V, "|", this.Decryption)
return errors.New("numbers not in hexadecimal format")
}
pd.Key.Vi = make([]*big.Int, len(this.Vi))
var ok bool
for i, vi := range this.Vi {
pd.Key.Vi[i], ok = new(big.Int).SetString(vi, 16)
if !ok {
return errors.New("numbers not in hexadecimal format")
}
}
return nil
}
func (this *PartialDecryptionZKP) MarshalJSON() ([]byte, error) {
db := new(dbPartialDecryptionZKP)
db.FromPartialDecryptionZKP(this)
return json.Marshal(db)
}
func (this *PartialDecryptionZKP) UnmarshalJSON(data []byte) error {
db := new(dbPartialDecryptionZKP)
if err := json.Unmarshal(data, db); err != nil {
return err
}
return db.ToPartialDecryptionZKP(this)
}
func (this *PartialDecryptionZKP) GetBSON() (interface{}, error) {
db := new(dbPartialDecryptionZKP)
db.FromPartialDecryptionZKP(this)
return db, nil
}
func (this *PartialDecryptionZKP) SetBSON(raw bson.Raw) error {
db := new(dbPartialDecryptionZKP)
if err := raw.Unmarshal(db); err != nil {
return err
}
return db.ToPartialDecryptionZKP(this)
}
+123
View File
@@ -0,0 +1,123 @@
package paillier
import (
"crypto/rand"
"encoding/json"
"math/big"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
func AssertBSONIsGood(object, dump interface{}, t *testing.T) {
data, err := bson.Marshal(object)
if err != nil {
t.Error(err)
return
}
if err = bson.Unmarshal(data, dump); err != nil {
t.Error(err)
return
}
if !reflect.DeepEqual(object, dump) {
t.Fail()
}
}
func AssertJSONIsGood(object, dump interface{}, t *testing.T) {
data, err := json.Marshal(object)
if err != nil {
t.Error(err)
return
}
if err = json.Unmarshal(data, dump); err != nil {
t.Error(err)
return
}
if !reflect.DeepEqual(object, dump) {
t.Fail()
}
}
func TestCypherGetBSON(t *testing.T) {
key := CreatePrivateKey(big.NewInt(101), big.NewInt(113))
cypher, err := key.Encrypt(big.NewInt(100), rand.Reader)
if err != nil {
t.Error(err)
return
}
data, err := bson.Marshal(cypher)
if err != nil {
t.Error(err)
return
}
cypher2 := new(Cypher)
if err = bson.Unmarshal(data, cypher2); err != nil {
t.Error(err)
return
}
if !reflect.DeepEqual(cypher, cypher2) {
t.Fail()
}
}
func TestSetPrivateKeyBson(t *testing.T) {
key := CreatePrivateKey(big.NewInt(101), big.NewInt(113))
AssertBSONIsGood(key, new(PrivateKey), t)
}
func TestGetBSONEmptyKey(t *testing.T) {
key := new(PrivateKey)
m, err := key.GetBSON()
if err != nil {
t.Error(err)
}
if !reflect.DeepEqual(make(map[string]string), m) {
t.Error(m)
}
}
func TestPartialDecryptionZKPJsonification(t *testing.T) {
pd := new(PartialDecryptionZKP)
pd.Key = new(ThresholdKey)
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.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)
}
func TestPartialDecryptionZKPBSONification(t *testing.T) {
pd := new(PartialDecryptionZKP)
pd.Key = new(ThresholdKey)
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.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)
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)
}
+116
View File
@@ -0,0 +1,116 @@
package paillier
import (
"fmt"
"io"
"math/big"
)
type PublicKey struct {
N, G *big.Int // usually G is set to N+1
n2 *big.Int // the cache value of N^2
}
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
}
// 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
// package crypto/rand.
//
// 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)
if err != nil {
return nil, err
}
nSquare := pub.GetNSquare()
gm := new(big.Int).Exp(pub.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.
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())}
}
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
}
func (priv *PrivateKey) Decrypt(cypher *Cypher) (msg *big.Int) {
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)
return
}
type Cypher struct {
C *big.Int
}
func (this *Cypher) String() string {
return fmt.Sprintf("%x", this.C)
}
func L(u, n *big.Int) *big.Int {
t := new(big.Int).Add(u, big.NewInt(-1))
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 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)
return &PrivateKey{
PublicKey: PublicKey{
N: n,
G: g,
},
Lambda: lambda,
Mu: mu,
}
}
+70
View File
@@ -0,0 +1,70 @@
package paillier
import (
"crypto/rand"
"math/big"
"reflect"
"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) {
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")
}
}
func TestComputeMu(t *testing.T) {
p := big.NewInt(13)
q := big.NewInt(11)
lambda := computeLamda(p, q)
g := big.NewInt(5000)
n := new(big.Int).Mul(p, q)
exp := big.NewInt(3)
if !reflect.DeepEqual(computeMu(g, lambda, n), exp) {
t.Error("lambda is not well computed")
}
}
func TestEncryptDecryptSmall(t *testing.T) {
p := big.NewInt(13)
q := big.NewInt(11)
for i := 1; i < 10; i++ {
privateKey := CreatePrivateKey(p, q)
inicialValue := big.NewInt(100)
cypher, err := privateKey.Encrypt(inicialValue, rand.Reader)
if err != nil {
t.Error(err)
}
returnedValue := privateKey.Decrypt(cypher)
if !reflect.DeepEqual(inicialValue, returnedValue) {
t.Error("wrond decryption ", returnedValue, " is not ", inicialValue)
}
}
}
func TestAddCypher(t *testing.T) {
privateKey := CreatePrivateKey(big.NewInt(13), big.NewInt(11))
cypher1, _ := privateKey.Encrypt(big.NewInt(12), rand.Reader)
cypher2, _ := privateKey.Encrypt(big.NewInt(13), rand.Reader)
cypher3 := privateKey.Add(cypher1, cypher2)
m := privateKey.Decrypt(cypher3)
if !reflect.DeepEqual(m, big.NewInt(25)) {
t.Error(m)
}
}
+291
View File
@@ -0,0 +1,291 @@
package paillier
import (
"crypto/rand"
"crypto/sha256"
"errors"
"io"
"math/big"
"bitbucket.org/ustraca/crypto"
)
type ThresholdKey struct {
PublicKey
TotalNumberOfDecryptionServers int
Threshold int
V *big.Int
Vi []*big.Int
}
// 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 factorial of the number of TotalNumberOfDecryptionServers
func (this *ThresholdKey) Delta() *big.Int {
return crypto.Factorial(this.TotalNumberOfDecryptionServers)
}
func (this *ThresholdKey) MakeVerificationBeforeCombiningPartialDecryptions(shares []*PartialDecryption) error {
if len(shares) < this.Threshold {
return errors.New("Threshold not meet")
}
tmp := make(map[int]bool)
for _, share := range shares {
tmp[share.Id] = true
}
if len(tmp) != len(shares) {
return errors.New("two shares has been created by the same server")
}
return nil
}
func (this *ThresholdKey) 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()
for _, share2 := range shares {
if share2.Id != share.Id {
lambda = this.UpdateLambda(share, share2, lambda)
}
}
return lambda
}
func (this *ThresholdKey) 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 = new(big.Int).Mul(cprime, ret)
return new(big.Int).Mod(ret, this.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 {
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)
}
func (this *ThresholdKey) CombinePartialDecryptions(shares []*PartialDecryption) (*big.Int, error) {
if err := this.MakeVerificationBeforeCombiningPartialDecryptions(shares); err != nil {
return nil, err
}
cprime := ONE
for _, share := range shares {
lambda := this.ComputeLambda(share, shares)
cprime = this.updateCprime(cprime, lambda, share)
}
return this.computeDecryption(cprime), nil
}
func (this *ThresholdKey) 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)
}
// 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 {
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)
if err != nil {
return err
}
if res.Cmp(decryptedMessage) != 0 {
return errors.New("The decrypted message is not the same than the one in the shares")
}
return nil
}
type ThresholdPrivateKey struct {
ThresholdKey
Id int
Share *big.Int
}
// Decrypt the cypher text and returns the partial decryption
func (this *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())
return ret
}
func (this *ThresholdPrivateKey) copyVi() []*big.Int {
ret := make([]*big.Int, len(this.Vi))
for i, vi := range this.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))
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)
return new(big.Int).Add(r, tmp)
}
func (this *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) {
pd := new(PartialDecryptionZKP)
pd.Key = this.GetThresholdKey()
pd.C = c
pd.Id = this.Id
pd.Decryption = this.Decrypt(c).Decryption
// choose random number
r, err := rand.Int(random, this.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())
// compute b
b := new(big.Int).Exp(this.V, r, this.GetNSquare())
// compute hash
ci2 := new(big.Int).Exp(pd.Decryption, big.NewInt(2), nil)
pd.E = this.computeHash(a, b, c4, ci2)
pd.Z = this.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)
if err != nil {
return err
}
c, err := this.Encrypt(m, random)
if err != nil {
return err
}
proof, err := this.DecryptAndProduceZNP(c.C, random)
if err != nil {
return err
}
if !proof.Verify() {
return errors.New("invalid share.")
}
return nil
}
type PartialDecryption struct {
Id int
Decryption *big.Int
}
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
}
func (this *PartialDecryptionZKP) verifyPart1() *big.Int {
c4 := new(big.Int).Exp(this.C, FOUR, nil)
decryption2 := new(big.Int).Exp(this.Decryption, TWO, nil)
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())
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())
return b
}
func (this *PartialDecryptionZKP) Verify() bool {
a := this.verifyPart1()
b := this.verifyPart2()
hash := sha256.New()
hash.Write(a.Bytes())
hash.Write(b.Bytes())
c4 := new(big.Int).Exp(this.C, FOUR, nil)
hash.Write(c4.Bytes())
ci2 := new(big.Int).Exp(this.Decryption, TWO, nil)
hash.Write(ci2.Bytes())
expectedE := new(big.Int).SetBytes(hash.Sum([]byte{}))
return this.E.Cmp(expectedE) == 0
}
+200
View File
@@ -0,0 +1,200 @@
package paillier
import (
"crypto/rand"
"io"
"math/big"
"bitbucket.org/ustraca/crypto"
)
type ThresholdKeyGenerator struct {
nbits int
TotalNumberOfDecryptionServers int
Threshold int
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 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
nm *big.Int // nm = n*m
// As specified in the paper, d must satify d=1 mod n and d=0 mod m
d *big.Int
// A generator of QR in Z_{n^2}
v *big.Int
// 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
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
}
func (this *ThresholdKeyGenerator) GenerateSafePrimes() (*big.Int, *big.Int, error) {
return crypto.GenerateSafePrimes(this.nbits, this.Random)
}
func (this *ThresholdKeyGenerator) InitPandP1() error {
var err error
this.p, this.p1, err = this.GenerateSafePrimes()
return err
}
func (this *ThresholdKeyGenerator) InitQandQ1() error {
var err error
this.q, this.q1, err = this.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 (this *ThresholdKeyGenerator) ArePsAndQsGood() bool {
if this.p.Cmp(this.q) == 0 {
return false
}
if this.p.Cmp(this.q1) == 0 {
return false
}
if this.p1.Cmp(this.q) == 0 {
return false
}
return true
}
func (this *ThresholdKeyGenerator) InitPsAndQs() error {
if err := this.InitPandP1(); err != nil {
return err
}
if err := this.InitQandQ1(); err != nil {
return err
}
if !this.ArePsAndQsGood() {
return this.InitPsAndQs()
}
return nil
}
func (this *ThresholdKeyGenerator) ComputeV() error {
var err error
this.v, err = crypto.GetRandomGeneratorOfTheQuadraticResidue(this.nSquare, this.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)
}
func (this *ThresholdKeyGenerator) InitNumerialValues() error {
if err := this.InitPsAndQs(); err != nil {
return err
}
this.InitShortcuts()
this.InitD()
return this.ComputeV()
}
func (this *ThresholdKeyGenerator) GenerateHidingPolynomial() error {
this.polynomialCoefficients = make([]*big.Int, this.Threshold)
this.polynomialCoefficients[0] = this.d
var err error
for i := 1; i < this.Threshold; i++ {
this.polynomialCoefficients[i], err = rand.Int(this.Random, this.nm)
if err != nil {
return err
}
}
return nil
}
func (this *ThresholdKeyGenerator) ComputeShare(index int) *big.Int {
share := big.NewInt(0)
for i := 0; i < this.Threshold; i++ {
a := this.polynomialCoefficients[i]
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)
}
func (this *ThresholdKeyGenerator) CreateShares() []*big.Int {
shares := make([]*big.Int, this.TotalNumberOfDecryptionServers)
for i := 0; i < this.TotalNumberOfDecryptionServers; i++ {
shares[i] = this.ComputeShare(i)
}
return shares
}
func (this *ThresholdKeyGenerator) Delta() *big.Int {
return crypto.Factorial(this.TotalNumberOfDecryptionServers)
}
func (this *ThresholdKeyGenerator) CreateViArray(shares []*big.Int) (viArray []*big.Int) {
viArray = make([]*big.Int, len(shares))
delta := this.Delta()
for i, share := range shares {
tmp := new(big.Int).Mul(share, delta)
viArray[i] = new(big.Int).Exp(this.v, tmp, this.nSquare)
}
return viArray
}
func (this *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.TotalNumberOfDecryptionServers = this.TotalNumberOfDecryptionServers
ret.Threshold = this.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)
}
return ret
}
func (this *ThresholdKeyGenerator) Generate() ([]*ThresholdPrivateKey, error) {
if err := this.InitNumerialValues(); err != nil {
return nil, err
}
if err := this.GenerateHidingPolynomial(); err != nil {
return nil, err
}
return this.CreatePrivateKeys(), nil
}
+259
View File
@@ -0,0 +1,259 @@
package paillier
import (
"crypto/rand"
"math/big"
"reflect"
"testing"
)
var MockGenerateSafePrimes = func() (*big.Int, *big.Int, error) {
return big.NewInt(887), big.NewInt(443), nil
}
func AreSafePrimes(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)
}
if l := q.BitLen(); l != expectedLength-1 {
t.Error("q does not have the good length. ", l)
}
if !p.ProbablyPrime(100) {
t.Error("p is not a probable prime :(")
}
if !q.ProbablyPrime(100) {
t.Error("q is not a probable prime :(")
}
if p.Int64() != 2*q.Int64()+1 {
t.Error("p does not equals 2 * q + 1")
}
}
func TestGenerateSafePrimesOfThresholdKeyGenerator(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Random = rand.Reader
p, q, err := tkh.GenerateSafePrimes()
if err != nil {
t.Error(err)
return
}
AreSafePrimes(p, q, 10, t)
}
func TestInitPandP1(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Random = rand.Reader
tkh.InitPandP1()
AreSafePrimes(tkh.p, tkh.p1, 10, t)
}
func TestInitQandQ1(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Random = rand.Reader
tkh.InitQandQ1()
AreSafePrimes(tkh.q, tkh.q1, 10, t)
}
func TestInitPsAndQs(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Random = rand.Reader
tkh.InitPsAndQs()
AreSafePrimes(tkh.q, tkh.q1, 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() {
t.Fail()
}
tkh.p, tkh.p1, tkh.q, tkh.q1 = b(6), b(5), b(6), b(3)
if tkh.ArePsAndQsGood() {
t.Fail()
}
tkh.p, tkh.p1, tkh.q, tkh.q1 = b(6), b(5), b(5), b(3)
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()
if n(tkh.n) != 11*5 {
t.Error("wrong n", tkh.n)
}
if n(tkh.m) != 7*3 {
t.Error("wrong m", tkh.m)
}
if n(tkh.nm) != 11*5*7*3 {
t.Error("wrong nm", tkh.nm)
}
if n(tkh.nSquare) != 11*5*11*5 {
t.Error("wrong nSquare", tkh.nSquare)
}
}
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()
if n(tkh.d)%n(tkh.m) != 0 {
t.Fail()
}
if n(tkh.d)%n(tkh.n) != 1 {
t.Fail()
}
}
func TestInitNumerialValues(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Random = rand.Reader
if err := tkh.InitNumerialValues(); err != nil {
t.Error(err)
}
}
func TestGenerateHidingPolynomial(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Threshold = 10
tkh.Random = rand.Reader
if err := tkh.InitNumerialValues(); err != nil {
t.Error(err)
return
}
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()
}
for i := 1; i < len(p); i++ {
if j := n(p[i]); j < 0 || j >= n(tkh.nm) {
t.Fail()
}
}
}
func TestComputeShare(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Threshold = 3
tkh.TotalNumberOfDecryptionServers = 5
tkh.nm = b(103)
tkh.polynomialCoefficients = []*big.Int{b(29), b(88), b(51)}
share := tkh.ComputeShare(2)
if n(share) != 31 {
t.Error("error computing a share. ", share)
}
}
func TestCreateShares(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.nbits = 10
tkh.Threshold = 10
tkh.TotalNumberOfDecryptionServers = 100
tkh.Random = rand.Reader
if err := tkh.InitNumerialValues(); err != nil {
t.Error(err)
return
}
if err := tkh.GenerateHidingPolynomial(); err != nil {
t.Error(err)
return
}
if shares := tkh.CreateShares(); len(shares) != 100 {
t.Fail()
}
}
func TestCreateViArray(t *testing.T) {
tkh := new(ThresholdKeyGenerator)
tkh.TotalNumberOfDecryptionServers = 10
tkh.v = b(54)
tkh.nSquare = b(101 * 101)
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()
}
}
func TestGetThresholdKeyGenerator(t *testing.T) {
tkh := GetThresholdKeyGenerator(50, 10, 6, rand.Reader)
if err := tkh.InitNumerialValues(); err != nil {
t.Error(nil)
}
}
func TestGenerate(t *testing.T) {
tkh := GetThresholdKeyGenerator(32, 10, 6, rand.Reader)
tpks, err := tkh.Generate()
if err != nil {
t.Error(err)
return
}
if len(tpks) != 10 {
t.Fail()
}
for i, tpk := range tpks {
if tpk.Id != i+1 {
t.Fail()
}
if len(tpk.Vi) != 10 {
t.Fail()
}
if tpk.G == nil || tpk.N == nil {
t.Fail()
}
if tpk.Threshold != 6 || tpk.TotalNumberOfDecryptionServers != 10 {
t.Fail()
}
}
}
func TestComputeV(t *testing.T) {
tkh := GetThresholdKeyGenerator(32, 10, 6, rand.Reader)
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 {
t.Error(err)
return
}
if tkh.v.Cmp(tkh.nSquare) > 0 {
t.Error("v is too big")
}
if tkh.v.Cmp(tkh.n) > 0 {
return
}
}
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
`)
}
+369
View File
@@ -0,0 +1,369 @@
package paillier
import (
"crypto/rand"
"math/big"
"reflect"
"testing"
)
func GetThresholdPrivateKey() *ThresholdPrivateKey {
tkh := GetThresholdKeyGenerator(32, 10, 6, rand.Reader)
tpks, err := tkh.Generate()
if err != nil {
panic(err)
}
return tpks[6]
}
func TestDelta(t *testing.T) {
tk := new(ThresholdKey)
tk.TotalNumberOfDecryptionServers = 6
if delta := tk.Delta(); 720 != n(delta) {
t.Error("Delta is not 720 but", delta)
}
}
func TestCombineSharesConstant(t *testing.T) {
tk := new(ThresholdKey)
tk.N = big.NewInt(101 * 103)
tk.TotalNumberOfDecryptionServers = 6
if c := tk.CombineSharesConstant(); !reflect.DeepEqual(big.NewInt(4558), c) {
t.Error("wrong combined key. ", c)
}
}
func TestDecrypt(t *testing.T) {
key := new(ThresholdPrivateKey)
key.TotalNumberOfDecryptionServers = 10
key.N = b(101 * 103)
key.Share = b(862)
key.Id = 9
c := b(56)
partial := key.Decrypt(c)
if partial.Id != 9 {
t.Fail()
}
if n(partial.Decryption) != 40644522 {
t.Error("wrong decryption ", partial.Decryption)
}
}
func TestCopyVi(t *testing.T) {
key := new(ThresholdPrivateKey)
key.Vi = []*big.Int{b(34), b(2), b(29)}
vi := key.copyVi()
if !reflect.DeepEqual(vi, key.Vi) {
t.Fail()
}
key.Vi[1] = b(89)
if reflect.DeepEqual(vi, key.Vi) {
t.Fail()
}
}
func TestEncryptWithThresholdKey(t *testing.T) {
pd := GetThresholdPrivateKey()
_, err := pd.Encrypt(big.NewInt(876), rand.Reader)
if err != nil {
t.Fail()
}
}
func TestDecryptWithThresholdKey(t *testing.T) {
pd := GetThresholdPrivateKey()
c, err := pd.Encrypt(big.NewInt(876), rand.Reader)
if err != nil {
t.Fail()
}
pd.Decrypt(c.C)
}
func TestVerifyPart1(t *testing.T) {
pd := new(PartialDecryptionZKP)
pd.Key = new(ThresholdKey)
pd.Key.N = b(131)
pd.Decryption = b(101)
pd.C = b(99)
pd.E = b(112)
pd.Z = b(88)
if a := pd.verifyPart1(); n(a) != 11986 {
t.Error("wrong a ", a)
}
}
func TestVerifyPart2(t *testing.T) {
pd := new(PartialDecryptionZKP)
pd.Key = new(ThresholdKey)
pd.Id = 1
pd.Key.Vi = []*big.Int{b(77), b(67)} // vi is 67
pd.Key.N = b(131)
pd.Key.V = b(101)
pd.E = b(112)
pd.Z = b(88)
if b := pd.verifyPart2(); n(b) != 14602 {
t.Error("wrong b ", b)
}
}
func TestDecryptAndProduceZNP(t *testing.T) {
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() {
t.Fail()
}
}
func TestMakeVerificationBeforeCombiningPartialDecryptions(t *testing.T) {
tk := new(ThresholdKey)
tk.Threshold = 2
if tk.MakeVerificationBeforeCombiningPartialDecryptions([]*PartialDecryption{}) == nil {
t.Fail()
}
prms := []*PartialDecryption{new(PartialDecryption), new(PartialDecryption)}
prms[1].Id = 1
if tk.MakeVerificationBeforeCombiningPartialDecryptions(prms) != nil {
t.Fail()
}
prms[1].Id = 0
if tk.MakeVerificationBeforeCombiningPartialDecryptions(prms) == nil {
t.Fail()
}
}
func TestUpdateLambda(t *testing.T) {
tk := new(ThresholdKey)
lambda := b(11)
share1 := &PartialDecryption{3, b(5)}
share2 := &PartialDecryption{7, b(3)}
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.N = b(99)
cprime := b(77)
lambda := b(52)
share := &PartialDecryption{3, b(5)}
cprime = tk.updateCprime(cprime, lambda, share)
if n(cprime) != 8558 {
t.Error("wrong cprime", cprime)
}
}
func TestEncryptingDecryptingSimple(t *testing.T) {
tkh := GetThresholdKeyGenerator(10, 2, 1, rand.Reader)
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})
if err != nil {
t.Error(err)
}
if n(message) != n(message2) {
t.Error("decrypted message is not the same one than the input one ", message2)
}
}
func TestEncryptingDecrypting(t *testing.T) {
tkh := GetThresholdKeyGenerator(10, 2, 2, rand.Reader)
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)
message2, err := tpks[0].CombinePartialDecryptions([]*PartialDecryption{share1, share2})
if err != nil {
t.Error(err)
}
if n(message) != n(message2) {
t.Error("The decrypted cyphered is not original massage but ", message2)
}
}
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.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()
if err := pk.Validate(rand.Reader); err != nil {
t.Error(err)
}
pk.Id++
if err := pk.Validate(rand.Reader); err == nil {
t.Fail()
}
}
func TestCombinePartialDecryptionsZKP(t *testing.T) {
tkh := GetThresholdKeyGenerator(10, 2, 2, rand.Reader)
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 {
t.Error(err)
}
if n(message) != n(message2) {
t.Error("The decrypted cyphered is not original massage but ", message2)
}
share1.E = b(687687678)
_, err = tpks[0].CombinePartialDecryptionsZKP([]*PartialDecryptionZKP{share1, share2})
if err == nil {
t.Fail()
}
}
func TestCombinePartialDecryptionsWith100Shares(t *testing.T) {
tkh := GetThresholdKeyGenerator(10, 100, 50, rand.Reader)
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
}
shares := make([]*PartialDecryption, 75)
for i := 0; i < 75; i++ {
shares[i] = tpks[i].Decrypt(c.C)
}
message2, err := tpks[0].CombinePartialDecryptions(shares)
if err != nil {
t.Error(err)
}
if n(message) != n(message2) {
t.Error("The decrypted cyphered is not original massage but ", message2)
}
}
func TestVerifyDecryption(t *testing.T) {
tkh := GetThresholdKeyGenerator(10, 2, 2, rand.Reader)
tpks, err := tkh.Generate()
pk := &tpks[0].ThresholdKey
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 {
t.Error(err)
}
if err = pk.VerifyDecryption(cypher.C, b(100), pds); err == nil {
t.Error(err)
}
if err = pk.VerifyDecryption(new(big.Int).Add(b(1), cypher.C), b(101), pds); err == nil {
t.Error(err)
}
}
+28
View File
@@ -0,0 +1,28 @@
package paillier
import (
"crypto/rand"
"io"
"math/big"
)
var ZERO = big.NewInt(0)
var ONE = big.NewInt(1)
var TWO = big.NewInt(2)
var FOUR = big.NewInt(4)
// Generate a random element in the group of all the elements in Z/nZ that
// has a multiplicative inverse.
func GetRandomNumberInMultiplicativeGroup(n *big.Int, random io.Reader) (*big.Int, error) {
r, err := rand.Int(random, n)
if err != nil {
return nil, err
}
zero := big.NewInt(0)
one := big.NewInt(1)
if zero.Cmp(r) == 0 || one.Cmp(new(big.Int).GCD(nil, nil, n, r)) != 0 {
return GetRandomNumberInMultiplicativeGroup(n, random)
}
return r, nil
}
+55
View File
@@ -0,0 +1,55 @@
package paillier
import (
"crypto/rand"
"math/big"
"testing"
)
func b(i int) *big.Int {
return big.NewInt(int64(i))
}
func n(i *big.Int) int {
return int(i.Int64())
}
func areRelativelyPrime(a, b int) bool {
if b == 0 {
return a == 1
}
return areRelativelyPrime(b, a%b)
}
func TestConstants(t *testing.T) {
if n(ZERO) != 0 {
t.Fail()
}
if n(ONE) != 1 {
t.Fail()
}
if n(TWO) != 2 {
t.Fail()
}
if n(FOUR) != 4 {
t.Fail()
}
}
func TestGetRandomNumberInMultiplicativeGroup(t *testing.T) {
k := b(2 * 3 * 5 * 7)
for i := 0; i < 100; i++ {
m, err := GetRandomNumberInMultiplicativeGroup(k, rand.Reader)
if err != nil {
t.Error(err)
return
}
if !areRelativelyPrime(n(k), n(m)) {
t.Fail()
}
}
}