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)
 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}