From 2925e841f7fb34c8b3ad19b255c81eb569c8a872 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sat, 26 Jan 2019 21:05:03 -0500 Subject: [PATCH] internal: make all APIs chainable --- ed25519.go | 11 +++--- internal/group/ge.go | 19 +++++----- internal/radix51/fe.go | 54 +++++++++++++++++------------ internal/radix51/fe_mul.go | 3 +- internal/radix51/fe_mul_amd64.go | 3 +- internal/radix51/fe_square.go | 3 +- internal/radix51/fe_square_amd64.go | 3 +- 7 files changed, 53 insertions(+), 43 deletions(-) diff --git a/ed25519.go b/ed25519.go index b93de42..7419f81 100644 --- a/ed25519.go +++ b/ed25519.go @@ -91,12 +91,9 @@ func (curve ed25519Curve) Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) { // Double returns 2*(x,y). func (curve ed25519Curve) Double(x1, y1 *big.Int) (x, y *big.Int) { - var p group.ProjectiveGroupElement - - p.FromAffine(x1, y1) - + p := new(group.ProjectiveGroupElement).FromAffine(x1, y1) // Use the special-case DoubleZ1 here because we know Z will be 1. - return p.DoubleZ1().ToAffine() + return p.DoubleZ1(p).ToAffine() } // ScalarMult returns k*(Bx,By) where k is a number in big-endian form. @@ -125,10 +122,10 @@ func (curve ed25519Curve) ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int) var b = int32((s[i/8] >> uint(i&7)) & 1) if b == 0 { r1.Add(&r0, &r1) - r0.Double() + r0.Double(&r0) } else { r0.Add(&r0, &r1) - r1.Double() + r1.Double(&r0) } } diff --git a/internal/group/ge.go b/internal/group/ge.go index eb99ce7..8ca4a2d 100644 --- a/internal/group/ge.go +++ b/internal/group/ge.go @@ -38,11 +38,12 @@ type ExtendedGroupElement struct { // described in "Twisted Edwards Curves Revisited", Hisil-Wong-Carter-Dawson // 2008, Section 3.1 (https://eprint.iacr.org/2008/522.pdf) // See also https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3 -func (v *ExtendedGroupElement) FromAffine(x, y *big.Int) { +func (v *ExtendedGroupElement) FromAffine(x, y *big.Int) *ExtendedGroupElement { v.X.FromBig(x) v.Y.FromBig(y) v.T.Mul(&v.X, &v.Y) v.Z.One() + return v } // Extended coordinates are XYZT with x = X/Z, y = Y/Z, or the "P3" @@ -130,20 +131,17 @@ func (v *ExtendedGroupElement) Add(p1, p2 *ExtendedGroupElement) *ExtendedGroupE // instead of another point in extended coordinates. I have implemented it // this way to see if more straightforward code is worth the (hopefully small) // performance tradeoff. -func (v *ExtendedGroupElement) Double() *ExtendedGroupElement { +func (v *ExtendedGroupElement) Double(u *ExtendedGroupElement) *ExtendedGroupElement { // TODO: Convert to projective coordinates? Section 4.3 mixed doubling? - // TODO: make a decision about how these APIs work wrt chaining/smashing - // *v = *(v.ToProjective().Double().ToExtended()) - // return v var A, B, C, D, E, F, G, H radix51.FieldElement // A ← X1^2, B ← Y1^2 - A.Square(&v.X) - B.Square(&v.Y) + A.Square(&u.X) + B.Square(&u.Y) // C ← 2*Z1^2 - C.Square(&v.Z) + C.Square(&u.Z) C.Add(&C, &C) // TODO should probably implement FeSquare2 // D ← -1*A @@ -151,7 +149,7 @@ func (v *ExtendedGroupElement) Double() *ExtendedGroupElement { // E ← (X1+Y1)^2 − A − B var t0 radix51.FieldElement - t0.Add(&v.X, &v.Y) + t0.Add(&u.X, &u.Y) t0.Square(&t0) E.Sub(&t0, &A) E.Sub(&E, &B) @@ -174,10 +172,11 @@ type ProjectiveGroupElement struct { X, Y, Z radix51.FieldElement } -func (v *ProjectiveGroupElement) FromAffine(x, y *big.Int) { +func (v *ProjectiveGroupElement) FromAffine(x, y *big.Int) *ProjectiveGroupElement { v.X.FromBig(x) v.Y.FromBig(y) v.Z.Zero() + return v } func (v *ProjectiveGroupElement) ToAffine() (*big.Int, *big.Int) { diff --git a/internal/radix51/fe.go b/internal/radix51/fe.go index 1249aa8..a849544 100644 --- a/internal/radix51/fe.go +++ b/internal/radix51/fe.go @@ -29,32 +29,35 @@ var ( Two = &FieldElement{2, 0, 0, 0, 0} ) -func (v *FieldElement) Zero() { +func (v *FieldElement) Zero() *FieldElement { v[0] = 0 v[1] = 0 v[2] = 0 v[3] = 0 v[4] = 0 + return v } -func (v *FieldElement) One() { +func (v *FieldElement) One() *FieldElement { v[0] = 1 v[1] = 0 v[2] = 0 v[3] = 0 v[4] = 0 + return v } // SetInt sets the receiving FieldElement to the specified small integer. -func (v *FieldElement) SetInt(x uint64) { +func (v *FieldElement) SetInt(x uint64) *FieldElement { v[0] = x v[1] = 0 v[2] = 0 v[3] = 0 v[4] = 0 + return v } -func (v *FieldElement) Reduce(u *FieldElement) { +func (v *FieldElement) Reduce(u *FieldElement) *FieldElement { v.Set(u) // Lev v = v[0] + v[1]*2^51 + v[2]*2^102 + v[3]*2^153 + v[4]*2^204 @@ -92,21 +95,24 @@ func (v *FieldElement) Reduce(u *FieldElement) { v[3] = v[3] & maskLow51Bits // no additional carry v[4] = v[4] & maskLow51Bits + + return v } // Add sets v = a + b. Long sequences of additions without reduction that // let coefficients grow larger than 54 bits would be a problem. Paper // cautions: "do not have such sequences of additions". -func (v *FieldElement) Add(a, b *FieldElement) { +func (v *FieldElement) Add(a, b *FieldElement) *FieldElement { v[0] = a[0] + b[0] v[1] = a[1] + b[1] v[2] = a[2] + b[2] v[3] = a[3] + b[3] v[4] = a[4] + b[4] + return v } // Sub sets v = a - b. -func (v *FieldElement) Sub(a, b *FieldElement) { +func (v *FieldElement) Sub(a, b *FieldElement) *FieldElement { t := *b // Reduce each limb below 2^51, propagating carries. Ensures that results @@ -129,15 +135,17 @@ func (v *FieldElement) Sub(a, b *FieldElement) { v[2] = (a[2] + 0xFFFFFFFFFFFFE) - t[2] v[3] = (a[3] + 0xFFFFFFFFFFFFE) - t[3] v[4] = (a[4] + 0xFFFFFFFFFFFFE) - t[4] + + return v } // Neg sets v = -a. -func (v *FieldElement) Neg(a *FieldElement) { - v.Sub(&FieldElement{}, a) +func (v *FieldElement) Neg(a *FieldElement) *FieldElement { + return v.Sub(Zero, a) } // Invert sets v = 1/z mod p by calculating z^(p-2), p-2 = 2^255 - 21. -func (v *FieldElement) Invert(z *FieldElement) { +func (v *FieldElement) Invert(z *FieldElement) *FieldElement { // Inversion is implemented as exponentiation with exponent p − 2. It uses the // same sequence of 255 squarings and 11 multiplications as [Curve25519]. var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t FieldElement @@ -198,14 +206,15 @@ func (v *FieldElement) Invert(z *FieldElement) { t.Square(&t) // 2^254 - 2^4 t.Square(&t) // 2^255 - 2^5 - v.Mul(&t, &z11) // 2^255 - 21 + return v.Mul(&t, &z11) // 2^255 - 21 } -func (v *FieldElement) Set(a *FieldElement) { +func (v *FieldElement) Set(a *FieldElement) *FieldElement { *v = *a + return v } -func (v *FieldElement) FromBytes(x *[32]byte) { +func (v *FieldElement) FromBytes(x *[32]byte) *FieldElement { v[0] = uint64(x[0]) v[0] |= uint64(x[1]) << 8 v[0] |= uint64(x[2]) << 16 @@ -246,11 +255,12 @@ func (v *FieldElement) FromBytes(x *[32]byte) { v[4] |= uint64(x[29]) << 28 v[4] |= uint64(x[30]) << 36 v[4] |= uint64(x[31]&127) << 44 + + return v } func (v *FieldElement) ToBytes(r *[32]byte) { - var t FieldElement - t.Reduce(v) + t := new(FieldElement).Reduce(v) r[0] = byte(t[0] & 0xff) r[1] = byte((t[0] >> 8) & 0xff) @@ -294,7 +304,7 @@ func (v *FieldElement) ToBytes(r *[32]byte) { r[31] = byte((t[4] >> 44)) } -func (v *FieldElement) FromBig(num *big.Int) { +func (v *FieldElement) FromBig(num *big.Int) *FieldElement { var buf [32]byte offset := 0 @@ -312,7 +322,7 @@ func (v *FieldElement) FromBig(num *big.Int) { } } - v.FromBytes(&buf) + return v.FromBytes(&buf) } func (v *FieldElement) ToBig() *big.Int { @@ -350,19 +360,19 @@ func (v *FieldElement) Equal(u *FieldElement) int { // Select sets v to a if cond == 1, and to b if cond == 0. // v, a and b are allowed to overlap. -func (v *FieldElement) Select(a, b *FieldElement, cond int) { +func (v *FieldElement) Select(a, b *FieldElement, cond int) *FieldElement { m := uint64(cond) * 0xffffffffffffffff v[0] = (m & a[0]) | (^m & b[0]) v[1] = (m & a[1]) | (^m & b[1]) v[2] = (m & a[2]) | (^m & b[2]) v[3] = (m & a[3]) | (^m & b[3]) v[4] = (m & a[4]) | (^m & b[4]) + return v } // CondNeg sets v to -u if cond == 1, and to u if cond == 0. -func (v *FieldElement) CondNeg(u *FieldElement, cond int) { - v.Neg(u) - v.Select(v, u, cond) +func (v *FieldElement) CondNeg(u *FieldElement, cond int) *FieldElement { + return v.Select(v.Neg(u), u, cond) } // IsNegative returns 1 if v is negative, and 0 otherwise. @@ -373,6 +383,6 @@ func (v *FieldElement) IsNegative() int { } // Abs sets v to |u|. v and u are allowed to overlap. -func (v *FieldElement) Abs(u *FieldElement) { - v.CondNeg(u, u.IsNegative()) +func (v *FieldElement) Abs(u *FieldElement) *FieldElement { + return v.CondNeg(u, u.IsNegative()) } diff --git a/internal/radix51/fe_mul.go b/internal/radix51/fe_mul.go index 2c28e4f..08ffbb4 100644 --- a/internal/radix51/fe_mul.go +++ b/internal/radix51/fe_mul.go @@ -7,7 +7,7 @@ package radix51 // Mul sets out = x * y. -func (v *FieldElement) Mul(x, y *FieldElement) { +func (v *FieldElement) Mul(x, y *FieldElement) *FieldElement { var x0, x1, x2, x3, x4 uint64 var y0, y1, y2, y3, y4 uint64 @@ -123,4 +123,5 @@ func (v *FieldElement) Mul(x, y *FieldElement) { v[2] = r20 v[3] = r30 v[4] = r40 + return v } diff --git a/internal/radix51/fe_mul_amd64.go b/internal/radix51/fe_mul_amd64.go index d629bb5..7ad010f 100644 --- a/internal/radix51/fe_mul_amd64.go +++ b/internal/radix51/fe_mul_amd64.go @@ -7,8 +7,9 @@ package radix51 // Mul sets out = x * y. -func (v *FieldElement) Mul(x, y *FieldElement) { +func (v *FieldElement) Mul(x, y *FieldElement) *FieldElement { feMul(v, x, y) + return v } // go:noescape diff --git a/internal/radix51/fe_square.go b/internal/radix51/fe_square.go index 031ec7a..0a2d4ac 100644 --- a/internal/radix51/fe_square.go +++ b/internal/radix51/fe_square.go @@ -7,7 +7,7 @@ package radix51 // Square sets v = x * x. -func (v *FieldElement) Square(x *FieldElement) { +func (v *FieldElement) Square(x *FieldElement) *FieldElement { // Squaring needs only 15 mul instructions. Some inputs are multiplied by 2; // this is combined with multiplication by 19 where possible. The coefficient // reduction after squaring is the same as for multiplication. @@ -95,4 +95,5 @@ func (v *FieldElement) Square(x *FieldElement) { v[2] = r20 v[3] = r30 v[4] = r40 + return v } diff --git a/internal/radix51/fe_square_amd64.go b/internal/radix51/fe_square_amd64.go index 7d5b9ff..d91d669 100644 --- a/internal/radix51/fe_square_amd64.go +++ b/internal/radix51/fe_square_amd64.go @@ -7,8 +7,9 @@ package radix51 // Square sets v = x * x. -func (v *FieldElement) Square(x *FieldElement) { +func (v *FieldElement) Square(x *FieldElement) *FieldElement { feSquare(v, x) + return v } // go:noescape