Compare commits
15 commits
027561bd2a
...
a67b1e9d0a
Author | SHA1 | Date | |
---|---|---|---|
DataHoarder | a67b1e9d0a | ||
DataHoarder | b67b282d40 | ||
DataHoarder | f0596f127a | ||
a7dfd8e4e6 | |||
325f520de7 | |||
c0501e42ed | |||
23384ff85b | |||
16197b4051 | |||
6387a56aa6 | |||
c901e5ec3c | |||
daffb31912 | |||
5caf132ffa | |||
4bafd0bab4 | |||
40637db7b9 | |||
f25ca2c5f0 |
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
|
@ -6,12 +6,12 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go: [ '1.17', '1.x' ]
|
||||
go: [ '1.20', '1.x' ]
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
with: { go-version: "${{ matrix.go }}" }
|
||||
- uses: actions/checkout@v2
|
||||
- run: go test -quickchecks 1 ./...
|
||||
- run: go test -quickchecks 1 -tags purego ./...
|
||||
- run: go test -short ./...
|
||||
- run: go test -short -tags purego ./...
|
||||
- run: GOARCH=arm64 go test -c
|
||||
- run: GOARCH=arm go test -c
|
||||
|
|
|
@ -7,7 +7,7 @@ package edwards25519
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"filippo.io/edwards25519/field"
|
||||
"git.gammaspectra.live/P2Pool/edwards25519/field"
|
||||
)
|
||||
|
||||
// Point types.
|
||||
|
@ -27,13 +27,13 @@ type projP2 struct {
|
|||
//
|
||||
// The zero value is NOT valid, and it may be used only as a receiver.
|
||||
type Point struct {
|
||||
// The point is internally represented in extended coordinates (X, Y, Z, T)
|
||||
// where x = X/Z, y = Y/Z, and xy = T/Z per https://eprint.iacr.org/2008/522.
|
||||
x, y, z, t field.Element
|
||||
|
||||
// Make the type not comparable (i.e. used with == or as a map key), as
|
||||
// equivalent points can be represented by different Go values.
|
||||
_ incomparable
|
||||
|
||||
// The point is internally represented in extended coordinates (X, Y, Z, T)
|
||||
// where x = X/Z, y = Y/Z, and xy = T/Z per https://eprint.iacr.org/2008/522.
|
||||
x, y, z, t field.Element
|
||||
}
|
||||
|
||||
type incomparable [0]func()
|
||||
|
|
|
@ -6,12 +6,10 @@ package edwards25519
|
|||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"filippo.io/edwards25519/field"
|
||||
"git.gammaspectra.live/P2Pool/edwards25519/field"
|
||||
)
|
||||
|
||||
var B = NewGeneratorPoint()
|
||||
|
@ -282,9 +280,6 @@ func TestNonCanonicalPoints(t *testing.T) {
|
|||
var testAllocationsSink byte
|
||||
|
||||
func TestAllocations(t *testing.T) {
|
||||
if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") {
|
||||
t.Skip("skipping allocations test without relevant optimizations")
|
||||
}
|
||||
if allocs := testing.AllocsPerRun(100, func() {
|
||||
p := NewIdentityPoint()
|
||||
p.Add(p, NewGeneratorPoint())
|
||||
|
|
4
extra.go
4
extra.go
|
@ -10,7 +10,7 @@ package edwards25519
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"filippo.io/edwards25519/field"
|
||||
"git.gammaspectra.live/P2Pool/edwards25519/field"
|
||||
)
|
||||
|
||||
// ExtendedCoordinates returns v in extended coordinates (X:Y:Z:T) where
|
||||
|
@ -124,7 +124,7 @@ func (v *Point) MultByCofactor(p *Point) *Point {
|
|||
return v.fromP1xP1(&result)
|
||||
}
|
||||
|
||||
// Given k > 0, set s = s**(2*i).
|
||||
// Given k > 0, set s = s**(2*k).
|
||||
func (s *Scalar) pow2k(k int) {
|
||||
for i := 0; i < k; i++ {
|
||||
s.Multiply(s, s)
|
||||
|
|
|
@ -110,7 +110,7 @@ func TestScalarInvert(t *testing.T) {
|
|||
return check.Equal(scOne) == 1 && isReduced(xInv.Bytes())
|
||||
}
|
||||
|
||||
if err := quick.Check(invertWorks, quickCheckConfig32); err != nil {
|
||||
if err := quick.Check(invertWorks, quickCheckConfig(32)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ func TestMultiScalarMultMatchesBaseMult(t *testing.T) {
|
|||
return p.Equal(&check) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(multiScalarMultMatchesBaseMult, quickCheckConfig32); err != nil {
|
||||
if err := quick.Check(multiScalarMultMatchesBaseMult, quickCheckConfig(32)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ func TestVarTimeMultiScalarMultMatchesBaseMult(t *testing.T) {
|
|||
return p.Equal(&check) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(varTimeMultiScalarMultMatchesBaseMult, quickCheckConfig32); err != nil {
|
||||
if err := quick.Check(varTimeMultiScalarMultMatchesBaseMult, quickCheckConfig(32)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module asm
|
||||
module std/crypto/internal/edwards25519/field/_asm
|
||||
|
||||
go 1.18
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v0.0.0
|
||||
|
|
|
@ -129,9 +129,9 @@ func TestAliasing(t *testing.T) {
|
|||
var err error
|
||||
switch {
|
||||
case tt.oneArgF != nil:
|
||||
err = quick.Check(checkAliasingOneArg(tt.oneArgF), &quick.Config{MaxCountScale: 1 << 8})
|
||||
err = quick.Check(checkAliasingOneArg(tt.oneArgF), quickCheckConfig(256))
|
||||
case tt.twoArgsF != nil:
|
||||
err = quick.Check(checkAliasingTwoArgs(tt.twoArgsF), &quick.Config{MaxCountScale: 1 << 8})
|
||||
err = quick.Check(checkAliasingTwoArgs(tt.twoArgsF), quickCheckConfig(256))
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("%v: %v", tt.name, err)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build arm64,gc,!purego
|
||||
//go:build arm64 && gc && !purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ func feMulGeneric(v, a, b *Element) {
|
|||
rr4 := r4.lo&maskLow51Bits + c3
|
||||
|
||||
// Now all coefficients fit into 64-bit registers but are still too large to
|
||||
// be passed around as a Element. We therefore do one last carry chain,
|
||||
// be passed around as an Element. We therefore do one last carry chain,
|
||||
// where the carries will be small enough to fit in the wiggle room above 2⁵¹.
|
||||
*v = Element{rr0, rr1, rr2, rr3, rr4}
|
||||
v.carryPropagate()
|
||||
|
@ -245,7 +245,7 @@ func feSquareGeneric(v, a *Element) {
|
|||
v.carryPropagate()
|
||||
}
|
||||
|
||||
// carryPropagate brings the limbs below 52 bits by applying the reduction
|
||||
// carryPropagateGeneric brings the limbs below 52 bits by applying the reduction
|
||||
// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry.
|
||||
func (v *Element) carryPropagateGeneric() *Element {
|
||||
c0 := v.l0 >> 51
|
||||
|
|
|
@ -21,9 +21,15 @@ func (v Element) String() string {
|
|||
return hex.EncodeToString(v.Bytes())
|
||||
}
|
||||
|
||||
// quickCheckConfig1024 will make each quickcheck test run (1024 * -quickchecks)
|
||||
// times. The default value of -quickchecks is 100.
|
||||
var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10}
|
||||
// quickCheckConfig returns a quick.Config that scales the max count by the
|
||||
// given factor if the -short flag is not set.
|
||||
func quickCheckConfig(slowScale int) *quick.Config {
|
||||
cfg := new(quick.Config)
|
||||
if !testing.Short() {
|
||||
cfg.MaxCountScale = float64(slowScale)
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
func generateFieldElement(rand *mathrand.Rand) Element {
|
||||
const maskLow52Bits = (1 << 52) - 1
|
||||
|
@ -114,7 +120,7 @@ func TestMultiplyDistributesOverAdd(t *testing.T) {
|
|||
return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2)
|
||||
}
|
||||
|
||||
if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil {
|
||||
if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig(1024)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -419,7 +425,7 @@ func TestMult32(t *testing.T) {
|
|||
return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2)
|
||||
}
|
||||
|
||||
if err := quick.Check(mult32EquivalentToMul, quickCheckConfig1024); err != nil {
|
||||
if err := quick.Check(mult32EquivalentToMul, quickCheckConfig(1024)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -498,7 +504,7 @@ func TestCarryPropagate(t *testing.T) {
|
|||
return *t1 == *t2 && isInBounds(t2)
|
||||
}
|
||||
|
||||
if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil {
|
||||
if err := quick.Check(asmLikeGeneric, quickCheckConfig(1024)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
|
@ -522,7 +528,7 @@ func TestFeSquare(t *testing.T) {
|
|||
return t1 == t2 && isInBounds(&t2)
|
||||
}
|
||||
|
||||
if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil {
|
||||
if err := quick.Check(asmLikeGeneric, quickCheckConfig(1024)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -546,7 +552,7 @@ func TestFeMul(t *testing.T) {
|
|||
b1 == b2 && isInBounds(&b2)
|
||||
}
|
||||
|
||||
if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil {
|
||||
if err := quick.Check(asmLikeGeneric, quickCheckConfig(1024)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
|
4
go.mod
4
go.mod
|
@ -1,3 +1,3 @@
|
|||
module filippo.io/edwards25519
|
||||
module git.gammaspectra.live/P2Pool/edwards25519
|
||||
|
||||
go 1.17
|
||||
go 1.20
|
||||
|
|
|
@ -104,7 +104,7 @@ func (s *Scalar) Set(x *Scalar) *Scalar {
|
|||
// If x is not of the right length, SetUniformBytes returns nil and an error,
|
||||
// and the receiver is unchanged.
|
||||
//
|
||||
// SetUniformBytes can be used to set s to an uniformly distributed value given
|
||||
// SetUniformBytes can be used to set s to a uniformly distributed value given
|
||||
// 64 uniformly distributed random bytes.
|
||||
func (s *Scalar) SetUniformBytes(x []byte) (*Scalar, error) {
|
||||
if len(x) != 64 {
|
||||
|
|
|
@ -103,7 +103,7 @@ func TestScalarAliasing(t *testing.T) {
|
|||
}, v, x, y)
|
||||
},
|
||||
} {
|
||||
err := quick.Check(f, &quick.Config{MaxCountScale: 1 << 5})
|
||||
err := quick.Check(f, quickCheckConfig(32))
|
||||
if err != nil {
|
||||
t.Errorf("%v: %v", name, err)
|
||||
}
|
||||
|
|
126
scalar_fiat.go
126
scalar_fiat.go
|
@ -41,7 +41,7 @@ package edwards25519
|
|||
import "math/bits"
|
||||
|
||||
type fiatScalarUint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
|
||||
type fiatScalarInt1 int64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
|
||||
type fiatScalarInt1 int64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
|
||||
|
||||
// The type fiatScalarMontgomeryDomainFieldElement is a field element in the Montgomery domain.
|
||||
//
|
||||
|
@ -56,14 +56,18 @@ type fiatScalarNonMontgomeryDomainFieldElement [4]uint64
|
|||
// fiatScalarCmovznzU64 is a single-word conditional move.
|
||||
//
|
||||
// Postconditions:
|
||||
// out1 = (if arg1 = 0 then arg2 else arg3)
|
||||
//
|
||||
// out1 = (if arg1 = 0 then arg2 else arg3)
|
||||
//
|
||||
// Input Bounds:
|
||||
// arg1: [0x0 ~> 0x1]
|
||||
// arg2: [0x0 ~> 0xffffffffffffffff]
|
||||
// arg3: [0x0 ~> 0xffffffffffffffff]
|
||||
//
|
||||
// arg1: [0x0 ~> 0x1]
|
||||
// arg2: [0x0 ~> 0xffffffffffffffff]
|
||||
// arg3: [0x0 ~> 0xffffffffffffffff]
|
||||
//
|
||||
// Output Bounds:
|
||||
// out1: [0x0 ~> 0xffffffffffffffff]
|
||||
//
|
||||
// out1: [0x0 ~> 0xffffffffffffffff]
|
||||
func fiatScalarCmovznzU64(out1 *uint64, arg1 fiatScalarUint1, arg2 uint64, arg3 uint64) {
|
||||
x1 := (uint64(arg1) * 0xffffffffffffffff)
|
||||
x2 := ((x1 & arg3) | ((^x1) & arg2))
|
||||
|
@ -73,12 +77,14 @@ func fiatScalarCmovznzU64(out1 *uint64, arg1 fiatScalarUint1, arg2 uint64, arg3
|
|||
// fiatScalarMul multiplies two field elements in the Montgomery domain.
|
||||
//
|
||||
// Preconditions:
|
||||
// 0 ≤ eval arg1 < m
|
||||
// 0 ≤ eval arg2 < m
|
||||
// Postconditions:
|
||||
// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
//
|
||||
// 0 ≤ eval arg1 < m
|
||||
// 0 ≤ eval arg2 < m
|
||||
//
|
||||
// Postconditions:
|
||||
//
|
||||
// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
func fiatScalarMul(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement, arg2 *fiatScalarMontgomeryDomainFieldElement) {
|
||||
x1 := arg1[1]
|
||||
x2 := arg1[2]
|
||||
|
@ -367,12 +373,14 @@ func fiatScalarMul(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScala
|
|||
// fiatScalarAdd adds two field elements in the Montgomery domain.
|
||||
//
|
||||
// Preconditions:
|
||||
// 0 ≤ eval arg1 < m
|
||||
// 0 ≤ eval arg2 < m
|
||||
// Postconditions:
|
||||
// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
//
|
||||
// 0 ≤ eval arg1 < m
|
||||
// 0 ≤ eval arg2 < m
|
||||
//
|
||||
// Postconditions:
|
||||
//
|
||||
// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
func fiatScalarAdd(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement, arg2 *fiatScalarMontgomeryDomainFieldElement) {
|
||||
var x1 uint64
|
||||
var x2 uint64
|
||||
|
@ -417,12 +425,14 @@ func fiatScalarAdd(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScala
|
|||
// fiatScalarSub subtracts two field elements in the Montgomery domain.
|
||||
//
|
||||
// Preconditions:
|
||||
// 0 ≤ eval arg1 < m
|
||||
// 0 ≤ eval arg2 < m
|
||||
// Postconditions:
|
||||
// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
//
|
||||
// 0 ≤ eval arg1 < m
|
||||
// 0 ≤ eval arg2 < m
|
||||
//
|
||||
// Postconditions:
|
||||
//
|
||||
// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
func fiatScalarSub(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement, arg2 *fiatScalarMontgomeryDomainFieldElement) {
|
||||
var x1 uint64
|
||||
var x2 uint64
|
||||
|
@ -458,11 +468,13 @@ func fiatScalarSub(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScala
|
|||
// fiatScalarOpp negates a field element in the Montgomery domain.
|
||||
//
|
||||
// Preconditions:
|
||||
// 0 ≤ eval arg1 < m
|
||||
// Postconditions:
|
||||
// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
//
|
||||
// 0 ≤ eval arg1 < m
|
||||
//
|
||||
// Postconditions:
|
||||
//
|
||||
// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
func fiatScalarOpp(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement) {
|
||||
var x1 uint64
|
||||
var x2 uint64
|
||||
|
@ -498,14 +510,20 @@ func fiatScalarOpp(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScala
|
|||
// fiatScalarNonzero outputs a single non-zero word if the input is non-zero and zero otherwise.
|
||||
//
|
||||
// Preconditions:
|
||||
// 0 ≤ eval arg1 < m
|
||||
//
|
||||
// 0 ≤ eval arg1 < m
|
||||
//
|
||||
// Postconditions:
|
||||
// out1 = 0 ↔ eval (from_montgomery arg1) mod m = 0
|
||||
//
|
||||
// out1 = 0 ↔ eval (from_montgomery arg1) mod m = 0
|
||||
//
|
||||
// Input Bounds:
|
||||
// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
|
||||
//
|
||||
// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
|
||||
//
|
||||
// Output Bounds:
|
||||
// out1: [0x0 ~> 0xffffffffffffffff]
|
||||
//
|
||||
// out1: [0x0 ~> 0xffffffffffffffff]
|
||||
func fiatScalarNonzero(out1 *uint64, arg1 *[4]uint64) {
|
||||
x1 := (arg1[0] | (arg1[1] | (arg1[2] | arg1[3])))
|
||||
*out1 = x1
|
||||
|
@ -514,11 +532,13 @@ func fiatScalarNonzero(out1 *uint64, arg1 *[4]uint64) {
|
|||
// fiatScalarFromMontgomery translates a field element out of the Montgomery domain.
|
||||
//
|
||||
// Preconditions:
|
||||
// 0 ≤ eval arg1 < m
|
||||
// Postconditions:
|
||||
// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
//
|
||||
// 0 ≤ eval arg1 < m
|
||||
//
|
||||
// Postconditions:
|
||||
//
|
||||
// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
func fiatScalarFromMontgomery(out1 *fiatScalarNonMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement) {
|
||||
x1 := arg1[0]
|
||||
var x2 uint64
|
||||
|
@ -668,11 +688,13 @@ func fiatScalarFromMontgomery(out1 *fiatScalarNonMontgomeryDomainFieldElement, a
|
|||
// fiatScalarToMontgomery translates a field element into the Montgomery domain.
|
||||
//
|
||||
// Preconditions:
|
||||
// 0 ≤ eval arg1 < m
|
||||
// Postconditions:
|
||||
// eval (from_montgomery out1) mod m = eval arg1 mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
//
|
||||
// 0 ≤ eval arg1 < m
|
||||
//
|
||||
// Postconditions:
|
||||
//
|
||||
// eval (from_montgomery out1) mod m = eval arg1 mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
func fiatScalarToMontgomery(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarNonMontgomeryDomainFieldElement) {
|
||||
x1 := arg1[1]
|
||||
x2 := arg1[2]
|
||||
|
@ -930,14 +952,20 @@ func fiatScalarToMontgomery(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *
|
|||
// fiatScalarToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order.
|
||||
//
|
||||
// Preconditions:
|
||||
// 0 ≤ eval arg1 < m
|
||||
//
|
||||
// 0 ≤ eval arg1 < m
|
||||
//
|
||||
// Postconditions:
|
||||
// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31]
|
||||
//
|
||||
// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31]
|
||||
//
|
||||
// Input Bounds:
|
||||
// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1fffffffffffffff]]
|
||||
//
|
||||
// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1fffffffffffffff]]
|
||||
//
|
||||
// Output Bounds:
|
||||
// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1f]]
|
||||
//
|
||||
// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1f]]
|
||||
func fiatScalarToBytes(out1 *[32]uint8, arg1 *[4]uint64) {
|
||||
x1 := arg1[3]
|
||||
x2 := arg1[2]
|
||||
|
@ -1036,15 +1064,21 @@ func fiatScalarToBytes(out1 *[32]uint8, arg1 *[4]uint64) {
|
|||
// fiatScalarFromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order.
|
||||
//
|
||||
// Preconditions:
|
||||
// 0 ≤ bytes_eval arg1 < m
|
||||
//
|
||||
// 0 ≤ bytes_eval arg1 < m
|
||||
//
|
||||
// Postconditions:
|
||||
// eval out1 mod m = bytes_eval arg1 mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
//
|
||||
// eval out1 mod m = bytes_eval arg1 mod m
|
||||
// 0 ≤ eval out1 < m
|
||||
//
|
||||
// Input Bounds:
|
||||
// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1f]]
|
||||
//
|
||||
// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1f]]
|
||||
//
|
||||
// Output Bounds:
|
||||
// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1fffffffffffffff]]
|
||||
//
|
||||
// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1fffffffffffffff]]
|
||||
func fiatScalarFromBytes(out1 *[4]uint64, arg1 *[32]uint8) {
|
||||
x1 := (uint64(arg1[31]) << 56)
|
||||
x2 := (uint64(arg1[30]) << 48)
|
||||
|
|
|
@ -14,6 +14,16 @@ import (
|
|||
"testing/quick"
|
||||
)
|
||||
|
||||
// quickCheckConfig returns a quick.Config that scales the max count by the
|
||||
// given factor if the -short flag is not set.
|
||||
func quickCheckConfig(slowScale int) *quick.Config {
|
||||
cfg := new(quick.Config)
|
||||
if !testing.Short() {
|
||||
cfg.MaxCountScale = float64(slowScale)
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
var scOneBytes = [32]byte{1}
|
||||
var scOne, _ = new(Scalar).SetCanonicalBytes(scOneBytes[:])
|
||||
var scMinusOne, _ = new(Scalar).SetCanonicalBytes(scalarMinusOneBytes[:])
|
||||
|
@ -53,15 +63,11 @@ func (Scalar) Generate(rand *mathrand.Rand, size int) reflect.Value {
|
|||
return reflect.ValueOf(val)
|
||||
}
|
||||
|
||||
// quickCheckConfig1024 will make each quickcheck test run (1024 * -quickchecks)
|
||||
// times. The default value of -quickchecks is 100.
|
||||
var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10}
|
||||
|
||||
func TestScalarGenerate(t *testing.T) {
|
||||
f := func(sc Scalar) bool {
|
||||
return isReduced(sc.Bytes())
|
||||
}
|
||||
if err := quick.Check(f, quickCheckConfig1024); err != nil {
|
||||
if err := quick.Check(f, quickCheckConfig(1024)); err != nil {
|
||||
t.Errorf("generated unreduced scalar: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +82,7 @@ func TestScalarSetCanonicalBytes(t *testing.T) {
|
|||
repr := sc.Bytes()
|
||||
return bytes.Equal(in[:], repr) && isReduced(repr)
|
||||
}
|
||||
if err := quick.Check(f1, quickCheckConfig1024); err != nil {
|
||||
if err := quick.Check(f1, quickCheckConfig(1024)); err != nil {
|
||||
t.Errorf("failed bytes->scalar->bytes round-trip: %v", err)
|
||||
}
|
||||
|
||||
|
@ -86,7 +92,7 @@ func TestScalarSetCanonicalBytes(t *testing.T) {
|
|||
}
|
||||
return sc1 == sc2
|
||||
}
|
||||
if err := quick.Check(f2, quickCheckConfig1024); err != nil {
|
||||
if err := quick.Check(f2, quickCheckConfig(1024)); err != nil {
|
||||
t.Errorf("failed scalar->bytes->scalar round-trip: %v", err)
|
||||
}
|
||||
|
||||
|
@ -115,7 +121,7 @@ func TestScalarSetUniformBytes(t *testing.T) {
|
|||
inBig := bigIntFromLittleEndianBytes(in[:])
|
||||
return inBig.Mod(inBig, mod).Cmp(scBig) == 0
|
||||
}
|
||||
if err := quick.Check(f, quickCheckConfig1024); err != nil {
|
||||
if err := quick.Check(f, quickCheckConfig(1024)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +181,7 @@ func TestScalarMultiplyDistributesOverAdd(t *testing.T) {
|
|||
return t1 == t2 && isReduced(reprT1) && isReduced(reprT2)
|
||||
}
|
||||
|
||||
if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil {
|
||||
if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig(1024)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +200,7 @@ func TestScalarAddLikeSubNeg(t *testing.T) {
|
|||
return t1 == t2 && isReduced(t1.Bytes())
|
||||
}
|
||||
|
||||
if err := quick.Check(addLikeSubNeg, quickCheckConfig1024); err != nil {
|
||||
if err := quick.Check(addLikeSubNeg, quickCheckConfig(1024)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,6 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
// quickCheckConfig32 will make each quickcheck test run (32 * -quickchecks)
|
||||
// times. The default value of -quickchecks is 100.
|
||||
quickCheckConfig32 = &quick.Config{MaxCountScale: 1 << 5}
|
||||
|
||||
// a random scalar generated using dalek.
|
||||
dalekScalar, _ = (&Scalar{}).SetCanonicalBytes([]byte{219, 106, 114, 9, 174, 249, 155, 89, 69, 203, 201, 93, 92, 116, 234, 187, 78, 115, 103, 172, 182, 98, 62, 103, 187, 136, 13, 100, 248, 110, 12, 4})
|
||||
// the above, times the edwards25519 basepoint.
|
||||
|
@ -83,7 +79,7 @@ func TestScalarMultDistributesOverAdd(t *testing.T) {
|
|||
return check.Equal(&r) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(scalarMultDistributesOverAdd, quickCheckConfig32); err != nil {
|
||||
if err := quick.Check(scalarMultDistributesOverAdd, quickCheckConfig(32)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +101,7 @@ func TestScalarMultNonIdentityPoint(t *testing.T) {
|
|||
return p.Equal(&q) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(scalarMultNonIdentityPoint, quickCheckConfig32); err != nil {
|
||||
if err := quick.Check(scalarMultNonIdentityPoint, quickCheckConfig(32)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +145,7 @@ func TestScalarMultMatchesBaseMult(t *testing.T) {
|
|||
return p.Equal(&q) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(scalarMultMatchesBaseMult, quickCheckConfig32); err != nil {
|
||||
if err := quick.Check(scalarMultMatchesBaseMult, quickCheckConfig(32)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +173,7 @@ func TestVarTimeDoubleBaseMultMatchesBaseMult(t *testing.T) {
|
|||
return p.Equal(&check) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(varTimeDoubleBaseMultMatchesBaseMult, quickCheckConfig32); err != nil {
|
||||
if err := quick.Check(varTimeDoubleBaseMultMatchesBaseMult, quickCheckConfig(32)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ func (v *projLookupTable) FromP3(q *Point) {
|
|||
tmpP3 := Point{}
|
||||
tmpP1xP1 := projP1xP1{}
|
||||
for i := 0; i < 7; i++ {
|
||||
// Compute (i+1)*Q as Q + i*Q and convert to a ProjCached
|
||||
// Compute (i+1)*Q as Q + i*Q and convert to a projCached
|
||||
// This is needlessly complicated because the API has explicit
|
||||
// receivers instead of creating stack objects and relying on RVO
|
||||
v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(q, &v.points[i])))
|
||||
|
@ -53,7 +53,7 @@ func (v *affineLookupTable) FromP3(q *Point) {
|
|||
tmpP3 := Point{}
|
||||
tmpP1xP1 := projP1xP1{}
|
||||
for i := 0; i < 7; i++ {
|
||||
// Compute (i+1)*Q as Q + i*Q and convert to AffineCached
|
||||
// Compute (i+1)*Q as Q + i*Q and convert to affineCached
|
||||
v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(q, &v.points[i])))
|
||||
}
|
||||
}
|
||||
|
|
128
unsafe.go
Normal file
128
unsafe.go
Normal file
|
@ -0,0 +1,128 @@
|
|||
package edwards25519
|
||||
|
||||
// UnsafeVarTimeScalarMult sets v = x * q, and returns v., and returns v. Execution time depends on the inputs.
|
||||
// Deprecated: Unsafe for private operations
|
||||
func (v *Point) UnsafeVarTimeScalarMult(x *Scalar, q *Point) *Point {
|
||||
checkInitialized(q)
|
||||
|
||||
// Build lookup table for point q
|
||||
var table nafLookupTable5
|
||||
table.FromP3(q)
|
||||
// Compute a NAF for scalar x
|
||||
naf := x.nonAdjacentForm(5)
|
||||
|
||||
multiple := &projCached{}
|
||||
tmp1 := &projP1xP1{}
|
||||
tmp2 := &projP2{}
|
||||
tmp2.Zero()
|
||||
|
||||
// Skip the trailing zeroes
|
||||
i := 255
|
||||
for ; i >= 0; i-- {
|
||||
if naf[i] != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if i == -1 {
|
||||
v.fromP2(tmp2)
|
||||
return v
|
||||
}
|
||||
|
||||
// Move from high to low bits, doubling the accumulator
|
||||
// at each iteration and checking whether there is a nonzero
|
||||
// coefficient to look up a multiple of.
|
||||
//
|
||||
// Skip trying to find the first nonzero coefficent, because
|
||||
// searching might be more work than a few extra doublings.
|
||||
for ; i >= 0; i-- {
|
||||
tmp1.Double(tmp2)
|
||||
if naf[i] > 0 {
|
||||
v.fromP1xP1(tmp1)
|
||||
table.SelectInto(multiple, naf[i])
|
||||
tmp1.Add(v, multiple)
|
||||
} else if naf[i] < 0 {
|
||||
v.fromP1xP1(tmp1)
|
||||
table.SelectInto(multiple, -naf[i])
|
||||
tmp1.Sub(v, multiple)
|
||||
}
|
||||
|
||||
tmp2.FromP1xP1(tmp1)
|
||||
}
|
||||
|
||||
v.fromP2(tmp2)
|
||||
return v
|
||||
}
|
||||
|
||||
// UnsafeVarTimeScalarBaseMult sets v = x * B, where B is the canonical generator, and returns v. Execution time depends on the inputs.
|
||||
// Deprecated: Unsafe for private operations
|
||||
func (v *Point) UnsafeVarTimeScalarBaseMult(x *Scalar) *Point {
|
||||
basepointTable := basepointTable()
|
||||
|
||||
// Write x = sum(x_i * 16^i) so x*B = sum( B*x_i*16^i )
|
||||
// as described in the Ed25519 paper
|
||||
//
|
||||
// Group even and odd coefficients
|
||||
// x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B
|
||||
// + x_1*16^1*B + x_3*16^3*B + ... + x_63*16^63*B
|
||||
// x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B
|
||||
// + 16*( x_1*16^0*B + x_3*16^2*B + ... + x_63*16^62*B)
|
||||
//
|
||||
// We use a lookup table for each i to get x_i*16^(2*i)*B
|
||||
// and do four doublings to multiply by 16.
|
||||
digits := x.signedRadix16()
|
||||
|
||||
multiple := &affineCached{}
|
||||
tmp1 := &projP1xP1{}
|
||||
tmp2 := &projP2{}
|
||||
|
||||
// Accumulate the odd components first
|
||||
v.Set(NewIdentityPoint())
|
||||
for i := 1; i < 64; i += 2 {
|
||||
basepointTable[i/2].UnsafeVarTimeSelectInto(multiple, digits[i])
|
||||
tmp1.AddAffine(v, multiple)
|
||||
v.fromP1xP1(tmp1)
|
||||
}
|
||||
|
||||
// Multiply by 16
|
||||
tmp2.FromP3(v) // tmp2 = v in P2 coords
|
||||
tmp1.Double(tmp2) // tmp1 = 2*v in P1xP1 coords
|
||||
tmp2.FromP1xP1(tmp1) // tmp2 = 2*v in P2 coords
|
||||
tmp1.Double(tmp2) // tmp1 = 4*v in P1xP1 coords
|
||||
tmp2.FromP1xP1(tmp1) // tmp2 = 4*v in P2 coords
|
||||
tmp1.Double(tmp2) // tmp1 = 8*v in P1xP1 coords
|
||||
tmp2.FromP1xP1(tmp1) // tmp2 = 8*v in P2 coords
|
||||
tmp1.Double(tmp2) // tmp1 = 16*v in P1xP1 coords
|
||||
v.fromP1xP1(tmp1) // now v = 16*(odd components)
|
||||
|
||||
// Accumulate the even components
|
||||
for i := 0; i < 64; i += 2 {
|
||||
basepointTable[i/2].UnsafeVarTimeSelectInto(multiple, digits[i])
|
||||
tmp1.AddAffine(v, multiple)
|
||||
v.fromP1xP1(tmp1)
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// Set dest to x*Q, where -8 <= x <= 8, in variable time.
|
||||
// Deprecated: Unsafe for private operations
|
||||
func (v *affineLookupTable) UnsafeVarTimeSelectInto(dest *affineCached, x int8) {
|
||||
if x == 0 {
|
||||
dest.Zero()
|
||||
return
|
||||
}
|
||||
|
||||
// Compute xabs = |x|
|
||||
xmask := x >> 7
|
||||
xabs := uint8((x + xmask) ^ xmask)
|
||||
|
||||
// Set dest = j*Q
|
||||
*dest = v.points[xabs-1]
|
||||
|
||||
// Now dest = |x|*Q, conditionally negate to get x*Q
|
||||
if (xmask & 1) > 0 {
|
||||
dest.YplusX, dest.YminusX = dest.YminusX, dest.YplusX
|
||||
dest.T2d.Negate(&dest.T2d)
|
||||
}
|
||||
}
|
100
unsafe_test.go
Normal file
100
unsafe_test.go
Normal file
|
@ -0,0 +1,100 @@
|
|||
package edwards25519
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"testing/quick"
|
||||
)
|
||||
|
||||
func TestUnsafeVarTimeScalarMultMatchesScalarBaseMult(t *testing.T) {
|
||||
unsafeVarTimeScalarMultMatchesScalarMult := func(x Scalar) bool {
|
||||
var p, check Point
|
||||
|
||||
p.UnsafeVarTimeScalarMult(&x, B)
|
||||
|
||||
check.ScalarBaseMult(&x)
|
||||
|
||||
checkOnCurve(t, &p, &check)
|
||||
return p.Equal(&check) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(unsafeVarTimeScalarMultMatchesScalarMult, quickCheckConfig(32)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnsafeVarTimeScalarBaseMultMatchesScalarBaseMult(t *testing.T) {
|
||||
unsafeVarTimeScalarBaseMultMatchesScalarMult := func(x Scalar) bool {
|
||||
var p, check Point
|
||||
|
||||
p.UnsafeVarTimeScalarBaseMult(&x)
|
||||
|
||||
check.ScalarBaseMult(&x)
|
||||
|
||||
checkOnCurve(t, &p, &check)
|
||||
return p.Equal(&check) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(unsafeVarTimeScalarBaseMultMatchesScalarMult, quickCheckConfig(32)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnsafeVarTimeScalarMultNonIdentityPoint(t *testing.T) {
|
||||
// Check whether p.ScalarMult and q.ScalaBaseMult give the same,
|
||||
// when p and q are originally set to the base point.
|
||||
|
||||
unsafeVarTimeScalarMultNonIdentityPoint := func(x Scalar) bool {
|
||||
var p, q Point
|
||||
p.Set(B)
|
||||
q.Set(B)
|
||||
|
||||
p.UnsafeVarTimeScalarMult(&x, B)
|
||||
q.ScalarBaseMult(&x)
|
||||
|
||||
checkOnCurve(t, &p, &q)
|
||||
|
||||
return p.Equal(&q) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(unsafeVarTimeScalarMultNonIdentityPoint, quickCheckConfig(32)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnsafeVarTimeScalarBaseMultNonIdentityPoint(t *testing.T) {
|
||||
// Check whether p.ScalarMult and q.ScalaBaseMult give the same,
|
||||
// when p and q are originally set to the base point.
|
||||
|
||||
unsafeVarTimeScalarBaseMultNonIdentityPoint := func(x Scalar) bool {
|
||||
var p, q Point
|
||||
p.Set(B)
|
||||
q.Set(B)
|
||||
|
||||
p.UnsafeVarTimeScalarBaseMult(&x)
|
||||
q.ScalarBaseMult(&x)
|
||||
|
||||
checkOnCurve(t, &p, &q)
|
||||
|
||||
return p.Equal(&q) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(unsafeVarTimeScalarBaseMultNonIdentityPoint, quickCheckConfig(32)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnsafeVarTimeScalarMult(b *testing.B) {
|
||||
var p Point
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
p.UnsafeVarTimeScalarMult(dalekScalar, B)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnsafeVarTimeScalarBaseMult(b *testing.B) {
|
||||
var p Point
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
p.UnsafeVarTimeScalarBaseMult(dalekScalar)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue