Files
paillier/paillier.go
T
Piotr Dyraga d892a58e4b Cleared up Paillier scheme API
The code for generating private key is based on approach described in [KL 08], construction 11.32 which is compatible with the one described in [DJN 10], section 3.2 except that instead of generating Lamda private key compontent from LCM of `p` and `q` we use Euler's totient function as suggested in [KL 08]. I cleared up naming as well as removed G and Mu parameters from Paillier key. For the modification of Paillier scheme we use, where g = n + 1, N is the only one parameter needed for a public key. Also, Mu is needed only for Decrypting and can be computed there from Lambda and N so there is no need to keep it in the private key.

I added documentation to <Key, Enc, Dec> functions with an important note that `p` and `q` supplied to `CreatePrivateKey` must be either of equal length or `gcd(pq, (p-1)(q-1)) = 1` which is assured if both primes are of equal length. This requirement is mentioned both in [KL 08] and [DJN 10].

[KL 08]:  Jonathan Katz, Yehuda Lindell, (2008)
          Introduction to Modern Cryptography: Principles and Protocols,
          Chapman & Hall/CRC

[DJN 10]: Ivan Damgard, Mads Jurik, Jesper Buus Nielsen, (2010)
          A Generalization of Paillier’s Public-Key System
          with Applications to Electronic Voting
          Aarhus University, Dept. of Computer Science, BRICS
2018-05-24 18:41:10 +02:00

134 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 plaintext in a cypher one. The plain text must be smaller that
// N and bigger or equal than zero. random is usually rand.Reader from the
// package crypto/rand.
//
// m - plaintext to encrypt
// E(m, r) = [(1 + N) r^N] mod N^2
//
// See [KL 08] construction 11.32, page 414.
//
// Returns an error if an error has be returned by io.Reader.
func (pub *PublicKey) Encrypt(m *big.Int, random io.Reader) (*Cypher, error) {
r, err := GetRandomNumberInMultiplicativeGroup(pub.N, random)
if err != nil {
return nil, err
}
nSquare := pub.GetNSquare()
g := new(big.Int).Add(pub.N, big.NewInt(1))
gm := new(big.Int).Exp(g, m, nSquare)
rn := new(big.Int).Exp(r, pub.N, nSquare)
return &Cypher{new(big.Int).Mod(new(big.Int).Mul(rn, gm), nSquare)}, nil
}
// Takes two cypher texts and returns a 3rd one that encode
// the sum of the two plain texts.
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 *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)
return ret
}
// Decodes ciphertext into a plaintext message.
//
// c - cyphertext to decrypt
// N, lambda - key attributes
//
// D(c) = [ ((c^lambda) mod N^2) - 1) / N ] lambda^-1 mod N
//
// See [KL 08] construction 11.32, page 414.
func (priv *PrivateKey) Decrypt(cypher *Cypher) (msg *big.Int) {
mu := new(big.Int).ModInverse(priv.Lambda, priv.N)
tmp := new(big.Int).Exp(cypher.C, priv.Lambda, priv.GetNSquare())
msg = new(big.Int).Mod(new(big.Int).Mul(L(tmp, priv.N), 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 minusOne(x *big.Int) *big.Int {
return new(big.Int).Add(x, big.NewInt(-1))
}
func computePhi(p, q *big.Int) *big.Int {
return new(big.Int).Mul(minusOne(p), minusOne(q))
}
// CreatePrivateKey generates a Paillier private key accepting two large prime
// numbers of equal length or other such that gcd(pq, (p-1)(q-1)) = 1.
//
// Algorithm is based on approach described in [KL 08], construction 11.32,
// page 414 which is compatible with one described in [DJN 10], section 3.2
// except that instead of generating Lambda private key component from LCM
// of p and q we use Euler's totient function as suggested in [KL 08].
//
// [KL 08]: Jonathan Katz, Yehuda Lindell, (2008)
// Introduction to Modern Cryptography: Principles and Protocols,
// Chapman & Hall/CRC
//
// [DJN 10]: Ivan Damgard, Mads Jurik, Jesper Buus Nielsen, (2010)
// A Generalization of Paillier’s Public-Key System
// with Applications to Electronic Voting
// Aarhus University, Dept. of Computer Science, BRICS
func CreatePrivateKey(p, q *big.Int) *PrivateKey {
n := new(big.Int).Mul(p, q)
lambda := computePhi(p, q)
return &PrivateKey{
PublicKey: PublicKey{
N: n,
},
Lambda: lambda,
}
}