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).
|
// Double returns 2*(x,y).
|
||||||
func (curve ed25519Curve) Double(x1, y1 *big.Int) (x, y *big.Int) {
|
func (curve ed25519Curve) Double(x1, y1 *big.Int) (x, y *big.Int) {
|
||||||
var p group.ProjectiveGroupElement
|
p := new(group.ProjectiveGroupElement).FromAffine(x1, y1)
|
||||||
|
|
||||||
p.FromAffine(x1, y1)
|
|
||||||
|
|
||||||
// Use the special-case DoubleZ1 here because we know Z will be 1.
|
// 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.
|
// 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)
|
var b = int32((s[i/8] >> uint(i&7)) & 1)
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
r1.Add(&r0, &r1)
|
r1.Add(&r0, &r1)
|
||||||
r0.Double()
|
r0.Double(&r0)
|
||||||
} else {
|
} else {
|
||||||
r0.Add(&r0, &r1)
|
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
|
// described in "Twisted Edwards Curves Revisited", Hisil-Wong-Carter-Dawson
|
||||||
// 2008, Section 3.1 (https://eprint.iacr.org/2008/522.pdf)
|
// 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
|
// 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.X.FromBig(x)
|
||||||
v.Y.FromBig(y)
|
v.Y.FromBig(y)
|
||||||
v.T.Mul(&v.X, &v.Y)
|
v.T.Mul(&v.X, &v.Y)
|
||||||
v.Z.One()
|
v.Z.One()
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extended coordinates are XYZT with x = X/Z, y = Y/Z, or the "P3"
|
// 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
|
// instead of another point in extended coordinates. I have implemented it
|
||||||
// this way to see if more straightforward code is worth the (hopefully small)
|
// this way to see if more straightforward code is worth the (hopefully small)
|
||||||
// performance tradeoff.
|
// 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: 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
|
var A, B, C, D, E, F, G, H radix51.FieldElement
|
||||||
|
|
||||||
// A ← X1^2, B ← Y1^2
|
// A ← X1^2, B ← Y1^2
|
||||||
A.Square(&v.X)
|
A.Square(&u.X)
|
||||||
B.Square(&v.Y)
|
B.Square(&u.Y)
|
||||||
|
|
||||||
// C ← 2*Z1^2
|
// C ← 2*Z1^2
|
||||||
C.Square(&v.Z)
|
C.Square(&u.Z)
|
||||||
C.Add(&C, &C) // TODO should probably implement FeSquare2
|
C.Add(&C, &C) // TODO should probably implement FeSquare2
|
||||||
|
|
||||||
// D ← -1*A
|
// D ← -1*A
|
||||||
|
@ -151,7 +149,7 @@ func (v *ExtendedGroupElement) Double() *ExtendedGroupElement {
|
||||||
|
|
||||||
// E ← (X1+Y1)^2 − A − B
|
// E ← (X1+Y1)^2 − A − B
|
||||||
var t0 radix51.FieldElement
|
var t0 radix51.FieldElement
|
||||||
t0.Add(&v.X, &v.Y)
|
t0.Add(&u.X, &u.Y)
|
||||||
t0.Square(&t0)
|
t0.Square(&t0)
|
||||||
E.Sub(&t0, &A)
|
E.Sub(&t0, &A)
|
||||||
E.Sub(&E, &B)
|
E.Sub(&E, &B)
|
||||||
|
@ -174,10 +172,11 @@ type ProjectiveGroupElement struct {
|
||||||
X, Y, Z radix51.FieldElement
|
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.X.FromBig(x)
|
||||||
v.Y.FromBig(y)
|
v.Y.FromBig(y)
|
||||||
v.Z.Zero()
|
v.Z.Zero()
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ProjectiveGroupElement) ToAffine() (*big.Int, *big.Int) {
|
func (v *ProjectiveGroupElement) ToAffine() (*big.Int, *big.Int) {
|
||||||
|
|
|
@ -29,32 +29,35 @@ var (
|
||||||
Two = &FieldElement{2, 0, 0, 0, 0}
|
Two = &FieldElement{2, 0, 0, 0, 0}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (v *FieldElement) Zero() {
|
func (v *FieldElement) Zero() *FieldElement {
|
||||||
v[0] = 0
|
v[0] = 0
|
||||||
v[1] = 0
|
v[1] = 0
|
||||||
v[2] = 0
|
v[2] = 0
|
||||||
v[3] = 0
|
v[3] = 0
|
||||||
v[4] = 0
|
v[4] = 0
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *FieldElement) One() {
|
func (v *FieldElement) One() *FieldElement {
|
||||||
v[0] = 1
|
v[0] = 1
|
||||||
v[1] = 0
|
v[1] = 0
|
||||||
v[2] = 0
|
v[2] = 0
|
||||||
v[3] = 0
|
v[3] = 0
|
||||||
v[4] = 0
|
v[4] = 0
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetInt sets the receiving FieldElement to the specified small integer.
|
// 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[0] = x
|
||||||
v[1] = 0
|
v[1] = 0
|
||||||
v[2] = 0
|
v[2] = 0
|
||||||
v[3] = 0
|
v[3] = 0
|
||||||
v[4] = 0
|
v[4] = 0
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *FieldElement) Reduce(u *FieldElement) {
|
func (v *FieldElement) Reduce(u *FieldElement) *FieldElement {
|
||||||
v.Set(u)
|
v.Set(u)
|
||||||
|
|
||||||
// Lev v = v[0] + v[1]*2^51 + v[2]*2^102 + v[3]*2^153 + v[4]*2^204
|
// 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
|
v[3] = v[3] & maskLow51Bits
|
||||||
// no additional carry
|
// no additional carry
|
||||||
v[4] = v[4] & maskLow51Bits
|
v[4] = v[4] & maskLow51Bits
|
||||||
|
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add sets v = a + b. Long sequences of additions without reduction that
|
// Add sets v = a + b. Long sequences of additions without reduction that
|
||||||
// let coefficients grow larger than 54 bits would be a problem. Paper
|
// let coefficients grow larger than 54 bits would be a problem. Paper
|
||||||
// cautions: "do not have such sequences of additions".
|
// 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[0] = a[0] + b[0]
|
||||||
v[1] = a[1] + b[1]
|
v[1] = a[1] + b[1]
|
||||||
v[2] = a[2] + b[2]
|
v[2] = a[2] + b[2]
|
||||||
v[3] = a[3] + b[3]
|
v[3] = a[3] + b[3]
|
||||||
v[4] = a[4] + b[4]
|
v[4] = a[4] + b[4]
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sub sets v = a - b.
|
// Sub sets v = a - b.
|
||||||
func (v *FieldElement) Sub(a, b *FieldElement) {
|
func (v *FieldElement) Sub(a, b *FieldElement) *FieldElement {
|
||||||
t := *b
|
t := *b
|
||||||
|
|
||||||
// Reduce each limb below 2^51, propagating carries. Ensures that results
|
// 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[2] = (a[2] + 0xFFFFFFFFFFFFE) - t[2]
|
||||||
v[3] = (a[3] + 0xFFFFFFFFFFFFE) - t[3]
|
v[3] = (a[3] + 0xFFFFFFFFFFFFE) - t[3]
|
||||||
v[4] = (a[4] + 0xFFFFFFFFFFFFE) - t[4]
|
v[4] = (a[4] + 0xFFFFFFFFFFFFE) - t[4]
|
||||||
|
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Neg sets v = -a.
|
// Neg sets v = -a.
|
||||||
func (v *FieldElement) Neg(a *FieldElement) {
|
func (v *FieldElement) Neg(a *FieldElement) *FieldElement {
|
||||||
v.Sub(&FieldElement{}, a)
|
return v.Sub(Zero, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invert sets v = 1/z mod p by calculating z^(p-2), p-2 = 2^255 - 21.
|
// 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
|
// Inversion is implemented as exponentiation with exponent p − 2. It uses the
|
||||||
// same sequence of 255 squarings and 11 multiplications as [Curve25519].
|
// 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
|
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^254 - 2^4
|
||||||
t.Square(&t) // 2^255 - 2^5
|
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
|
*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[0])
|
||||||
v[0] |= uint64(x[1]) << 8
|
v[0] |= uint64(x[1]) << 8
|
||||||
v[0] |= uint64(x[2]) << 16
|
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[29]) << 28
|
||||||
v[4] |= uint64(x[30]) << 36
|
v[4] |= uint64(x[30]) << 36
|
||||||
v[4] |= uint64(x[31]&127) << 44
|
v[4] |= uint64(x[31]&127) << 44
|
||||||
|
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *FieldElement) ToBytes(r *[32]byte) {
|
func (v *FieldElement) ToBytes(r *[32]byte) {
|
||||||
var t FieldElement
|
t := new(FieldElement).Reduce(v)
|
||||||
t.Reduce(v)
|
|
||||||
|
|
||||||
r[0] = byte(t[0] & 0xff)
|
r[0] = byte(t[0] & 0xff)
|
||||||
r[1] = byte((t[0] >> 8) & 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))
|
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
|
var buf [32]byte
|
||||||
|
|
||||||
offset := 0
|
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 {
|
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.
|
// Select sets v to a if cond == 1, and to b if cond == 0.
|
||||||
// v, a and b are allowed to overlap.
|
// 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
|
m := uint64(cond) * 0xffffffffffffffff
|
||||||
v[0] = (m & a[0]) | (^m & b[0])
|
v[0] = (m & a[0]) | (^m & b[0])
|
||||||
v[1] = (m & a[1]) | (^m & b[1])
|
v[1] = (m & a[1]) | (^m & b[1])
|
||||||
v[2] = (m & a[2]) | (^m & b[2])
|
v[2] = (m & a[2]) | (^m & b[2])
|
||||||
v[3] = (m & a[3]) | (^m & b[3])
|
v[3] = (m & a[3]) | (^m & b[3])
|
||||||
v[4] = (m & a[4]) | (^m & b[4])
|
v[4] = (m & a[4]) | (^m & b[4])
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// CondNeg sets v to -u if cond == 1, and to u if cond == 0.
|
// CondNeg sets v to -u if cond == 1, and to u if cond == 0.
|
||||||
func (v *FieldElement) CondNeg(u *FieldElement, cond int) {
|
func (v *FieldElement) CondNeg(u *FieldElement, cond int) *FieldElement {
|
||||||
v.Neg(u)
|
return v.Select(v.Neg(u), u, cond)
|
||||||
v.Select(v, u, cond)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNegative returns 1 if v is negative, and 0 otherwise.
|
// 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.
|
// Abs sets v to |u|. v and u are allowed to overlap.
|
||||||
func (v *FieldElement) Abs(u *FieldElement) {
|
func (v *FieldElement) Abs(u *FieldElement) *FieldElement {
|
||||||
v.CondNeg(u, u.IsNegative())
|
return v.CondNeg(u, u.IsNegative())
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
package radix51
|
package radix51
|
||||||
|
|
||||||
// Mul sets out = x * y.
|
// 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 x0, x1, x2, x3, x4 uint64
|
||||||
var y0, y1, y2, y3, y4 uint64
|
var y0, y1, y2, y3, y4 uint64
|
||||||
|
|
||||||
|
@ -123,4 +123,5 @@ func (v *FieldElement) Mul(x, y *FieldElement) {
|
||||||
v[2] = r20
|
v[2] = r20
|
||||||
v[3] = r30
|
v[3] = r30
|
||||||
v[4] = r40
|
v[4] = r40
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
package radix51
|
package radix51
|
||||||
|
|
||||||
// Mul sets out = x * y.
|
// Mul sets out = x * y.
|
||||||
func (v *FieldElement) Mul(x, y *FieldElement) {
|
func (v *FieldElement) Mul(x, y *FieldElement) *FieldElement {
|
||||||
feMul(v, x, y)
|
feMul(v, x, y)
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// go:noescape
|
// go:noescape
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
package radix51
|
package radix51
|
||||||
|
|
||||||
// Square sets v = x * x.
|
// 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;
|
// Squaring needs only 15 mul instructions. Some inputs are multiplied by 2;
|
||||||
// this is combined with multiplication by 19 where possible. The coefficient
|
// this is combined with multiplication by 19 where possible. The coefficient
|
||||||
// reduction after squaring is the same as for multiplication.
|
// reduction after squaring is the same as for multiplication.
|
||||||
|
@ -95,4 +95,5 @@ func (v *FieldElement) Square(x *FieldElement) {
|
||||||
v[2] = r20
|
v[2] = r20
|
||||||
v[3] = r30
|
v[3] = r30
|
||||||
v[4] = r40
|
v[4] = r40
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
package radix51
|
package radix51
|
||||||
|
|
||||||
// Square sets v = x * x.
|
// Square sets v = x * x.
|
||||||
func (v *FieldElement) Square(x *FieldElement) {
|
func (v *FieldElement) Square(x *FieldElement) *FieldElement {
|
||||||
feSquare(v, x)
|
feSquare(v, x)
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// go:noescape
|
// go:noescape
|
||||||
|
|
Loading…
Reference in New Issue