imported from https://bitbucket.org/ustraca/crypto
This commit is contained in:
1 parent
ca20730438
commit
8a9743f08e
11 files changed
+1805
No files matched your search
@@ -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
@@ -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)
|
||||||
|
}
|
||||||
@@ -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
@@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
`)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in new issue
Block a user