arnaucube
arnaucube/cryptofunPublic Self-hosted repository
cryptofun/elgamal/elgamal.go
elgamal/elgamal.goRaw
 1package elgamal
 2
 3import (
 4	"math/big"
 5
 6	"github.com/arnaucube/cryptofun/ecc"
 7)
 8
 9// EG is the ElGamal data structure
10type EG struct {
11	EC ecc.EC
12	G  ecc.Point
13	N  *big.Int
14}
15
16// NewEG defines a new EG data structure
17func NewEG(ec ecc.EC, g ecc.Point) (EG, error) {
18	var eg EG
19	var err error
20	eg.EC = ec
21	eg.G = g
22	eg.N, err = ec.Order(g)
23	return eg, err
24}
25
26// PubK returns the public key Point calculated from the private key over the elliptic curve
27func (eg EG) PubK(privK *big.Int) (ecc.Point, error) {
28	// privK: rand < ec.Q
29	privKCopy := new(big.Int).SetBytes(privK.Bytes())
30	pubK, err := eg.EC.Mul(eg.G, privKCopy)
31	return pubK, err
32}
33
34// Encrypt encrypts a point m with the public key point, returns two points
35func (eg EG) Encrypt(m ecc.Point, pubK ecc.Point, r *big.Int) ([2]ecc.Point, error) {
36	rCopy := new(big.Int).SetBytes(r.Bytes())
37	p1, err := eg.EC.Mul(eg.G, rCopy)
38	if err != nil {
39		return [2]ecc.Point{}, err
40	}
41	rCopy = new(big.Int).SetBytes(r.Bytes())
42	p2, err := eg.EC.Mul(pubK, rCopy)
43	if err != nil {
44		return [2]ecc.Point{}, err
45	}
46	p3, err := eg.EC.Add(m, p2)
47	if err != nil {
48		return [2]ecc.Point{}, err
49	}
50	c := [2]ecc.Point{p1, p3}
51	return c, err
52}
53
54// Decrypt decrypts c (two points) with the private key, returns the point decrypted
55func (eg EG) Decrypt(c [2]ecc.Point, privK *big.Int) (ecc.Point, error) {
56	c1 := c[0]
57	c2 := c[1]
58	privKCopy := new(big.Int).SetBytes(privK.Bytes())
59	c1PrivK, err := eg.EC.Mul(c1, privKCopy)
60	if err != nil {
61		return ecc.Point{}, err
62	}
63	c1PrivKNeg := eg.EC.Neg(c1PrivK)
64	d, err := eg.EC.Add(c2, c1PrivKNeg)
65	return d, err
66}