mirror of https://github.com/gtank/ristretto255
Update gtank/ed25519 code to fe6e0954e0
Our Ristretto-agnostic field operations are now upstreamed, so we can drop the internal package.
This commit is contained in:
parent
7522470fbc
commit
dcc5867ec2
|
@ -3,60 +3,14 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package edwards25519
|
package ristretto255
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/subtle"
|
"math/big"
|
||||||
|
|
||||||
"github.com/gtank/ristretto255/internal/edwards25519/internal/radix51"
|
. "github.com/gtank/ristretto255/internal/radix51"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FeEqual returns 1 if a and b are equal, and 0 otherwise.
|
|
||||||
func FeEqual(a, b *FieldElement) int {
|
|
||||||
var sa, sb [32]byte
|
|
||||||
radix51.FeToBytes(&sa, a)
|
|
||||||
radix51.FeToBytes(&sb, b)
|
|
||||||
return subtle.ConstantTimeCompare(sa[:], sb[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// FeSelect sets out to v if cond == 1, and to u if cond == 0.
|
|
||||||
// out, v and u are allowed to overlap.
|
|
||||||
func FeSelect(out, v, u *FieldElement, cond int) {
|
|
||||||
b := uint64(cond) * 0xffffffffffffffff
|
|
||||||
out[0] = (b & v[0]) | (^b & u[0])
|
|
||||||
out[1] = (b & v[1]) | (^b & u[1])
|
|
||||||
out[2] = (b & v[2]) | (^b & u[2])
|
|
||||||
out[3] = (b & v[3]) | (^b & u[3])
|
|
||||||
out[4] = (b & v[4]) | (^b & u[4])
|
|
||||||
}
|
|
||||||
|
|
||||||
// FeCondNeg sets u to -u if cond == 1, and to u if cond == 0.
|
|
||||||
func FeCondNeg(u *FieldElement, cond int) {
|
|
||||||
var neg FieldElement
|
|
||||||
FeNeg(&neg, u)
|
|
||||||
|
|
||||||
b := uint64(cond) * 0xffffffffffffffff
|
|
||||||
u[0] ^= b & (u[0] ^ neg[0])
|
|
||||||
u[1] ^= b & (u[1] ^ neg[1])
|
|
||||||
u[2] ^= b & (u[2] ^ neg[2])
|
|
||||||
u[3] ^= b & (u[3] ^ neg[3])
|
|
||||||
u[4] ^= b & (u[4] ^ neg[4])
|
|
||||||
}
|
|
||||||
|
|
||||||
// FeIsNegative returns 1 if u is negative, and 0 otherwise.
|
|
||||||
func FeIsNegative(u *FieldElement) int {
|
|
||||||
var b [32]byte
|
|
||||||
radix51.FeToBytes(&b, u)
|
|
||||||
return int(b[0] & 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FeAbs sets out to |u|. out and u are allowed to overlap.
|
|
||||||
func FeAbs(out, u *FieldElement) {
|
|
||||||
var neg FieldElement
|
|
||||||
FeNeg(&neg, u)
|
|
||||||
FeSelect(out, &neg, u, FeIsNegative(u))
|
|
||||||
}
|
|
||||||
|
|
||||||
// fePow22523 is from x/crypto/ed25519/internal/edwards25519.
|
// fePow22523 is from x/crypto/ed25519/internal/edwards25519.
|
||||||
func fePow22523(out, z *FieldElement) {
|
func fePow22523(out, z *FieldElement) {
|
||||||
var t0, t1, t2 FieldElement
|
var t0, t1, t2 FieldElement
|
||||||
|
@ -150,7 +104,7 @@ func FeSqrtRatio(u, v *FieldElement) (int, *FieldElement) {
|
||||||
FeNeg(uneg, u)
|
FeNeg(uneg, u)
|
||||||
correct_sign_sqrt := FeEqual(check, u)
|
correct_sign_sqrt := FeEqual(check, u)
|
||||||
flipped_sign_sqrt := FeEqual(check, uneg)
|
flipped_sign_sqrt := FeEqual(check, uneg)
|
||||||
FeMul(uneg, uneg, &SQRT_M1)
|
FeMul(uneg, uneg, sqrtM1)
|
||||||
flipped_sign_sqrt_i := FeEqual(check, uneg)
|
flipped_sign_sqrt_i := FeEqual(check, uneg)
|
||||||
|
|
||||||
// done with these ("freeing" a, b)
|
// done with these ("freeing" a, b)
|
||||||
|
@ -159,7 +113,7 @@ func FeSqrtRatio(u, v *FieldElement) (int, *FieldElement) {
|
||||||
// r_prime = SQRT_M1 * r
|
// r_prime = SQRT_M1 * r
|
||||||
// r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r)
|
// r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r)
|
||||||
r_prime := &a
|
r_prime := &a
|
||||||
FeMul(r_prime, r, &SQRT_M1)
|
FeMul(r_prime, r, sqrtM1)
|
||||||
FeSelect(r, r_prime, r, flipped_sign_sqrt|flipped_sign_sqrt_i)
|
FeSelect(r, r_prime, r, flipped_sign_sqrt|flipped_sign_sqrt_i)
|
||||||
|
|
||||||
FeAbs(r, r)
|
FeAbs(r, r)
|
||||||
|
@ -167,3 +121,13 @@ func FeSqrtRatio(u, v *FieldElement) (int, *FieldElement) {
|
||||||
|
|
||||||
return was_square, r
|
return was_square, r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fieldElementFromDecimal(s string) *FieldElement {
|
||||||
|
n, ok := new(big.Int).SetString(s, 10)
|
||||||
|
if !ok {
|
||||||
|
panic("ristretto255: not a valid decimal: " + s)
|
||||||
|
}
|
||||||
|
var fe FieldElement
|
||||||
|
FeFromBig(&fe, n)
|
||||||
|
return &fe
|
||||||
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Copyright 2019 George Tankersley. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package edwards25519
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/gtank/ristretto255/internal/edwards25519/internal/radix51"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
SQRT_M1 FieldElement
|
|
||||||
SQRT_AD_MINUS_ONE FieldElement
|
|
||||||
INVSQRT_A_MINUS_D FieldElement
|
|
||||||
ONE_MINUS_D_SQ FieldElement
|
|
||||||
D_MINUS_ONE_SQ FieldElement
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
var (
|
|
||||||
CONST_SQRT_M1, _ = new(big.Int).SetString("19681161376707505956807079304988542015446066515923890162744021073123829784752", 10)
|
|
||||||
CONST_SQRT_AD_MINUS_ONE, _ = new(big.Int).SetString("25063068953384623474111414158702152701244531502492656460079210482610430750235", 10)
|
|
||||||
CONST_INVSQRT_A_MINUS_D, _ = new(big.Int).SetString("54469307008909316920995813868745141605393597292927456921205312896311721017578", 10)
|
|
||||||
CONST_ONE_MINUS_D_SQ, _ = new(big.Int).SetString("1159843021668779879193775521855586647937357759715417654439879720876111806838", 10)
|
|
||||||
CONST_D_MINUS_ONE_SQ, _ = new(big.Int).SetString("40440834346308536858101042469323190826248399146238708352240133220865137265952", 10)
|
|
||||||
)
|
|
||||||
|
|
||||||
radix51.FeFromBig(&SQRT_M1, CONST_SQRT_M1)
|
|
||||||
radix51.FeFromBig(&SQRT_AD_MINUS_ONE, CONST_SQRT_AD_MINUS_ONE)
|
|
||||||
radix51.FeFromBig(&INVSQRT_A_MINUS_D, CONST_INVSQRT_A_MINUS_D)
|
|
||||||
radix51.FeFromBig(&ONE_MINUS_D_SQ, CONST_ONE_MINUS_D_SQ)
|
|
||||||
radix51.FeFromBig(&D_MINUS_ONE_SQ, CONST_D_MINUS_ONE_SQ)
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Copyright 2019 George Tankersley. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package edwards25519
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gtank/ristretto255/internal/edwards25519/internal/group"
|
|
||||||
"github.com/gtank/ristretto255/internal/edwards25519/internal/radix51"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Expose some types and functions from the internal package to ristretto255.
|
|
||||||
|
|
||||||
type ExtendedGroupElement = group.ExtendedGroupElement
|
|
||||||
type FieldElement = radix51.FieldElement
|
|
||||||
|
|
||||||
var FeMul = radix51.FeMul
|
|
||||||
var FeSquare = radix51.FeSquare
|
|
||||||
var FeNeg = radix51.FeNeg
|
|
|
@ -1,6 +1,6 @@
|
||||||
package group
|
package group
|
||||||
|
|
||||||
import "github.com/gtank/ristretto255/internal/edwards25519/internal/radix51"
|
import "github.com/gtank/ristretto255/internal/radix51"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// d, a constant in the curve equation
|
// d, a constant in the curve equation
|
|
@ -5,7 +5,7 @@ package group
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
field "github.com/gtank/ristretto255/internal/edwards25519/internal/radix51"
|
field "github.com/gtank/ristretto255/internal/radix51"
|
||||||
)
|
)
|
||||||
|
|
||||||
// From EFD https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
|
// From EFD https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
|
|
@ -1,4 +1,5 @@
|
||||||
// Copyright (c) 2017 George Tankersley. All rights reserved.
|
// Copyright (c) 2017 George Tankersley. All rights reserved.
|
||||||
|
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -7,6 +8,7 @@
|
||||||
package radix51
|
package radix51
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/subtle"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
)
|
)
|
||||||
|
@ -330,3 +332,49 @@ func FeToBig(h *FieldElement) *big.Int {
|
||||||
out := new(big.Int)
|
out := new(big.Int)
|
||||||
return out.SetBits(words)
|
return out.SetBits(words)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FeEqual returns 1 if a and b are equal, and 0 otherwise.
|
||||||
|
func FeEqual(a, b *FieldElement) int {
|
||||||
|
var sa, sb [32]byte
|
||||||
|
FeToBytes(&sa, a)
|
||||||
|
FeToBytes(&sb, b)
|
||||||
|
return subtle.ConstantTimeCompare(sa[:], sb[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// FeSelect sets out to v if cond == 1, and to u if cond == 0.
|
||||||
|
// out, v and u are allowed to overlap.
|
||||||
|
func FeSelect(out, v, u *FieldElement, cond int) {
|
||||||
|
b := uint64(cond) * 0xffffffffffffffff
|
||||||
|
out[0] = (b & v[0]) | (^b & u[0])
|
||||||
|
out[1] = (b & v[1]) | (^b & u[1])
|
||||||
|
out[2] = (b & v[2]) | (^b & u[2])
|
||||||
|
out[3] = (b & v[3]) | (^b & u[3])
|
||||||
|
out[4] = (b & v[4]) | (^b & u[4])
|
||||||
|
}
|
||||||
|
|
||||||
|
// FeCondNeg sets u to -u if cond == 1, and to u if cond == 0.
|
||||||
|
func FeCondNeg(u *FieldElement, cond int) {
|
||||||
|
var neg FieldElement
|
||||||
|
FeNeg(&neg, u)
|
||||||
|
|
||||||
|
b := uint64(cond) * 0xffffffffffffffff
|
||||||
|
u[0] ^= b & (u[0] ^ neg[0])
|
||||||
|
u[1] ^= b & (u[1] ^ neg[1])
|
||||||
|
u[2] ^= b & (u[2] ^ neg[2])
|
||||||
|
u[3] ^= b & (u[3] ^ neg[3])
|
||||||
|
u[4] ^= b & (u[4] ^ neg[4])
|
||||||
|
}
|
||||||
|
|
||||||
|
// FeIsNegative returns 1 if u is negative, and 0 otherwise.
|
||||||
|
func FeIsNegative(u *FieldElement) int {
|
||||||
|
var b [32]byte
|
||||||
|
FeToBytes(&b, u)
|
||||||
|
return int(b[0] & 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FeAbs sets out to |u|. out and u are allowed to overlap.
|
||||||
|
func FeAbs(out, u *FieldElement) {
|
||||||
|
var neg FieldElement
|
||||||
|
FeNeg(&neg, u)
|
||||||
|
FeSelect(out, &neg, u, FeIsNegative(u))
|
||||||
|
}
|
|
@ -148,6 +148,21 @@ func vartimeEqual(x, y FieldElement) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFeEqual(t *testing.T) {
|
||||||
|
var x FieldElement = [5]uint64{1, 1, 1, 1, 1}
|
||||||
|
var y FieldElement = [5]uint64{5, 4, 3, 2, 1}
|
||||||
|
|
||||||
|
eq := FeEqual(&x, &x)
|
||||||
|
if !eq {
|
||||||
|
t.Errorf("wrong about equality")
|
||||||
|
}
|
||||||
|
|
||||||
|
eq = FeEqual(&x, &y)
|
||||||
|
if eq {
|
||||||
|
t.Errorf("wrong about inequality")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFeInvert(t *testing.T) {
|
func TestFeInvert(t *testing.T) {
|
||||||
var x FieldElement = [5]uint64{1, 1, 1, 1, 1}
|
var x FieldElement = [5]uint64{1, 1, 1, 1, 1}
|
||||||
var one FieldElement = [5]uint64{1, 0, 0, 0, 0}
|
var one FieldElement = [5]uint64{1, 0, 0, 0, 0}
|
|
@ -8,26 +8,40 @@
|
||||||
package ristretto255
|
package ristretto255
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gtank/ristretto255/internal/edwards25519"
|
"github.com/gtank/ristretto255/internal/group"
|
||||||
|
"github.com/gtank/ristretto255/internal/radix51"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
sqrtM1 = fieldElementFromDecimal(
|
||||||
|
"19681161376707505956807079304988542015446066515923890162744021073123829784752")
|
||||||
|
sqrtADMinusOne = fieldElementFromDecimal(
|
||||||
|
"25063068953384623474111414158702152701244531502492656460079210482610430750235")
|
||||||
|
invSqrtAMinusD = fieldElementFromDecimal(
|
||||||
|
"54469307008909316920995813868745141605393597292927456921205312896311721017578")
|
||||||
|
oneMinusDSQ = fieldElementFromDecimal(
|
||||||
|
"1159843021668779879193775521855586647937357759715417654439879720876111806838")
|
||||||
|
dMinusOneSQ = fieldElementFromDecimal(
|
||||||
|
"40440834346308536858101042469323190826248399146238708352240133220865137265952")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Element is an element of the ristretto255 prime-order group.
|
// Element is an element of the ristretto255 prime-order group.
|
||||||
type Element struct {
|
type Element struct {
|
||||||
r edwards25519.ExtendedGroupElement
|
r group.ExtendedGroupElement
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal returns 1 if e is equivalent to ee, and 0 otherwise.
|
// Equal returns 1 if e is equivalent to ee, and 0 otherwise.
|
||||||
// Note that Elements must not be compared in any other way.
|
// Note that Elements must not be compared in any other way.
|
||||||
func (e *Element) Equal(ee *Element) int {
|
func (e *Element) Equal(ee *Element) int {
|
||||||
var f0, f1 edwards25519.FieldElement
|
var f0, f1 radix51.FieldElement
|
||||||
|
|
||||||
edwards25519.FeMul(&f0, &e.r.X, &ee.r.Y) // x1 * y2
|
radix51.FeMul(&f0, &e.r.X, &ee.r.Y) // x1 * y2
|
||||||
edwards25519.FeMul(&f1, &e.r.Y, &ee.r.X) // y1 * x2
|
radix51.FeMul(&f1, &e.r.Y, &ee.r.X) // y1 * x2
|
||||||
out := edwards25519.FeEqual(&f0, &f1)
|
out := radix51.FeEqual(&f0, &f1)
|
||||||
|
|
||||||
edwards25519.FeMul(&f0, &e.r.Y, &ee.r.Y) // y1 * y2
|
radix51.FeMul(&f0, &e.r.Y, &ee.r.Y) // y1 * y2
|
||||||
edwards25519.FeMul(&f1, &e.r.X, &ee.r.X) // x1 * x2
|
radix51.FeMul(&f1, &e.r.X, &ee.r.X) // x1 * x2
|
||||||
out = out | edwards25519.FeEqual(&f0, &f1)
|
out = out | radix51.FeEqual(&f0, &f1)
|
||||||
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
@ -37,7 +51,8 @@ func (e *Element) Equal(ee *Element) int {
|
||||||
// a random element.
|
// a random element.
|
||||||
func (e *Element) FromUniformBytes(b []byte) {
|
func (e *Element) FromUniformBytes(b []byte) {
|
||||||
if len(b) != 64 {
|
if len(b) != 64 {
|
||||||
panic("ristretto255: FromUniformBytes called with a byte slice of length different than 64")
|
panic("ristretto255: FromUniformBytes: input is not 64 bytes long")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panic("ristretto255: FromUniformBytes: unimplemented")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue