diff --git a/internal/edwards25519/edwards25519.go b/internal/edwards25519/edwards25519.go index ff5f3be..e03c641 100644 --- a/internal/edwards25519/edwards25519.go +++ b/internal/edwards25519/edwards25519.go @@ -107,6 +107,14 @@ func (v *ProjP3) FromP1xP1(p *ProjP1xP1) *ProjP3 { return v } +func (v *ProjP3) FromP2(p *ProjP2) *ProjP3 { + v.X.Mul(&p.X, &p.Z) + v.Y.Mul(&p.Y, &p.Z) + v.Z.Square(&p.Z) + v.T.Mul(&p.X, &p.Y) + return v +} + func (v *ProjCached) FromP3(p *ProjP3) *ProjCached { v.YplusX.Add(&p.Y, &p.X) v.YminusX.Sub(&p.Y, &p.X) @@ -232,6 +240,26 @@ func (v *ProjP1xP1) Double(p *ProjP2) *ProjP1xP1 { return v } +func (v *ProjP3) Neg(p *ProjP3) *ProjP3 { + v.X.Neg(&p.X) + v.Y.Set(&p.Y) + v.Z.Set(&p.Z) + v.T.Neg(&p.T) + return v +} + +// by @ebfull +// https://github.com/dalek-cryptography/curve25519-dalek/pull/226/files +func (v *ProjP3) Equal(u *ProjP3) int { + var t1, t2, t3, t4 radix51.FieldElement + t1.Mul(&v.X, &u.Z) + t2.Mul(&u.X, &v.Z) + t3.Mul(&v.Y, &u.Z) + t4.Mul(&u.Y, &v.Z) + + return t1.Equal(&t2) & t3.Equal(&t4) +} + // From EFD https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html // An elliptic curve in twisted Edwards form has parameters a, d and coordinates // x, y satisfying the following equations: diff --git a/internal/edwards25519/edwards25519_test.go b/internal/edwards25519/edwards25519_test.go index 93a7fba..5422ea3 100644 --- a/internal/edwards25519/edwards25519_test.go +++ b/internal/edwards25519/edwards25519_test.go @@ -36,3 +36,49 @@ func TestAddSubNegOnBasePoint(t *testing.T) { t.Error("B + (-B) != 0") } } + +func TestAddSubNegOnBasePoint2(t *testing.T) { + + var B, Bneg ProjP3 + var tmpP2 ProjP2 + var tmpP1xP1 ProjP1xP1 + var tmpCached ProjCached + + B = ProjP3{ + X: radix51.FieldElement([5]uint64{426475514619346, 2063872706840040, 14628272888959, 107677749330612, 288339085807592}), + Y: radix51.FieldElement([5]uint64{1934594822876571, 2049809580636559, 1991994783322914, 1758681962032007, 380046701118659}), + Z: radix51.FieldElement([5]uint64{1, 0, 0, 0, 0}), + T: radix51.FieldElement([5]uint64{410445769351754, 2235400917701188, 1495825632738689, 1351628537510093, 430502003771208}), + } + + Bneg.Neg(&B) + + var checkLhs, checkRhs, zero ProjP3 + zero.Zero() + + tmpCached.FromP3(&B) + tmpP1xP1.Add(&B, &tmpCached) + checkLhs.FromP1xP1(&tmpP1xP1) + tmpP2.FromP3(&B) + tmpP1xP1.Double(&tmpP2) + checkRhs.FromP1xP1(&tmpP1xP1) + if checkLhs.Equal(&checkRhs) != 1 { + t.Error("B + B != [2]B") + } + + tmpCached.FromP3(&B) + tmpP1xP1.Sub(&B, &tmpCached) + checkLhs.FromP1xP1(&tmpP1xP1) + tmpCached.FromP3(&Bneg) + tmpP1xP1.Add(&B, &tmpCached) + checkRhs.FromP1xP1(&tmpP1xP1) + if checkLhs.Equal(&checkRhs) != 1 { + t.Error("B - B != B + (-B)") + } + if zero.Equal(&checkLhs) != 1 { + t.Error("B - B != 0") + } + if zero.Equal(&checkRhs) != 1 { + t.Error("B + (-B) != 0") + } +}