package elgamal import ( "math/big" "github.com/arnaucube/cryptofun/ecc" ) // EG is the ElGamal data structure type EG struct { EC ecc.EC G ecc.Point N *big.Int } // NewEG defines a new EG data structure func NewEG(ec ecc.EC, g ecc.Point) (EG, error) { var eg EG var err error eg.EC = ec eg.G = g eg.N, err = ec.Order(g) return eg, err } // PubK returns the public key Point calculated from the private key over the elliptic curve func (eg EG) PubK(privK *big.Int) (ecc.Point, error) { // privK: rand < ec.Q privKCopy := new(big.Int).SetBytes(privK.Bytes()) pubK, err := eg.EC.Mul(eg.G, privKCopy) return pubK, err } // Encrypt encrypts a point m with the public key point, returns two points func (eg EG) Encrypt(m ecc.Point, pubK ecc.Point, r *big.Int) ([2]ecc.Point, error) { rCopy := new(big.Int).SetBytes(r.Bytes()) p1, err := eg.EC.Mul(eg.G, rCopy) if err != nil { return [2]ecc.Point{}, err } rCopy = new(big.Int).SetBytes(r.Bytes()) p2, err := eg.EC.Mul(pubK, rCopy) if err != nil { return [2]ecc.Point{}, err } p3, err := eg.EC.Add(m, p2) if err != nil { return [2]ecc.Point{}, err } c := [2]ecc.Point{p1, p3} return c, err } // Decrypt decrypts c (two points) with the private key, returns the point decrypted func (eg EG) Decrypt(c [2]ecc.Point, privK *big.Int) (ecc.Point, error) { c1 := c[0] c2 := c[1] privKCopy := new(big.Int).SetBytes(privK.Bytes()) c1PrivK, err := eg.EC.Mul(c1, privKCopy) if err != nil { return ecc.Point{}, err } c1PrivKNeg := eg.EC.Neg(c1PrivK) d, err := eg.EC.Add(c2, c1PrivKNeg) return d, err }