Documentation improvements, code cleaned up #2
+38
-4
@@ -8,6 +8,20 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Public key for a threshold Paillier scheme.
|
||||||
|
//
|
||||||
|
// `V` is a generator in the cyclic group of squares Z_n^2 and is used to
|
||||||
|
// execute a zero-knowledge proof of a received share decryption.
|
||||||
|
//
|
||||||
|
// `Vi` is an array of verification keys for each decryption server `i`.
|
||||||
|
//
|
||||||
|
// Key generation, encryption, share decryption and combining for the threshold
|
||||||
|
// Paillier scheme has been described in [DJN 10], section 5.1.
|
||||||
|
//
|
||||||
|
// [DJN 10]: Ivan Damgard, Mads Jurik, Jesper Buus Nielsen, (2010)
|
||||||
|
// A Generalization of Paillier’s Public-Key System
|
||||||
|
// with Applications to Electronic Voting
|
||||||
|
// Aarhus University, Dept. of Computer Science, BRICS
|
||||||
type ThresholdKey struct {
|
type ThresholdKey struct {
|
||||||
PublicKey
|
PublicKey
|
||||||
TotalNumberOfDecryptionServers int
|
TotalNumberOfDecryptionServers int
|
||||||
@@ -16,17 +30,23 @@ type ThresholdKey struct {
|
|||||||
Vi []*big.Int
|
Vi []*big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the value of (4*delta**2)** -1 mod n
|
// Returns the value of [(4*delta^2)]^-1 mod n.
|
||||||
|
// It is a constant value for the given `ThresholdKey` and is used in the last
|
||||||
|
// step of share combining.
|
||||||
func (this *ThresholdKey) combineSharesConstant() *big.Int {
|
func (this *ThresholdKey) combineSharesConstant() *big.Int {
|
||||||
tmp := new(big.Int).Mul(FOUR, new(big.Int).Mul(this.delta(), this.delta()))
|
tmp := new(big.Int).Mul(FOUR, new(big.Int).Mul(this.delta(), this.delta()))
|
||||||
return (&big.Int{}).ModInverse(tmp, this.N)
|
return (&big.Int{}).ModInverse(tmp, this.N)
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the factorial of the number of TotalNumberOfDecryptionServers
|
// Returns the factorial of the number of `TotalNumberOfDecryptionServers`.
|
||||||
|
// It is a contant value for the given `ThresholdKey`.
|
||||||
func (this *ThresholdKey) delta() *big.Int {
|
func (this *ThresholdKey) delta() *big.Int {
|
||||||
return Factorial(this.TotalNumberOfDecryptionServers)
|
return Factorial(this.TotalNumberOfDecryptionServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks if the number of received, unique shares is less than the
|
||||||
|
// required threshold.
|
||||||
|
// This method does not execute ZKP on received shares.
|
||||||
func (this *ThresholdKey) makeVerificationBeforeCombiningPartialDecryptions(shares []*PartialDecryption) error {
|
func (this *ThresholdKey) makeVerificationBeforeCombiningPartialDecryptions(shares []*PartialDecryption) error {
|
||||||
if len(shares) < this.Threshold {
|
if len(shares) < this.Threshold {
|
||||||
return errors.New("Threshold not meet")
|
return errors.New("Threshold not meet")
|
||||||
@@ -47,6 +67,8 @@ func (this *ThresholdKey) updateLambda(share1, share2 *PartialDecryption, lambda
|
|||||||
return new(big.Int).Div(num, denom)
|
return new(big.Int).Div(num, denom)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Evaluates lambda parameter for each decrypted share. See second figure in the
|
||||||
|
// "Share combining" paragraph in [DJK 10], section 5.2.
|
||||||
func (this *ThresholdKey) computeLambda(share *PartialDecryption, shares []*PartialDecryption) *big.Int {
|
func (this *ThresholdKey) computeLambda(share *PartialDecryption, shares []*PartialDecryption) *big.Int {
|
||||||
lambda := this.delta()
|
lambda := this.delta()
|
||||||
for _, share2 := range shares {
|
for _, share2 := range shares {
|
||||||
@@ -64,6 +86,7 @@ func (this *ThresholdKey) updateCprime(cprime, lambda *big.Int, share *PartialDe
|
|||||||
return new(big.Int).Mod(ret, this.GetNSquare())
|
return new(big.Int).Mod(ret, this.GetNSquare())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: unused? kill?
|
||||||
func (this *ThresholdKey) divide(a, b *big.Int) *big.Int {
|
func (this *ThresholdKey) divide(a, b *big.Int) *big.Int {
|
||||||
if a.Cmp(ZERO) == -1 {
|
if a.Cmp(ZERO) == -1 {
|
||||||
if b.Cmp(ZERO) == -1 {
|
if b.Cmp(ZERO) == -1 {
|
||||||
@@ -83,11 +106,18 @@ func (this *ThresholdKey) exp(a, b, c *big.Int) *big.Int {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Executes the last step of message decryption. Takes `cprime` value computed
|
||||||
|
// from valid shares provided by decryption servers and multiplies this value
|
||||||
|
// by `combineSharesContant` which is specific to the given public `ThresholdKey`.
|
||||||
func (this *ThresholdKey) computeDecryption(cprime *big.Int) *big.Int {
|
func (this *ThresholdKey) computeDecryption(cprime *big.Int) *big.Int {
|
||||||
l := L(cprime, this.N)
|
l := L(cprime, this.N)
|
||||||
return new(big.Int).Mod(new(big.Int).Mul(this.combineSharesConstant(), l), this.N)
|
return new(big.Int).Mod(new(big.Int).Mul(this.combineSharesConstant(), l), this.N)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Combines partial decryptions provided by decryption servers and returns
|
||||||
|
// decrypted message.
|
||||||
|
// This function does not verify zero knowledge proofs. Returned message can be
|
||||||
|
// incorrectly decrypted if an adversary corrupted partial decryption.
|
||||||
func (this *ThresholdKey) CombinePartialDecryptions(shares []*PartialDecryption) (*big.Int, error) {
|
func (this *ThresholdKey) CombinePartialDecryptions(shares []*PartialDecryption) (*big.Int, error) {
|
||||||
if err := this.makeVerificationBeforeCombiningPartialDecryptions(shares); err != nil {
|
if err := this.makeVerificationBeforeCombiningPartialDecryptions(shares); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -102,6 +132,10 @@ func (this *ThresholdKey) CombinePartialDecryptions(shares []*PartialDecryption)
|
|||||||
return this.computeDecryption(cprime), nil
|
return this.computeDecryption(cprime), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Combines partial decryptions provided by decription servers and returns
|
||||||
|
// decrypted message.
|
||||||
|
// Function verifies zero knowledge proofs and filters out all shares that failed
|
||||||
|
// verification.
|
||||||
func (this *ThresholdKey) CombinePartialDecryptionsZKP(shares []*PartialDecryptionZKP) (*big.Int, error) {
|
func (this *ThresholdKey) CombinePartialDecryptionsZKP(shares []*PartialDecryptionZKP) (*big.Int, error) {
|
||||||
ret := make([]*PartialDecryption, 0)
|
ret := make([]*PartialDecryption, 0)
|
||||||
for _, share := range shares {
|
for _, share := range shares {
|
||||||
@@ -157,7 +191,7 @@ func (this *ThresholdPrivateKey) copyVi() []*big.Int {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *ThresholdPrivateKey) GetThresholdKey() *ThresholdKey {
|
func (this *ThresholdPrivateKey) getThresholdKey() *ThresholdKey {
|
||||||
ret := new(ThresholdKey)
|
ret := new(ThresholdKey)
|
||||||
ret.Threshold = this.Threshold
|
ret.Threshold = this.Threshold
|
||||||
ret.TotalNumberOfDecryptionServers = this.TotalNumberOfDecryptionServers
|
ret.TotalNumberOfDecryptionServers = this.TotalNumberOfDecryptionServers
|
||||||
@@ -184,7 +218,7 @@ func (this *ThresholdPrivateKey) computeHash(a, b, c4, ci2 *big.Int) *big.Int {
|
|||||||
|
|
||||||
func (this *ThresholdPrivateKey) DecryptAndProduceZNP(c *big.Int, random io.Reader) (*PartialDecryptionZKP, error) {
|
func (this *ThresholdPrivateKey) DecryptAndProduceZNP(c *big.Int, random io.Reader) (*PartialDecryptionZKP, error) {
|
||||||
pd := new(PartialDecryptionZKP)
|
pd := new(PartialDecryptionZKP)
|
||||||
pd.Key = this.GetThresholdKey()
|
pd.Key = this.getThresholdKey()
|
||||||
pd.C = c
|
pd.C = c
|
||||||
pd.Id = this.Id
|
pd.Id = this.Id
|
||||||
pd.Decryption = this.Decrypt(c).Decryption
|
pd.Decryption = this.Decrypt(c).Decryption
|
||||||
|
|||||||
Reference in new issue
Block a user