arnaucube
arnaucube/cryptofunPublic Self-hosted repository
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 = 18
 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}