mirror of https://github.com/gtank/ristretto255
internal: make all APIs chainable
This commit is contained in:
parent
6c2fda803c
commit
2925e841f7
11
ed25519.go
11
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue