cryptofun/paillier/paillier.go
paillier/paillier.goRaw
1package paillier
2
3import (
4 "crypto/rand"
5 "errors"
6 "math/big"
7
8 prime "../prime"
9)
10
11const (
12 bits = 16
13)
14
15// PublicKey stores the public key data
16type PublicKey struct {
17 N *big.Int `json:"n"`
18 G *big.Int `json:"g"`
19}
20
21// PrivateKey stores the private key data
22type PrivateKey struct {
23 Lambda *big.Int `json:"lambda"`
24 Mu *big.Int `json:"mu"`
25}
26
27// Key stores the public and private key data
28type Key struct {
29 PubK PublicKey
30 PrivK PrivateKey
31}
32
33// GenerateKeyPair generates a random private and public key
34func GenerateKeyPair() (key Key, err error) {
35 p, err := rand.Prime(rand.Reader, bits/2)
36 if err != nil {
37 return key, err
38 }
39 q, err := rand.Prime(rand.Reader, bits/2)
40 if err != nil {
41 return key, err
42 }
43
44 pq := new(big.Int).Mul(p, q)
45 p1q1 := big.NewInt((p.Int64() - 1) * (q.Int64() - 1))
46 gcd := new(big.Int).GCD(nil, nil, pq, p1q1)
47 if gcd.Int64() != int64(1) {
48 return key, errors.New("gcd comprovation failed")
49 }
50
51 n := new(big.Int).Mul(p, q)
52 lambda := big.NewInt(int64(lcm(float64(p.Int64())-1, float64(q.Int64())-1)))
53
54 //g generation
55 alpha := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
56 beta := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
57 alphan := new(big.Int).Mul(alpha, n)
58 alphan1 := new(big.Int).Add(alphan, big.NewInt(1))
59 betaN := new(big.Int).Exp(beta, n, nil)
60 ab := new(big.Int).Mul(alphan1, betaN)
61 n2 := new(big.Int).Mul(n, n)
62 g := new(big.Int).Mod(ab, n2)
63 //in some Paillier implementations use this:
64 // g = new(big.Int).Add(n, big.NewInt(1))
65
66 key.PubK.N = n
67 key.PubK.G = g
68
69 //mu generation
70 Glambda := new(big.Int).Exp(g, lambda, nil)
71 u := new(big.Int).Mod(Glambda, n2)
72 L := l(u, n)
73 mu := new(big.Int).ModInverse(L, n)
74
75 key.PrivK.Lambda = lambda
76 key.PrivK.Mu = mu
77
78 return key, nil
79}
80
81func lcm(a, b float64) float64 {
82 r := (a * b) / float64(prime.Gcd(int(a), int(b)))
83 return r
84
85}
86func l(u *big.Int, n *big.Int) *big.Int {
87 u1 := new(big.Int).Sub(u, big.NewInt(1))
88 L := new(big.Int).Div(u1, n)
89 return L
90}
91
92// Encrypt encrypts a message m with given PublicKey
93func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
94 gM := new(big.Int).Exp(pubK.G, m, nil)
95 r := big.NewInt(int64(prime.RandInt(0, int(pubK.N.Int64()))))
96 rN := new(big.Int).Exp(r, pubK.N, nil)
97 gMrN := new(big.Int).Mul(gM, rN)
98 n2 := new(big.Int).Mul(pubK.N, pubK.N)
99 c := new(big.Int).Mod(gMrN, n2)
100 return c
101}
102
103// Decrypt deencrypts a ciphertext c with given PublicKey and PrivateKey
104func Decrypt(c *big.Int, pubK PublicKey, privK PrivateKey) *big.Int {
105 cLambda := new(big.Int).Exp(c, privK.Lambda, nil)
106 n2 := new(big.Int).Mul(pubK.N, pubK.N)
107 u := new(big.Int).Mod(cLambda, n2)
108 L := l(u, pubK.N)
109 LMu := new(big.Int).Mul(L, privK.Mu)
110 m := new(big.Int).Mod(LMu, pubK.N)
111 return m
112}
113
114// HomomorphicAddition calculates the addition of tow encrypted values given a PublicKey
115func HomomorphicAddition(c1 *big.Int, c2 *big.Int, pubK PublicKey) *big.Int {
116 c1c2 := new(big.Int).Mul(c1, c2)
117 n2 := new(big.Int).Mul(pubK.N, pubK.N)
118 d := new(big.Int).Mod(c1c2, n2)
119 return d
120}