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