added ECC ElGamal Encryption and Decryption

This commit is contained in:
arnaucode
2018-07-28 21:57:03 +02:00
parent a440bab76a
commit d4e05e49c3
6 changed files with 218 additions and 46 deletions

View File

@@ -6,6 +6,7 @@ import (
"math/big"
)
// EC is the data structure for the elliptic curve parameters
type EC struct {
A *big.Int
B *big.Int
@@ -40,14 +41,29 @@ func (ec *EC) At(x *big.Int) (Point, Point, error) {
return Point{x, y}, Point{x, new(big.Int).Sub(ec.Q, y)}, nil
}
// TODO add valid checker point function
// TODO add valid checker point function Valid()
// Neg returns the inverse of the P point on the elliptic curve
func (ec *EC) Neg(p Point) Point {
// TODO get error when point not found on the ec
return Point{p.X, new(big.Int).Sub(ec.Q, p.Y)}
}
// Add adds two points p1 and p2 and gets q
// Order returns smallest n where nG = O (point at zero)
func (ec *EC) Order(g Point) (int, error) {
for i := 1; i < int(ec.Q.Int64())+1; i++ {
mPoint, err := ec.Mul(g, i)
if err != nil {
return i, err
}
if mPoint.Equal(zeroPoint) {
return i, nil
}
}
return -1, errors.New("invalid order")
}
// Add adds two points p1 and p2 and gets q, returns the negate of q
func (ec *EC) Add(p1, p2 Point) (Point, error) {
if p1.Equal(zeroPoint) {
return p2, nil
@@ -69,7 +85,7 @@ func (ec *EC) Add(p1, p2 Point) (Point, error) {
numerator = new(big.Int).Add(x23, ec.A)
// 2 * y
denominator = new(big.Int).Mul(big.NewInt(int64(2)), p1.Y)
// (3 * x^2 + a) / (2 * y) mod ec.Q
// s = (3 * x^2 + a) / (2 * y) mod ec.Q
denInv := new(big.Int).ModInverse(denominator, ec.Q)
sRaw = new(big.Int).Mul(numerator, denInv)
s = new(big.Int).Mod(sRaw, ec.Q)
@@ -79,7 +95,7 @@ func (ec *EC) Add(p1, p2 Point) (Point, error) {
numerator = new(big.Int).Sub(p1.Y, p2.Y)
// x0-x1
denominator = new(big.Int).Sub(p1.X, p2.X)
// (y0-y1) / (x0-x1) mod ec.Q
// s = (y0-y1) / (x0-x1) mod ec.Q
denInv := new(big.Int).ModInverse(denominator, ec.Q)
sRaw = new(big.Int).Mul(numerator, denInv)
s = new(big.Int).Mod(sRaw, ec.Q)
@@ -104,17 +120,29 @@ func (ec *EC) Add(p1, p2 Point) (Point, error) {
// q.Y = (s(p1.X - q.X) - p1.Y) mod ec.Q
q.Y = new(big.Int).Mod(sXoX2Y, ec.Q)
// negate q
// q = ec.Neg(q)
return q, nil
}
// Mul multiplies a point n times on the elliptic curve
func (ec *EC) Mul(p Point, n int) (Point, error) {
var err error
for i := 0; i < n; i++ {
p, err = ec.Add(p, p)
if err != nil {
return zeroPoint, err
p2 := p
r := zeroPoint
for 0 < n {
if n&1 == 1 {
r, err = ec.Add(r, p2)
if err != nil {
return p, err
}
}
n = n >> 1
p2, err = ec.Add(p2, p2)
if err != nil {
return p, err
}
}
return p, nil
return r, nil
}

View File

@@ -1,51 +1,46 @@
package ecc
import (
"fmt"
"math/big"
"testing"
)
func TestECC(t *testing.T) {
ec := NewEC(0, 7, 11)
p1, p1_, err := ec.At(big.NewInt(int64(7)))
p1, p1i, err := ec.At(big.NewInt(int64(7)))
if err != nil {
t.Errorf(err.Error())
}
if !p1.Equal(Point{big.NewInt(int64(7)), big.NewInt(int64(3))}) {
t.Errorf("p1!=(7, 11)")
}
if !p1_.Equal(Point{big.NewInt(int64(7)), big.NewInt(int64(8))}) {
t.Errorf("p1_!=(7, 8)")
if !p1i.Equal(Point{big.NewInt(int64(7)), big.NewInt(int64(8))}) {
t.Errorf("p1i!=(7, 8)")
}
}
func TestNeg(t *testing.T) {
ec := NewEC(0, 7, 11)
p1, p1_, err := ec.At(big.NewInt(int64(7)))
p1, p1i, err := ec.At(big.NewInt(int64(7)))
if err != nil {
t.Errorf(err.Error())
}
p1Neg := ec.Neg(p1)
if !p1Neg.Equal(p1_) {
t.Errorf("p1Neg!=p1_")
if !p1Neg.Equal(p1i) {
t.Errorf("p1Neg!=p1i")
}
}
func TestAdd(t *testing.T) {
ec := NewEC(0, 7, 11)
p1, _, err := ec.At(big.NewInt(int64(7)))
if err != nil {
t.Errorf(err.Error())
}
p2, _, err := ec.At(big.NewInt(int64(6)))
if err != nil {
t.Errorf(err.Error())
}
p1 := Point{big.NewInt(int64(4)), big.NewInt(int64(7))}
p2 := Point{big.NewInt(int64(2)), big.NewInt(int64(2))}
q, err := ec.Add(p1, p2)
if err != nil {
t.Errorf(err.Error())
}
if !q.Equal(Point{big.NewInt(int64(2)), big.NewInt(int64(9))}) {
t.Errorf("q!=(2, 9)")
if !q.Equal(Point{big.NewInt(int64(3)), big.NewInt(int64(1))}) {
t.Errorf("q!=(3, 1)")
}
// check that q exists on the elliptic curve
@@ -61,47 +56,50 @@ func TestAdd(t *testing.T) {
func TestAddSamePoint(t *testing.T) {
ec := NewEC(0, 7, 11)
p1, p1_, err := ec.At(big.NewInt(int64(4)))
if err != nil {
t.Errorf(err.Error())
}
p1 := Point{big.NewInt(int64(4)), big.NewInt(int64(7))}
p1i := Point{big.NewInt(int64(4)), big.NewInt(int64(4))}
q, err := ec.Add(p1, p1)
if err != nil {
t.Errorf(err.Error())
}
if !q.Equal(Point{big.NewInt(int64(6)), big.NewInt(int64(6))}) {
t.Errorf("q!=(6, 6)")
if !q.Equal(Point{big.NewInt(int64(6)), big.NewInt(int64(5))}) {
t.Errorf("q!=(6, 5)")
}
q_, err := ec.Add(p1_, p1_)
q_, err := ec.Add(p1i, p1i)
if err != nil {
t.Errorf(err.Error())
}
if !q_.Equal(Point{big.NewInt(int64(6)), big.NewInt(int64(5))}) {
t.Errorf("q_!=(6, 5)")
if !q_.Equal(Point{big.NewInt(int64(6)), big.NewInt(int64(6))}) {
t.Errorf("q_!=(6, 6)")
}
}
func TestMulEqualSelfAdd(t *testing.T) {
ec := NewEC(0, 7, 11)
p1, _, err := ec.At(big.NewInt(int64(4)))
if err != nil {
t.Errorf(err.Error())
}
ec := NewEC(0, 7, 29)
p1 := Point{big.NewInt(int64(11)), big.NewInt(int64(27))}
p1p1, err := ec.Add(p1, p1)
if err != nil {
t.Errorf(err.Error())
}
q, err := ec.Mul(p1, 1)
p1p1, err = ec.Add(p1p1, p1)
if err != nil {
t.Errorf(err.Error())
}
q, err := ec.Mul(p1, 3)
if err != nil {
t.Errorf(err.Error())
}
if !q.Equal(p1p1) {
fmt.Println(q)
fmt.Println(p1p1)
t.Errorf("q!=p1*p1")
}
}
func TestMul(t *testing.T) {
ec := NewEC(0, 7, 29)
p1 := Point{big.NewInt(int64(4)), big.NewInt(int64(19))}
@@ -109,22 +107,22 @@ func TestMul(t *testing.T) {
if err != nil {
t.Errorf(err.Error())
}
if !q3.Equal(Point{big.NewInt(int64(19)), big.NewInt(int64(15))}) {
t.Errorf("q3!=(19, 15)")
if !q3.Equal(Point{big.NewInt(int64(6)), big.NewInt(int64(7))}) {
t.Errorf("q3!=(6, 7)")
}
q7, err := ec.Mul(p1, 7)
if err != nil {
t.Errorf(err.Error())
}
if !q7.Equal(Point{big.NewInt(int64(19)), big.NewInt(int64(15))}) {
t.Errorf("q7!=(19, 15)")
if !q7.Equal(Point{big.NewInt(int64(19)), big.NewInt(int64(14))}) {
t.Errorf("q7!=(19, 14)")
}
q8, err := ec.Mul(p1, 8)
if err != nil {
t.Errorf(err.Error())
}
if !q8.Equal(Point{big.NewInt(int64(4)), big.NewInt(int64(19))}) {
t.Errorf("q8!=(4, 19)")
if !q8.Equal(Point{big.NewInt(int64(19)), big.NewInt(int64(15))}) {
t.Errorf("q8!=(19, 15)")
}
}

View File

@@ -10,11 +10,13 @@ var (
zeroPoint = Point{bigZero, bigZero}
)
// Point is the data structure for a point, containing the X and Y coordinates
type Point struct {
X *big.Int
Y *big.Int
}
// Equal compares the X and Y coord of a Point and returns true if are the same
func (c1 *Point) Equal(c2 Point) bool {
if !bytes.Equal(c1.X.Bytes(), c2.X.Bytes()) {
return false