mirror of https://github.com/gtank/ristretto255
internal/radix51: add docs and some light readability refactors
This commit is contained in:
parent
010995eaa9
commit
d23de5461e
|
@ -3,8 +3,11 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Field arithmetic in radix 2^51 representation. This code is a port of the
|
||||
// public domain amd64-51-30k version of ed25519 from SUPERCOP.
|
||||
// GF(2^255-19) field arithmetic in radix 2^51 representation. This code is a
|
||||
// port of the public domain amd64-51-30k version of ed25519 from SUPERCOP.
|
||||
//
|
||||
// The interface works similarly to math/big.Int, and all arguments and
|
||||
// receivers are allowed to alias.
|
||||
package radix51
|
||||
|
||||
import (
|
||||
|
@ -15,13 +18,12 @@ import (
|
|||
|
||||
// FieldElement represents an element of the field GF(2^255-19). An element t
|
||||
// represents the integer t[0] + t[1]*2^51 + t[2]*2^102 + t[3]*2^153 +
|
||||
// t[4]*2^204. The zero value is a valid zero element.
|
||||
// t[4]*2^204. Each limb must not exceed 2^54 - 1 to be valid.
|
||||
//
|
||||
// The zero value is a valid zero element.
|
||||
type FieldElement [5]uint64
|
||||
|
||||
const (
|
||||
// The vaule 2^51-1, used in carry propagation
|
||||
maskLow51Bits = uint64(1)<<51 - 1
|
||||
)
|
||||
const maskLow51Bits uint64 = (1 << 51) - 1
|
||||
|
||||
var (
|
||||
Zero = &FieldElement{0, 0, 0, 0, 0}
|
||||
|
@ -30,6 +32,7 @@ var (
|
|||
MinusOne = new(FieldElement).Neg(One)
|
||||
)
|
||||
|
||||
// Zero sets v = 0 and returns v.
|
||||
func (v *FieldElement) Zero() *FieldElement {
|
||||
v[0] = 0
|
||||
v[1] = 0
|
||||
|
@ -39,6 +42,7 @@ func (v *FieldElement) Zero() *FieldElement {
|
|||
return v
|
||||
}
|
||||
|
||||
// One sets v = 1 and returns v.
|
||||
func (v *FieldElement) One() *FieldElement {
|
||||
v[0] = 1
|
||||
v[1] = 0
|
||||
|
@ -48,6 +52,7 @@ func (v *FieldElement) One() *FieldElement {
|
|||
return v
|
||||
}
|
||||
|
||||
// Reduce reduces v modulo 2^255 - 19 and returns it.
|
||||
func (v *FieldElement) Reduce(u *FieldElement) *FieldElement {
|
||||
v.Set(u)
|
||||
|
||||
|
@ -90,9 +95,11 @@ func (v *FieldElement) Reduce(u *FieldElement) *FieldElement {
|
|||
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".
|
||||
// Add sets v = a + b and returns v.
|
||||
//
|
||||
// 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) *FieldElement {
|
||||
v[0] = a[0] + b[0]
|
||||
v[1] = a[1] + b[1]
|
||||
|
@ -102,7 +109,7 @@ func (v *FieldElement) Add(a, b *FieldElement) *FieldElement {
|
|||
return v
|
||||
}
|
||||
|
||||
// Sub sets v = a - b.
|
||||
// Sub sets v = a - b and returns v.
|
||||
func (v *FieldElement) Sub(a, b *FieldElement) *FieldElement {
|
||||
t := *b
|
||||
|
||||
|
@ -130,12 +137,12 @@ func (v *FieldElement) Sub(a, b *FieldElement) *FieldElement {
|
|||
return v
|
||||
}
|
||||
|
||||
// Neg sets v = -a.
|
||||
// Neg sets v = -a and returns v.
|
||||
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.
|
||||
// Invert sets v = 1/z mod p and returns v.
|
||||
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].
|
||||
|
@ -200,15 +207,18 @@ func (v *FieldElement) Invert(z *FieldElement) *FieldElement {
|
|||
return v.Mul(&t, &z11) // 2^255 - 21
|
||||
}
|
||||
|
||||
// Set sets v = a and returns v.
|
||||
func (v *FieldElement) Set(a *FieldElement) *FieldElement {
|
||||
*v = *a
|
||||
return v
|
||||
}
|
||||
|
||||
// FromBytes sets v to x, which must be a 32 bytes little-endian encoding.
|
||||
func (v *FieldElement) FromBytes(x []byte) *FieldElement {
|
||||
if len(x) != 32 {
|
||||
panic("invalid input size")
|
||||
panic("ed25519: invalid field element input size")
|
||||
}
|
||||
|
||||
v[0] = uint64(x[0])
|
||||
v[0] |= uint64(x[1]) << 8
|
||||
v[0] |= uint64(x[2]) << 16
|
||||
|
@ -366,7 +376,6 @@ func (v *FieldElement) Equal(u *FieldElement) int {
|
|||
const mask64Bits uint64 = (1 << 64) - 1
|
||||
|
||||
// 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) *FieldElement {
|
||||
m := uint64(cond) * mask64Bits
|
||||
v[0] = (m & a[0]) | (^m & b[0])
|
||||
|
@ -390,7 +399,7 @@ func (v *FieldElement) IsNegative() int {
|
|||
return int(b[0] & 1)
|
||||
}
|
||||
|
||||
// Abs sets v to |u|. v and u are allowed to overlap.
|
||||
// Abs sets v to |u| and returns v.
|
||||
func (v *FieldElement) Abs(u *FieldElement) *FieldElement {
|
||||
return v.CondNeg(u, u.IsNegative())
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
package radix51
|
||||
|
||||
// Mul sets out = x * y.
|
||||
// Mul sets v = x * y and returns v.
|
||||
func (v *FieldElement) Mul(x, y *FieldElement) *FieldElement {
|
||||
var x0, x1, x2, x3, x4 uint64
|
||||
var y0, y1, y2, y3, y4 uint64
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
package radix51
|
||||
|
||||
// Mul sets out = x * y.
|
||||
// Mul sets v = x * y and returns v.
|
||||
func (v *FieldElement) Mul(x, y *FieldElement) *FieldElement {
|
||||
feMul(v, x, y)
|
||||
return v
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
|
||||
// +build amd64,!noasm
|
||||
|
||||
// func feMul(outp *uint64, xp *uint64, yp *uint64)
|
||||
// func feMul(out, a, b *FieldElement)
|
||||
TEXT ·feMul(SB),$0-24
|
||||
MOVQ outp+0(FP), DI
|
||||
MOVQ xp+8(FP), BX
|
||||
MOVQ yp+16(FP), CX
|
||||
MOVQ out+0(FP), DI
|
||||
MOVQ a+8(FP), BX
|
||||
MOVQ b+16(FP), CX
|
||||
|
||||
// Calculate r0
|
||||
MOVQ 0(BX), AX // rax <-- x0
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
package radix51
|
||||
|
||||
// Square sets v = x * x.
|
||||
// Square sets v = x * x and returns v.
|
||||
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
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
package radix51
|
||||
|
||||
// Square sets v = x * x.
|
||||
// Square sets v = x * x and returns v.
|
||||
func (v *FieldElement) Square(x *FieldElement) *FieldElement {
|
||||
feSquare(v, x)
|
||||
return v
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
// +build amd64,!noasm
|
||||
|
||||
// func feSquare(outp *uint64, xp *uint64)
|
||||
// func feSquare(out, x *FieldElement)
|
||||
TEXT ·feSquare(SB),4,$0-16
|
||||
MOVQ outp+0(FP), DI
|
||||
MOVQ xp+8(FP), SI
|
||||
MOVQ out+0(FP), DI
|
||||
MOVQ x+8(FP), SI
|
||||
|
||||
// r0 = x0*x0 + x1*38*x4 + x2*38*x3
|
||||
MOVQ 0(SI), AX
|
||||
|
|
Loading…
Reference in New Issue