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
15type PublicKey struct {
16 N *big.Int `json:"n"`
17 G *big.Int `json:"g"`
18}
19type PrivateKey struct {
20 Lambda *big.Int `json:"lambda"`
21 Mu *big.Int `json:"mu"`
22}
23
24type Key struct {
25 PubK PublicKey
26 PrivK PrivateKey
27}
28
29func GenerateKeyPair() (key Key, err error) {
30 p, err := rand.Prime(rand.Reader, bits/2)
31 if err != nil {
32 return key, err
33 }
34 q, err := rand.Prime(rand.Reader, bits/2)
35 if err != nil {
36 return key, err
37 }
38
39 pq := new(big.Int).Mul(p, q)
40 p1q1 := big.NewInt((p.Int64() - 1) * (q.Int64() - 1))
41 gcd := new(big.Int).GCD(nil, nil, pq, p1q1)
42 if gcd.Int64() != int64(1) {
43 return key, errors.New("gcd comprovation failed")
44 }
45
46 n := new(big.Int).Mul(p, q)
47 lambda := big.NewInt(int64(Lcm(float64(p.Int64())-1, float64(q.Int64())-1)))
48
49 //g generation
50 alpha := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
51 beta := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
52 alphan := new(big.Int).Mul(alpha, n)
53 alphan1 := new(big.Int).Add(alphan, big.NewInt(1))
54 betaN := new(big.Int).Exp(beta, n, nil)
55 ab := new(big.Int).Mul(alphan1, betaN)
56 n2 := new(big.Int).Mul(n, n)
57 g := new(big.Int).Mod(ab, n2)
58 //in some Paillier implementations use this:
59 // g = new(big.Int).Add(n, big.NewInt(1))
60
61 key.PubK.N = n
62 key.PubK.G = g
63
64 //mu generation
65 Glambda := new(big.Int).Exp(g, lambda, nil)
66 u := new(big.Int).Mod(Glambda, n2)
67 L := L(u, n)
68 mu := new(big.Int).ModInverse(L, n)
69
70 key.PrivK.Lambda = lambda
71 key.PrivK.Mu = mu
72
73 return key, nil
74}
75
76func Lcm(a, b float64) float64 {
77 r := (a * b) / float64(prime.Gcd(int(a), int(b)))
78 return r
79
80}
81func L(u *big.Int, n *big.Int) *big.Int {
82 u1 := new(big.Int).Sub(u, big.NewInt(1))
83 L := new(big.Int).Div(u1, n)
84 return L
85}
86
87func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
88 gM := new(big.Int).Exp(pubK.G, m, nil)
89 r := big.NewInt(int64(prime.RandInt(0, int(pubK.N.Int64()))))
90 rN := new(big.Int).Exp(r, pubK.N, nil)
91 gMrN := new(big.Int).Mul(gM, rN)
92 n2 := new(big.Int).Mul(pubK.N, pubK.N)
93 c := new(big.Int).Mod(gMrN, n2)
94 return c
95}
96func Decrypt(c *big.Int, pubK PublicKey, privK PrivateKey) *big.Int {
97 cLambda := new(big.Int).Exp(c, privK.Lambda, nil)
98 n2 := new(big.Int).Mul(pubK.N, pubK.N)
99 u := new(big.Int).Mod(cLambda, n2)
100 L := L(u, pubK.N)
101 LMu := new(big.Int).Mul(L, privK.Mu)
102 m := new(big.Int).Mod(LMu, pubK.N)
103 return m
104}
105
106func HomomorphicAddition(c1 *big.Int, c2 *big.Int, pubK PublicKey) *big.Int {
107 c1c2 := new(big.Int).Mul(c1, c2)
108 n2 := new(big.Int).Mul(pubK.N, pubK.N)
109 d := new(big.Int).Mod(c1c2, n2)
110 return d
111}