From 151ca78806d3a20aa9773c7ec930ded576a37167 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sun, 7 Oct 2018 00:16:23 +0200 Subject: [PATCH] bn128 finite fields operations --- README.md | 13 ++ bn128/fq.go | 74 ++++++++ bn128/fq12.go | 118 +++++++++++++ bn128/fq2.go | 110 ++++++++++++ bn128/fq6.go | 150 ++++++++++++++++ bn128/fqn_test.go | 190 +++++++++++++++++++++ ecc/ecc.go | 32 ++-- ecc/ecc_test.go | 20 +-- ecc/point.go | 12 +- ecdsa/ecdsa_test.go | 4 +- elgamal/elgamal_test.go | 6 +- schnorr/schnorr_test.go | 18 +- shamirsecretsharing/shamirsecretsharing.go | 2 +- utils/utils.go | 17 ++ 14 files changed, 712 insertions(+), 54 deletions(-) create mode 100644 bn128/fq.go create mode 100644 bn128/fq12.go create mode 100644 bn128/fq2.go create mode 100644 bn128/fq6.go create mode 100644 bn128/fqn_test.go create mode 100644 utils/utils.go diff --git a/README.md b/README.md index 1cfc130..425cd8e 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,19 @@ https://en.wikipedia.org/wiki/Schnorr_signature - [x] Sign - [x] Verify signature + +## Bn128 +**[not finished]** + +This is implemented followng the implementations and info from: +- https://github.com/iden3/zksnark +- https://github.com/zcash/zcash/tree/master/src/snark +- `Multiplication and Squaring on Pairing-Friendly +Fields`, Augusto Jun Devegili, Colm Ó hÉigeartaigh, Michael Scott, and Ricardo Dahab https://pdfs.semanticscholar.org/3e01/de88d7428076b2547b60072088507d881bf1.pdf +- `Optimal Pairings`, Frederik Vercauteren https://www.cosic.esat.kuleuven.be/bcrypt/optimal.pdf + +- [x] Fq, Fq2, Fq6, Fq12 operations + --- To run all tests: diff --git a/bn128/fq.go b/bn128/fq.go new file mode 100644 index 0000000..630b56c --- /dev/null +++ b/bn128/fq.go @@ -0,0 +1,74 @@ +package bn128 + +import ( + "math/big" +) + +// Fq is the Z field over modulus Q +type Fq struct { + Q *big.Int // Q +} + +// NewFq generates a new Fq +func NewFq(q *big.Int) Fq { + return Fq{ + q, + } +} + +// Zero returns a Zero value on the Fq +func (fq Fq) Zero() *big.Int { + return big.NewInt(int64(0)) +} + +// One returns a One value on the Fq +func (fq Fq) One() *big.Int { + return big.NewInt(int64(1)) +} + +// Add performs an addition on the Fq +func (fq Fq) Add(a, b *big.Int) *big.Int { + sum := new(big.Int).Add(a, b) + return new(big.Int).Mod(sum, fq.Q) +} + +// Double performs a doubling on the Fq +func (fq Fq) Double(a *big.Int) *big.Int { + sum := new(big.Int).Add(a, a) + return new(big.Int).Mod(sum, fq.Q) +} + +// Sub performs a substraction on the Fq +func (fq Fq) Sub(a, b *big.Int) *big.Int { + sum := new(big.Int).Sub(a, b) + return new(big.Int).Mod(sum, fq.Q) +} + +// Neg performs a negation on the Fq +func (fq Fq) Neg(a *big.Int) *big.Int { + m := new(big.Int).Neg(a) + return new(big.Int).Mod(m, fq.Q) +} + +// Mul performs a multiplication on the Fq +func (fq Fq) Mul(a, b *big.Int) *big.Int { + m := new(big.Int).Mul(a, b) + return new(big.Int).Mod(m, fq.Q) +} + +// Inverse returns the inverse on the Fq +func (fq Fq) Inverse(a *big.Int) *big.Int { + return new(big.Int).ModInverse(a, fq.Q) +} + +// Div performs a division on the Fq +func (fq Fq) Div(a, b *big.Int) *big.Int { + // not used in fq1, method added to fit the interface + return a +} + +// Square performs a square operation on the Fq +func (fq Fq) Square(a *big.Int) *big.Int { + m := new(big.Int).Mul(a, a) + return new(big.Int).Mod(m, fq.Q) +} diff --git a/bn128/fq12.go b/bn128/fq12.go new file mode 100644 index 0000000..80d6131 --- /dev/null +++ b/bn128/fq12.go @@ -0,0 +1,118 @@ +package bn128 + +import ( + "math/big" +) + +// Fq12 uses the same algorithms than Fq2, but with [2][3][2]*big.Int data structure + +// Fq12 is Field 12 +type Fq12 struct { + F Fq6 + Fq2 Fq2 + NonResidue [2]*big.Int +} + +// NewFq12 generates a new Fq12 +func NewFq12(f Fq6, fq2 Fq2, nonResidue [2]*big.Int) Fq12 { + fq12 := Fq12{ + f, + fq2, + nonResidue, + } + return fq12 +} + +// Zero returns a Zero value on the Fq12 +func (fq12 Fq12) Zero() [2][3][2]*big.Int { + return [2][3][2]*big.Int{fq12.F.Zero(), fq12.F.Zero()} +} + +// One returns a One value on the Fq12 +func (fq12 Fq12) One() [2][3][2]*big.Int { + return [2][3][2]*big.Int{fq12.F.One(), fq12.F.One()} +} + +func (fq12 Fq12) mulByNonResidue(a [3][2]*big.Int) [3][2]*big.Int { + return [3][2]*big.Int{ + fq12.Fq2.Mul(fq12.NonResidue, a[2]), + a[0], + a[1], + } +} + +// Add performs an addition on the Fq12 +func (fq12 Fq12) Add(a, b [2][3][2]*big.Int) [2][3][2]*big.Int { + return [2][3][2]*big.Int{ + fq12.F.Add(a[0], b[0]), + fq12.F.Add(a[1], b[1]), + } +} + +// Double performs a doubling on the Fq12 +func (fq12 Fq12) Double(a [2][3][2]*big.Int) [2][3][2]*big.Int { + return fq12.Add(a, a) +} + +// Sub performs a substraction on the Fq12 +func (fq12 Fq12) Sub(a, b [2][3][2]*big.Int) [2][3][2]*big.Int { + return [2][3][2]*big.Int{ + fq12.F.Sub(a[0], b[0]), + fq12.F.Sub(a[1], b[1]), + } +} + +// Neg performs a negation on the Fq12 +func (fq12 Fq12) Neg(a [2][3][2]*big.Int) [2][3][2]*big.Int { + return fq12.Sub(fq12.Zero(), a) +} + +// Mul performs a multiplication on the Fq12 +func (fq12 Fq12) Mul(a, b [2][3][2]*big.Int) [2][3][2]*big.Int { + // Multiplication and Squaring on Pairing-Friendly [2]*big.Ints.pdf; Section 3 (Karatsuba) + v0 := fq12.F.Mul(a[0], b[0]) + v1 := fq12.F.Mul(a[1], b[1]) + return [2][3][2]*big.Int{ + fq12.F.Add(v0, fq12.mulByNonResidue(v1)), + fq12.F.Sub( + fq12.F.Mul( + fq12.F.Add(a[0], a[1]), + fq12.F.Add(b[0], b[1])), + fq12.F.Add(v0, v1)), + } +} + +// Inverse returns the inverse on the Fq12 +func (fq12 Fq12) Inverse(a [2][3][2]*big.Int) [2][3][2]*big.Int { + t0 := fq12.F.Square(a[0]) + t1 := fq12.F.Square(a[1]) + t2 := fq12.F.Sub(t0, fq12.mulByNonResidue(t1)) + t3 := fq12.F.Inverse(t2) + return [2][3][2]*big.Int{ + fq12.F.Mul(a[0], t3), + fq12.F.Neg(fq12.F.Mul(a[1], t3)), + } +} + +// Div performs a division on the Fq12 +func (fq12 Fq12) Div(a, b [2][3][2]*big.Int) [2][3][2]*big.Int { + return fq12.Mul(a, fq12.Inverse(b)) +} + +// Square performs a square operation on the Fq12 +func (fq12 Fq12) Square(a [2][3][2]*big.Int) [2][3][2]*big.Int { + ab := fq12.F.Mul(a[0], a[1]) + + return [2][3][2]*big.Int{ + fq12.F.Sub( + fq12.F.Mul( + fq12.F.Add(a[0], a[1]), + fq12.F.Add( + a[0], + fq12.mulByNonResidue(a[1]))), + fq12.F.Add( + ab, + fq12.mulByNonResidue(ab))), + fq12.F.Add(ab, ab), + } +} diff --git a/bn128/fq2.go b/bn128/fq2.go new file mode 100644 index 0000000..66d76a1 --- /dev/null +++ b/bn128/fq2.go @@ -0,0 +1,110 @@ +package bn128 + +import ( + "math/big" +) + +// Fq2 is Field 2 +type Fq2 struct { + F Fq + NonResidue *big.Int +} + +// NewFq2 generates a new Fq2 +func NewFq2(f Fq, nonResidue *big.Int) Fq2 { + fq2 := Fq2{ + f, + nonResidue, + } + return fq2 +} + +// Zero returns a Zero value on the Fq2 +func (fq2 Fq2) Zero() [2]*big.Int { + return [2]*big.Int{fq2.F.Zero(), fq2.F.Zero()} +} + +// One returns a One value on the Fq2 +func (fq2 Fq2) One() [2]*big.Int { + return [2]*big.Int{fq2.F.One(), fq2.F.One()} +} + +func (fq2 Fq2) mulByNonResidue(a *big.Int) *big.Int { + return fq2.F.Mul(fq2.NonResidue, a) +} + +// Add performs an addition on the Fq2 +func (fq2 Fq2) Add(a, b [2]*big.Int) [2]*big.Int { + return [2]*big.Int{ + fq2.F.Add(a[0], b[0]), + fq2.F.Add(a[1], b[1]), + } +} + +// Double performs a doubling on the Fq2 +func (fq2 Fq2) Double(a [2]*big.Int) [2]*big.Int { + return fq2.Add(a, a) +} + +// Sub performs a substraction on the Fq2 +func (fq2 Fq2) Sub(a, b [2]*big.Int) [2]*big.Int { + return [2]*big.Int{ + fq2.F.Sub(a[0], b[0]), + fq2.F.Sub(a[1], b[1]), + } +} + +// Neg performs a negation on the Fq2 +func (fq2 Fq2) Neg(a [2]*big.Int) [2]*big.Int { + return fq2.Sub(fq2.Zero(), a) +} + +// Mul performs a multiplication on the Fq2 +func (fq2 Fq2) Mul(a, b [2]*big.Int) [2]*big.Int { + // Multiplication and Squaring on Pairing-Friendly.pdf; Section 3 (Karatsuba) + v0 := fq2.F.Mul(a[0], b[0]) + v1 := fq2.F.Mul(a[1], b[1]) + return [2]*big.Int{ + fq2.F.Add(v0, fq2.mulByNonResidue(v1)), + fq2.F.Sub( + fq2.F.Mul( + fq2.F.Add(a[0], a[1]), + fq2.F.Add(b[0], b[1])), + fq2.F.Add(v0, v1)), + } +} + +// Inverse returns the inverse on the Fq2 +func (fq2 Fq2) Inverse(a [2]*big.Int) [2]*big.Int { + t0 := fq2.F.Square(a[0]) + t1 := fq2.F.Square(a[1]) + t2 := fq2.F.Sub(t0, fq2.mulByNonResidue(t1)) + t3 := fq2.F.Inverse(t2) + return [2]*big.Int{ + fq2.F.Mul(a[0], t3), + fq2.F.Neg(fq2.F.Mul(a[1], t3)), + } +} + +// Div performs a division on the Fq2 +func (fq2 Fq2) Div(a, b [2]*big.Int) [2]*big.Int { + return fq2.Mul(a, fq2.Inverse(b)) +} + +// Square performs a square operation on the Fq2 +func (fq2 Fq2) Square(a [2]*big.Int) [2]*big.Int { + ab := fq2.F.Mul(a[0], a[1]) + + return [2]*big.Int{ + fq2.F.Sub( + fq2.F.Mul( + fq2.F.Add(a[0], a[1]), + fq2.F.Add( + a[0], + fq2.mulByNonResidue(a[1]))), + fq2.F.Add( + ab, + fq2.mulByNonResidue(ab))), + fq2.F.Add(ab, ab), + } +} diff --git a/bn128/fq6.go b/bn128/fq6.go new file mode 100644 index 0000000..90e7b4a --- /dev/null +++ b/bn128/fq6.go @@ -0,0 +1,150 @@ +package bn128 + +import ( + "math/big" +) + +// Fq6 is Field 6 +type Fq6 struct { + F Fq2 + NonResidue [2]*big.Int +} + +// NewFq6 generates a new Fq6 +func NewFq6(f Fq2, nonResidue [2]*big.Int) Fq6 { + fq6 := Fq6{ + f, + nonResidue, + } + return fq6 +} + +// Zero returns a Zero value on the Fq6 +func (fq6 Fq6) Zero() [3][2]*big.Int { + return [3][2]*big.Int{fq6.F.Zero(), fq6.F.Zero(), fq6.F.Zero()} +} + +// One returns a One value on the Fq6 +func (fq6 Fq6) One() [3][2]*big.Int { + return [3][2]*big.Int{fq6.F.One(), fq6.F.One(), fq6.F.One()} +} + +func (fq6 Fq6) mulByNonResidue(a [2]*big.Int) [2]*big.Int { + return fq6.F.Mul(fq6.NonResidue, a) +} + +// Add performs an addition on the Fq6 +func (fq6 Fq6) Add(a, b [3][2]*big.Int) [3][2]*big.Int { + return [3][2]*big.Int{ + fq6.F.Add(a[0], b[0]), + fq6.F.Add(a[1], b[1]), + fq6.F.Add(a[2], b[2]), + } +} + +// Sub performs a substraction on the Fq6 +func (fq6 Fq6) Sub(a, b [3][2]*big.Int) [3][2]*big.Int { + return [3][2]*big.Int{ + fq6.F.Sub(a[0], b[0]), + fq6.F.Sub(a[1], b[1]), + fq6.F.Sub(a[2], b[2]), + } +} + +// Neg performs a negation on the Fq6 +func (fq6 Fq6) Neg(a [3][2]*big.Int) [3][2]*big.Int { + return fq6.Sub(fq6.Zero(), a) +} + +// Mul performs a multiplication on the Fq6 +func (fq6 Fq6) Mul(a, b [3][2]*big.Int) [3][2]*big.Int { + v0 := fq6.F.Mul(a[0], b[0]) + v1 := fq6.F.Mul(a[1], b[1]) + v2 := fq6.F.Mul(a[2], b[2]) + return [3][2]*big.Int{ + fq6.F.Add( + v0, + fq6.mulByNonResidue( + fq6.F.Sub( + fq6.F.Mul( + fq6.F.Add(a[1], a[2]), + fq6.F.Add(b[1], b[2])), + fq6.F.Add(v1, v2)))), + + fq6.F.Add( + fq6.F.Sub( + fq6.F.Mul( + fq6.F.Add(a[0], a[1]), + fq6.F.Add(b[0], b[1])), + fq6.F.Add(v0, v1)), + fq6.mulByNonResidue(v2)), + + fq6.F.Add( + fq6.F.Sub( + fq6.F.Mul( + fq6.F.Add(a[0], a[2]), + fq6.F.Add(b[0], b[2])), + fq6.F.Add(v0, v2)), + v1), + } +} + +// Inverse returns the inverse on the Fq6 +func (fq6 Fq6) Inverse(a [3][2]*big.Int) [3][2]*big.Int { + t0 := fq6.F.Square(a[0]) + t1 := fq6.F.Square(a[1]) + t2 := fq6.F.Square(a[2]) + t3 := fq6.F.Mul(a[0], a[1]) + t4 := fq6.F.Mul(a[0], a[2]) + t5 := fq6.F.Mul(a[1], a[2]) + + c0 := fq6.F.Sub(t0, fq6.mulByNonResidue(t5)) + c1 := fq6.F.Sub(fq6.mulByNonResidue(t2), t3) + c2 := fq6.F.Sub(t1, t4) + + t6 := fq6.F.Inverse( + fq6.F.Add( + fq6.F.Mul(a[0], c0), + fq6.mulByNonResidue( + fq6.F.Add( + fq6.F.Mul(a[2], c1), + fq6.F.Mul(a[1], c2))))) + return [3][2]*big.Int{ + fq6.F.Mul(t6, c0), + fq6.F.Mul(t6, c1), + fq6.F.Mul(t6, c2), + } +} + +// Div performs a division on the Fq6 +func (fq6 Fq6) Div(a, b [3][2]*big.Int) [3][2]*big.Int { + return fq6.Mul(a, fq6.Inverse(b)) +} + +// Square performs a square operation on the Fq6 +func (fq6 Fq6) Square(a [3][2]*big.Int) [3][2]*big.Int { + s0 := fq6.F.Square(a[0]) + ab := fq6.F.Mul(a[0], a[1]) + s1 := fq6.F.Add(ab, ab) + s2 := fq6.F.Square( + fq6.F.Add( + fq6.F.Sub(a[0], a[1]), + a[2])) + bc := fq6.F.Mul(a[1], a[2]) + s3 := fq6.F.Add(bc, bc) + s4 := fq6.F.Square(a[2]) + + return [3][2]*big.Int{ + fq6.F.Add( + s0, + fq6.mulByNonResidue(s3)), + fq6.F.Add( + s1, + fq6.mulByNonResidue(s4)), + fq6.F.Sub( + fq6.F.Add( + fq6.F.Add(s1, s2), + s3), + fq6.F.Add(s0, s4)), + } +} diff --git a/bn128/fqn_test.go b/bn128/fqn_test.go new file mode 100644 index 0000000..3f17673 --- /dev/null +++ b/bn128/fqn_test.go @@ -0,0 +1,190 @@ +package bn128 + +import ( + "math/big" + "testing" + + "github.com/stretchr/testify/assert" +) + +func iToBig(a int) *big.Int { + return big.NewInt(int64(a)) +} + +func iiToBig(a, b int) [2]*big.Int { + return [2]*big.Int{iToBig(a), iToBig(b)} +} + +func iiiToBig(a, b int) [2]*big.Int { + return [2]*big.Int{iToBig(a), iToBig(b)} +} + +func TestFq1(t *testing.T) { + fq1 := NewFq(iToBig(7)) + + res := fq1.Add(iToBig(4), iToBig(4)) + assert.Equal(t, iToBig(1), res) + + res = fq1.Double(iToBig(5)) + assert.Equal(t, iToBig(3), res) + + res = fq1.Sub(iToBig(5), iToBig(7)) + assert.Equal(t, iToBig(5), res) + + res = fq1.Neg(iToBig(5)) + assert.Equal(t, iToBig(2), res) + + res = fq1.Mul(iToBig(5), iToBig(11)) + assert.Equal(t, iToBig(6), res) + + res = fq1.Inverse(iToBig(4)) + assert.Equal(t, iToBig(2), res) + + res = fq1.Square(iToBig(5)) + assert.Equal(t, iToBig(4), res) +} + +func TestFq2(t *testing.T) { + fq1 := NewFq(iToBig(7)) + nonResidueFq2str := "-1" // i / Beta + nonResidueFq2, ok := new(big.Int).SetString(nonResidueFq2str, 10) + assert.True(t, ok) + assert.Equal(t, nonResidueFq2.String(), nonResidueFq2str) + + fq2 := Fq2{fq1, nonResidueFq2} + + res := fq2.Add(iiToBig(4, 4), iiToBig(3, 4)) + assert.Equal(t, iiToBig(0, 1), res) + + res = fq2.Double(iiToBig(5, 3)) + assert.Equal(t, iiToBig(3, 6), res) + + res = fq2.Sub(iiToBig(5, 3), iiToBig(7, 2)) + assert.Equal(t, iiToBig(5, 1), res) + + res = fq2.Neg(iiToBig(4, 4)) + assert.Equal(t, iiToBig(3, 3), res) + + res = fq2.Mul(iiToBig(4, 4), iiToBig(3, 4)) + assert.Equal(t, iiToBig(3, 0), res) + + res = fq2.Inverse(iiToBig(4, 4)) + assert.Equal(t, iiToBig(1, 6), res) + + res = fq2.Div(iiToBig(4, 4), iiToBig(3, 4)) + assert.Equal(t, iiToBig(0, 6), res) + + res = fq2.Square(iiToBig(4, 4)) + assert.Equal(t, iiToBig(0, 4), res) + res2 := fq2.Mul(iiToBig(4, 4), iiToBig(4, 4)) + assert.Equal(t, res, res2) + + res = fq2.Square(iiToBig(3, 5)) + assert.Equal(t, iiToBig(5, 2), res) + res2 = fq2.Mul(iiToBig(3, 5), iiToBig(3, 5)) + assert.Equal(t, res, res2) +} + +func TestFq6(t *testing.T) { + fq1 := NewFq(big.NewInt(int64(7))) + nonResidueFq2, ok := new(big.Int).SetString("-1", 10) // i + assert.True(t, ok) + nonResidueFq6 := iiToBig(9, 1) // TODO + + fq2 := Fq2{fq1, nonResidueFq2} + fq6 := Fq6{fq2, nonResidueFq6} + a := [3][2]*big.Int{ + iiToBig(1, 2), + iiToBig(3, 4), + iiToBig(5, 6)} + b := [3][2]*big.Int{ + iiToBig(12, 11), + iiToBig(10, 9), + iiToBig(8, 7)} + + res := fq6.Add(a, b) + assert.Equal(t, + [3][2]*big.Int{ + iiToBig(6, 6), + iiToBig(6, 6), + iiToBig(6, 6)}, + res) + + res = fq6.Sub(a, b) + assert.Equal(t, + [3][2]*big.Int{ + iiToBig(3, 5), + iiToBig(0, 2), + iiToBig(4, 6)}, + res) + + res = fq6.Mul(a, b) + assert.Equal(t, + [3][2]*big.Int{ + iiToBig(5, 0), + iiToBig(2, 1), + iiToBig(3, 0)}, + res) + + mulRes := fq6.Mul(a, b) + divRes := fq6.Div(mulRes, b) + assert.Equal(t, a, divRes) +} + +func TestFq12(t *testing.T) { + q, ok := new(big.Int).SetString("21888242871839275222246405745257275088696311157297823662689037894645226208583", 10) // i + assert.True(t, ok) + fq1 := NewFq(q) + nonResidueFq2, ok := new(big.Int).SetString("21888242871839275222246405745257275088696311157297823662689037894645226208582", 10) // i + assert.True(t, ok) + nonResidueFq6 := iiToBig(9, 1) + + fq2 := Fq2{fq1, nonResidueFq2} + fq6 := Fq6{fq2, nonResidueFq6} + fq12 := Fq12{fq6, fq2, nonResidueFq6} + + a := [2][3][2]*big.Int{ + { + iiToBig(1, 2), + iiToBig(3, 4), + iiToBig(5, 6), + }, + { + iiToBig(7, 8), + iiToBig(9, 10), + iiToBig(11, 12), + }, + } + b := [2][3][2]*big.Int{ + { + iiToBig(12, 11), + iiToBig(10, 9), + iiToBig(8, 7), + }, + { + iiToBig(6, 5), + iiToBig(4, 3), + iiToBig(2, 1), + }, + } + + res := fq12.Add(a, b) + assert.Equal(t, + [2][3][2]*big.Int{ + { + iiToBig(13, 13), + iiToBig(13, 13), + iiToBig(13, 13), + }, + { + iiToBig(13, 13), + iiToBig(13, 13), + iiToBig(13, 13), + }, + }, + res) + + mulRes := fq12.Mul(a, b) + divRes := fq12.Div(mulRes, b) + assert.Equal(t, a, divRes) +} diff --git a/ecc/ecc.go b/ecc/ecc.go index 4195326..f196248 100644 --- a/ecc/ecc.go +++ b/ecc/ecc.go @@ -14,10 +14,10 @@ type EC struct { } // NewEC (y^2 = x^3 + ax + b) mod q, where q is a prime number -func NewEC(a, b, q int) (ec EC) { - ec.A = big.NewInt(int64(a)) - ec.B = big.NewInt(int64(b)) - ec.Q = big.NewInt(int64(q)) +func NewEC(a, b, q *big.Int) (ec EC) { + ec.A = a + ec.B = b + ec.Q = q return ec } @@ -51,16 +51,16 @@ func (ec *EC) Neg(p Point) Point { // 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) { + if p1.Equal(ZeroPoint) { return p2, nil } - if p2.Equal(zeroPoint) { + if p2.Equal(ZeroPoint) { return p1, nil } var numerator, denominator, sRaw, s *big.Int - if bytes.Equal(p1.X.Bytes(), p2.X.Bytes()) && (!bytes.Equal(p1.Y.Bytes(), p2.Y.Bytes()) || bytes.Equal(p1.Y.Bytes(), bigZero.Bytes())) { - return zeroPoint, nil + if bytes.Equal(p1.X.Bytes(), p2.X.Bytes()) && (!bytes.Equal(p1.Y.Bytes(), p2.Y.Bytes()) || bytes.Equal(p1.Y.Bytes(), BigZero.Bytes())) { + return ZeroPoint, nil } else if bytes.Equal(p1.X.Bytes(), p2.X.Bytes()) { // use tangent as slope // x^2 @@ -115,10 +115,10 @@ func (ec *EC) Add(p1, p2 Point) (Point, error) { func (ec *EC) Mul(p Point, n *big.Int) (Point, error) { var err error p2 := p - r := zeroPoint - for bigZero.Cmp(n) == -1 { // 0 0 { return nil, errors.New("Error: need k