@@ -8,6 +8,7 @@ matrix: | |||||
fast_finish: true | fast_finish: true | ||||
script: | script: | ||||
- make test | |||||
- make bench | - make bench | ||||
- make cover | - make cover | ||||
- NOASM=1 make cover-sidh | - NOASM=1 make cover-sidh | ||||
@@ -3,44 +3,61 @@ MK_FILE_PATH = $(lastword $(MAKEFILE_LIST)) | |||||
PRJ_DIR = $(abspath $(dir $(MK_FILE_PATH))) | PRJ_DIR = $(abspath $(dir $(MK_FILE_PATH))) | ||||
GOPATH_LOCAL = $(PRJ_DIR)/build | GOPATH_LOCAL = $(PRJ_DIR)/build | ||||
GOPATH_DIR = github.com/cloudflare/p751sidh | GOPATH_DIR = github.com/cloudflare/p751sidh | ||||
CSHAKE_PKG = github.com/henrydcase/nobs/hash/sha3 | |||||
CSHAKE_PKG ?= github.com/henrydcase/nobs/hash/sha3 | |||||
CPU_PKG = golang.org/x/sys/cpu | CPU_PKG = golang.org/x/sys/cpu | ||||
TARGETS = p751toolbox sidh sike | TARGETS = p751toolbox sidh sike | ||||
GO ?= go | GO ?= go | ||||
GOARCH ?= | GOARCH ?= | ||||
OPTS_GCCGO ?= -compiler gccgo -O2 -g | OPTS_GCCGO ?= -compiler gccgo -O2 -g | ||||
OPTS_TAGS ?= -tags=noasm | |||||
OPTS ?= | OPTS ?= | ||||
OPTS_TAGS ?= -tags=noasm | |||||
NOASM ?= | NOASM ?= | ||||
# -run="NonExistent" is set to make sure tests are not run before benchmarking | |||||
BENCH_OPTS ?= -bench=. -run="NonExistent" | |||||
# whether to be verbose | |||||
V ?= 1 | |||||
ifeq ($(NOASM),1) | ifeq ($(NOASM),1) | ||||
OPTS+=$(OPTS_TAGS) | OPTS+=$(OPTS_TAGS) | ||||
endif | endif | ||||
ifeq ($(V),1) | |||||
OPTS += -v # Be verbose | |||||
BENCH_OPTS += -gcflags=-m # Show results from inlining | |||||
endif | |||||
clean: | clean: | ||||
rm -rf $(GOPATH_LOCAL) | rm -rf $(GOPATH_LOCAL) | ||||
rm -rf coverage*.txt | rm -rf coverage*.txt | ||||
prep: | |||||
build_env: | |||||
GOPATH=$(GOPATH_LOCAL) $(GO) get $(CSHAKE_PKG) $(CPU_PKG) | GOPATH=$(GOPATH_LOCAL) $(GO) get $(CSHAKE_PKG) $(CPU_PKG) | ||||
mkdir -p $(GOPATH_LOCAL)/src/$(GOPATH_DIR) | mkdir -p $(GOPATH_LOCAL)/src/$(GOPATH_DIR) | ||||
cp -rf p751toolbox $(GOPATH_LOCAL)/src/$(GOPATH_DIR) | |||||
cp -rf sidh $(GOPATH_LOCAL)/src/$(GOPATH_DIR) | |||||
cp -rf sike $(GOPATH_LOCAL)/src/$(GOPATH_DIR) | |||||
cp -rf etc $(GOPATH_LOCAL)/src/$(GOPATH_DIR) | cp -rf etc $(GOPATH_LOCAL)/src/$(GOPATH_DIR) | ||||
test-%: prep | |||||
GOPATH=$(GOPATH_LOCAL) $(GO) test -v $(OPTS) $(GOPATH_DIR)/$* | |||||
copy-target-%: | |||||
cp -rf $* $(GOPATH_LOCAL)/src/$(GOPATH_DIR) | |||||
bench-%: prep | |||||
cd $*; GOPATH=$(GOPATH_LOCAL) $(GO) test -v $(OPTS) -bench=. | |||||
prep_targets: build_env $(addprefix copy-target-, $(TARGETS)) | |||||
cover-%: prep | |||||
install-%: prep_targets | |||||
GOPATH=$(GOPATH_LOCAL) $(GO) install $(OPTS) $(GOPATH_DIR)/$* | |||||
test-%: prep_targets | |||||
GOPATH=$(GOPATH_LOCAL) $(GO) vet $(GOPATH_DIR)/$* | |||||
GOPATH=$(GOPATH_LOCAL) $(GO) test $(OPTS) $(GOPATH_DIR)/$* | |||||
bench-%: prep_targets | |||||
cd $*; GOPATH=$(GOPATH_LOCAL) $(GO) test $(OPTS) $(BENCH_OPTS) | |||||
cover-%: prep_targets | |||||
GOPATH=$(GOPATH_LOCAL) $(GO) test \ | GOPATH=$(GOPATH_LOCAL) $(GO) test \ | ||||
-race -coverprofile=coverage_$*.txt -covermode=atomic $(OPTS) $(GOPATH_DIR)/$* | -race -coverprofile=coverage_$*.txt -covermode=atomic $(OPTS) $(GOPATH_DIR)/$* | ||||
cat coverage_$*.txt >> coverage.txt | cat coverage_$*.txt >> coverage.txt | ||||
rm coverage_$*.txt | rm coverage_$*.txt | ||||
test: $(addprefix test-, $(TARGETS)) | |||||
bench: $(addprefix bench-, $(TARGETS)) | |||||
cover: $(addprefix cover-, $(TARGETS)) | |||||
bench: $(addprefix bench-, $(TARGETS)) | |||||
cover: $(addprefix cover-, $(TARGETS)) | |||||
install: $(addprefix install-, $(TARGETS)) | |||||
test: $(addprefix test-, $(TARGETS)) | |||||
@@ -28,15 +28,6 @@ type ProjectivePoint struct { | |||||
Z ExtensionFieldElement | Z ExtensionFieldElement | ||||
} | } | ||||
// A point on the projective line P^1(F_p). | |||||
// | |||||
// This represents a point on the (Kummer line) of the prime-field subgroup of | |||||
// the base curve E_0(F_p), defined by E_0 : y^2 = x^3 + x. | |||||
type ProjectivePrimeFieldPoint struct { | |||||
X PrimeFieldElement | |||||
Z PrimeFieldElement | |||||
} | |||||
func (params *ProjectiveCurveParameters) FromAffine(a *ExtensionFieldElement) { | func (params *ProjectiveCurveParameters) FromAffine(a *ExtensionFieldElement) { | ||||
params.A = *a | params.A = *a | ||||
params.C.One() | params.C.One() | ||||
@@ -158,34 +149,17 @@ func (cparams *ProjectiveCurveParameters) RecoverCurveCoefficients4(coefEq *Curv | |||||
return | return | ||||
} | } | ||||
func (point *ProjectivePoint) FromAffinePrimeField(x *PrimeFieldElement) { | |||||
point.X.A = x.A | |||||
point.X.B = zeroExtensionField.B | |||||
point.Z = oneExtensionField | |||||
} | |||||
func (point *ProjectivePoint) FromAffine(x *ExtensionFieldElement) { | func (point *ProjectivePoint) FromAffine(x *ExtensionFieldElement) { | ||||
point.X = *x | point.X = *x | ||||
point.Z = oneExtensionField | point.Z = oneExtensionField | ||||
} | } | ||||
func (point *ProjectivePrimeFieldPoint) FromAffine(x *PrimeFieldElement) { | |||||
point.X = *x | |||||
point.Z = onePrimeField | |||||
} | |||||
func (point *ProjectivePoint) ToAffine() *ExtensionFieldElement { | func (point *ProjectivePoint) ToAffine() *ExtensionFieldElement { | ||||
affine_x := new(ExtensionFieldElement) | affine_x := new(ExtensionFieldElement) | ||||
affine_x.Inv(&point.Z).Mul(affine_x, &point.X) | affine_x.Inv(&point.Z).Mul(affine_x, &point.X) | ||||
return affine_x | return affine_x | ||||
} | } | ||||
func (point *ProjectivePrimeFieldPoint) ToAffine() *PrimeFieldElement { | |||||
affine_x := new(PrimeFieldElement) | |||||
affine_x.Inv(&point.Z).Mul(affine_x, &point.X) | |||||
return affine_x | |||||
} | |||||
func (lhs *ProjectivePoint) VartimeEq(rhs *ProjectivePoint) bool { | func (lhs *ProjectivePoint) VartimeEq(rhs *ProjectivePoint) bool { | ||||
var t0, t1 ExtensionFieldElement | var t0, t1 ExtensionFieldElement | ||||
t0.Mul(&lhs.X, &rhs.Z) | t0.Mul(&lhs.X, &rhs.Z) | ||||
@@ -193,23 +167,11 @@ func (lhs *ProjectivePoint) VartimeEq(rhs *ProjectivePoint) bool { | |||||
return t0.VartimeEq(&t1) | return t0.VartimeEq(&t1) | ||||
} | } | ||||
func (lhs *ProjectivePrimeFieldPoint) VartimeEq(rhs *ProjectivePrimeFieldPoint) bool { | |||||
var t0, t1 PrimeFieldElement | |||||
t0.Mul(&lhs.X, &rhs.Z) | |||||
t1.Mul(&lhs.Z, &rhs.X) | |||||
return t0.VartimeEq(&t1) | |||||
} | |||||
func ProjectivePointConditionalSwap(xP, xQ *ProjectivePoint, choice uint8) { | func ProjectivePointConditionalSwap(xP, xQ *ProjectivePoint, choice uint8) { | ||||
ExtensionFieldConditionalSwap(&xP.X, &xQ.X, choice) | ExtensionFieldConditionalSwap(&xP.X, &xQ.X, choice) | ||||
ExtensionFieldConditionalSwap(&xP.Z, &xQ.Z, choice) | ExtensionFieldConditionalSwap(&xP.Z, &xQ.Z, choice) | ||||
} | } | ||||
func ProjectivePrimeFieldPointConditionalSwap(xP, xQ *ProjectivePrimeFieldPoint, choice uint8) { | |||||
PrimeFieldConditionalSwap(&xP.X, &xQ.X, choice) | |||||
PrimeFieldConditionalSwap(&xP.Z, &xQ.Z, choice) | |||||
} | |||||
// Combined coordinate doubling and differential addition. Takes projective points | // Combined coordinate doubling and differential addition. Takes projective points | ||||
// P,Q,Q-P and (A+2C)/4C curve E coefficient. Returns 2*P and P+Q calculated on E. | // P,Q,Q-P and (A+2C)/4C curve E coefficient. Returns 2*P and P+Q calculated on E. | ||||
// Function is used only by RightToLeftLadder. Corresponds to Algorithm 5 of SIKE | // Function is used only by RightToLeftLadder. Corresponds to Algorithm 5 of SIKE | ||||
@@ -105,16 +105,6 @@ func (dest *ExtensionFieldElement) Mul(lhs, rhs *ExtensionFieldElement) *Extensi | |||||
return dest | return dest | ||||
} | } | ||||
// Set dest = -x | |||||
// | |||||
// Allowed to overlap dest with x. | |||||
// | |||||
// Returns dest to allow chaining operations. | |||||
func (dest *ExtensionFieldElement) Neg(x *ExtensionFieldElement) *ExtensionFieldElement { | |||||
dest.Sub(&zeroExtensionField, x) | |||||
return dest | |||||
} | |||||
// Set dest = 1/x | // Set dest = 1/x | ||||
// | // | ||||
// Allowed to overlap dest with x. | // Allowed to overlap dest with x. | ||||
@@ -142,18 +132,21 @@ func (dest *ExtensionFieldElement) Inv(x *ExtensionFieldElement) *ExtensionField | |||||
fp751MontgomeryReduce(&asq_plus_bsq.A, &asq) // = (a^2 + b^2)*R mod p | fp751MontgomeryReduce(&asq_plus_bsq.A, &asq) // = (a^2 + b^2)*R mod p | ||||
// Now asq_plus_bsq = a^2 + b^2 | // Now asq_plus_bsq = a^2 + b^2 | ||||
var asq_plus_bsq_inv PrimeFieldElement | |||||
asq_plus_bsq_inv.Inv(&asq_plus_bsq) | |||||
c := &asq_plus_bsq_inv.A | |||||
// Invert asq_plus_bsq | |||||
inv := asq_plus_bsq | |||||
inv.Mul(&asq_plus_bsq, &asq_plus_bsq) | |||||
inv.P34(&inv) | |||||
inv.Mul(&inv, &inv) | |||||
inv.Mul(&inv, &asq_plus_bsq) | |||||
var ac fp751X2 | var ac fp751X2 | ||||
fp751Mul(&ac, a, c) | |||||
fp751Mul(&ac, a, &inv.A) | |||||
fp751MontgomeryReduce(&dest.A, &ac) | fp751MontgomeryReduce(&dest.A, &ac) | ||||
var minus_b Fp751Element | var minus_b Fp751Element | ||||
fp751SubReduced(&minus_b, &minus_b, b) | fp751SubReduced(&minus_b, &minus_b, b) | ||||
var minus_bc fp751X2 | var minus_bc fp751X2 | ||||
fp751Mul(&minus_bc, &minus_b, c) | |||||
fp751Mul(&minus_bc, &minus_b, &inv.A) | |||||
fp751MontgomeryReduce(&dest.B, &minus_bc) | fp751MontgomeryReduce(&dest.B, &minus_bc) | ||||
return dest | return dest | ||||
@@ -243,8 +236,20 @@ func (x *ExtensionFieldElement) ToBytes(output []byte) { | |||||
if len(output) < 188 { | if len(output) < 188 { | ||||
panic("output byte slice too short, need 188 bytes") | panic("output byte slice too short, need 188 bytes") | ||||
} | } | ||||
x.A.toBytesFromMontgomeryForm(output[0:94]) | |||||
x.B.toBytesFromMontgomeryForm(output[94:188]) | |||||
var a,b Fp751Element | |||||
FromMontgomery(x, &a, &b) | |||||
// convert to bytes in little endian form. 8*12 = 96, but we drop the last two bytes | |||||
// since p is 751 < 752=94*8 bits. | |||||
for i := 0; i < 94; i++ { | |||||
// set i = j*8 + k | |||||
j := i / 8 | |||||
k := uint64(i % 8) | |||||
output[i] = byte(a[j] >> (8 * k)) | |||||
output[i+94] = byte(b[j] >> (8 * k)) | |||||
} | |||||
} | } | ||||
// Read 188 bytes into the given ExtensionFieldElement. | // Read 188 bytes into the given ExtensionFieldElement. | ||||
@@ -254,8 +259,49 @@ func (x *ExtensionFieldElement) FromBytes(input []byte) { | |||||
if len(input) < 188 { | if len(input) < 188 { | ||||
panic("input byte slice too short, need 188 bytes") | panic("input byte slice too short, need 188 bytes") | ||||
} | } | ||||
x.A.montgomeryFormFromBytes(input[:94]) | |||||
x.B.montgomeryFormFromBytes(input[94:188]) | |||||
for i:=0; i<94; i++ { | |||||
j := i / 8 | |||||
k := uint64(i % 8) | |||||
x.A[j] |= uint64(input[i]) << (8 * k) | |||||
x.B[j] |= uint64(input[i+94]) << (8 * k) | |||||
} | |||||
ToMontgomery(x) | |||||
} | |||||
// Converts values in x.A and x.B to Montgomery domain | |||||
// x.A = x.A * R mod p | |||||
// x.B = x.B * R mod p | |||||
func ToMontgomery(x *ExtensionFieldElement) { | |||||
var aRR fp751X2 | |||||
// convert to montgomery domain | |||||
fp751Mul(&aRR, &x.A, &montgomeryRsq) // = a*R*R | |||||
fp751MontgomeryReduce(&x.A, &aRR) // = a*R mod p | |||||
fp751Mul(&aRR, &x.B, &montgomeryRsq) | |||||
fp751MontgomeryReduce(&x.B, &aRR) | |||||
} | |||||
// Converts values in x.A and x.B from Montgomery domain | |||||
// a = x.A mod p | |||||
// b = x.B mod p | |||||
// | |||||
// After returning from the call x is not modified. | |||||
func FromMontgomery(x *ExtensionFieldElement, a,b *Fp751Element) { | |||||
var aR fp751X2 | |||||
// convert from montgomery domain | |||||
copy(aR[:], x.A[:]) | |||||
fp751MontgomeryReduce(a, &aR) // = a mod p in [0, 2p) | |||||
fp751StrongReduce(a) // = a mod p in [0, p) | |||||
for i:=range(aR) { | |||||
aR[i] = 0 | |||||
} | |||||
copy(aR[:], x.B[:]) | |||||
fp751MontgomeryReduce(b, &aR) | |||||
fp751StrongReduce(b) | |||||
} | } | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
@@ -277,35 +323,6 @@ var onePrimeField = PrimeFieldElement{ | |||||
A: Fp751Element{0x249ad, 0x0, 0x0, 0x0, 0x0, 0x8310000000000000, 0x5527b1e4375c6c66, 0x697797bf3f4f24d0, 0xc89db7b2ac5c4e2e, 0x4ca4b439d2076956, 0x10f7926c7512c7e9, 0x2d5b24bce5e2}, | A: Fp751Element{0x249ad, 0x0, 0x0, 0x0, 0x0, 0x8310000000000000, 0x5527b1e4375c6c66, 0x697797bf3f4f24d0, 0xc89db7b2ac5c4e2e, 0x4ca4b439d2076956, 0x10f7926c7512c7e9, 0x2d5b24bce5e2}, | ||||
} | } | ||||
// Set dest = 0. | |||||
// | |||||
// Returns dest to allow chaining operations. | |||||
func (dest *PrimeFieldElement) Zero() *PrimeFieldElement { | |||||
*dest = zeroPrimeField | |||||
return dest | |||||
} | |||||
// Set dest = 1. | |||||
// | |||||
// Returns dest to allow chaining operations. | |||||
func (dest *PrimeFieldElement) One() *PrimeFieldElement { | |||||
*dest = onePrimeField | |||||
return dest | |||||
} | |||||
// Set dest to x. | |||||
// | |||||
// Returns dest to allow chaining operations. | |||||
func (dest *PrimeFieldElement) SetUint64(x uint64) *PrimeFieldElement { | |||||
var xRR fp751X2 | |||||
dest.A = Fp751Element{} // = 0 | |||||
dest.A[0] = x // = x | |||||
fp751Mul(&xRR, &dest.A, &montgomeryRsq) // = x*R*R | |||||
fp751MontgomeryReduce(&dest.A, &xRR) // = x*R mod p | |||||
return dest | |||||
} | |||||
// Set dest = lhs * rhs. | // Set dest = lhs * rhs. | ||||
// | // | ||||
// Allowed to overlap lhs or rhs with dest. | // Allowed to overlap lhs or rhs with dest. | ||||
@@ -328,104 +345,14 @@ func (dest *PrimeFieldElement) Mul(lhs, rhs *PrimeFieldElement) *PrimeFieldEleme | |||||
// | // | ||||
// Returns dest to allow chaining operations. | // Returns dest to allow chaining operations. | ||||
func (dest *PrimeFieldElement) Pow2k(x *PrimeFieldElement, k uint8) *PrimeFieldElement { | func (dest *PrimeFieldElement) Pow2k(x *PrimeFieldElement, k uint8) *PrimeFieldElement { | ||||
dest.Square(x) | |||||
dest.Mul(x, x) | |||||
for i := uint8(1); i < k; i++ { | for i := uint8(1); i < k; i++ { | ||||
dest.Square(dest) | |||||
dest.Mul(dest, dest) | |||||
} | } | ||||
return dest | return dest | ||||
} | } | ||||
// Set dest = x^2 | |||||
// | |||||
// Allowed to overlap x with dest. | |||||
// | |||||
// Returns dest to allow chaining operations. | |||||
func (dest *PrimeFieldElement) Square(x *PrimeFieldElement) *PrimeFieldElement { | |||||
a := &x.A // = a*R | |||||
b := &x.A // = b*R | |||||
var ab fp751X2 | |||||
fp751Mul(&ab, a, b) // = a*b*R*R | |||||
fp751MontgomeryReduce(&dest.A, &ab) // = a*b*R mod p | |||||
return dest | |||||
} | |||||
// Set dest = -x | |||||
// | |||||
// Allowed to overlap x with dest. | |||||
// | |||||
// Returns dest to allow chaining operations. | |||||
func (dest *PrimeFieldElement) Neg(x *PrimeFieldElement) *PrimeFieldElement { | |||||
dest.Sub(&zeroPrimeField, x) | |||||
return dest | |||||
} | |||||
// Set dest = lhs + rhs. | |||||
// | |||||
// Allowed to overlap lhs or rhs with dest. | |||||
// | |||||
// Returns dest to allow chaining operations. | |||||
func (dest *PrimeFieldElement) Add(lhs, rhs *PrimeFieldElement) *PrimeFieldElement { | |||||
fp751AddReduced(&dest.A, &lhs.A, &rhs.A) | |||||
return dest | |||||
} | |||||
// Set dest = lhs - rhs. | |||||
// | |||||
// Allowed to overlap lhs or rhs with dest. | |||||
// | |||||
// Returns dest to allow chaining operations. | |||||
func (dest *PrimeFieldElement) Sub(lhs, rhs *PrimeFieldElement) *PrimeFieldElement { | |||||
fp751SubReduced(&dest.A, &lhs.A, &rhs.A) | |||||
return dest | |||||
} | |||||
// Returns true if lhs = rhs. Takes variable time. | |||||
func (lhs *PrimeFieldElement) VartimeEq(rhs *PrimeFieldElement) bool { | |||||
return lhs.A.vartimeEq(rhs.A) | |||||
} | |||||
// If choice = 1u8, set (x,y) = (y,x). If choice = 0u8, set (x,y) = (x,y). | |||||
// | |||||
// Returns dest to allow chaining operations. | |||||
func PrimeFieldConditionalSwap(x, y *PrimeFieldElement, choice uint8) { | |||||
fp751ConditionalSwap(&x.A, &y.A, choice) | |||||
} | |||||
// Set dest = sqrt(x), if x is a square. If x is nonsquare dest is undefined. | |||||
// | |||||
// Allowed to overlap x with dest. | |||||
// | |||||
// Returns dest to allow chaining operations. | |||||
func (dest *PrimeFieldElement) Sqrt(x *PrimeFieldElement) *PrimeFieldElement { | |||||
tmp_x := *x // Copy x in case dest == x | |||||
// Since x is assumed to be square, x = y^2 | |||||
dest.P34(x) // dest = (y^2)^((p-3)/4) = y^((p-3)/2) | |||||
dest.Mul(dest, &tmp_x) // dest = y^2 * y^((p-3)/2) = y^((p+1)/2) | |||||
// Now dest^2 = y^(p+1) = y^2 = x, so dest = sqrt(x) | |||||
return dest | |||||
} | |||||
// Set dest = 1/x. | |||||
// | |||||
// Allowed to overlap x with dest. | |||||
// | |||||
// Returns dest to allow chaining operations. | |||||
func (dest *PrimeFieldElement) Inv(x *PrimeFieldElement) *PrimeFieldElement { | |||||
tmp_x := *x // Copy x in case dest == x | |||||
dest.Square(x) // dest = x^2 | |||||
dest.P34(dest) // dest = (x^2)^((p-3)/4) = x^((p-3)/2) | |||||
dest.Square(dest) // dest = x^(p-3) | |||||
dest.Mul(dest, &tmp_x) // dest = x^(p-2) | |||||
return dest | |||||
} | |||||
// Set dest = x^((p-3)/4). If x is square, this is 1/sqrt(x). | // Set dest = x^((p-3)/4). If x is square, this is 1/sqrt(x). | ||||
// | // | ||||
// Allowed to overlap x with dest. | // Allowed to overlap x with dest. | ||||
@@ -448,7 +375,7 @@ func (dest *PrimeFieldElement) P34(x *PrimeFieldElement) *PrimeFieldElement { | |||||
// Build a lookup table of odd multiples of x. | // Build a lookup table of odd multiples of x. | ||||
lookup := [16]PrimeFieldElement{} | lookup := [16]PrimeFieldElement{} | ||||
xx := &PrimeFieldElement{} | xx := &PrimeFieldElement{} | ||||
xx.Square(x) // Set xx = x^2 | |||||
xx.Mul(x, x) // Set xx = x^2 | |||||
lookup[0] = *x | lookup[0] = *x | ||||
for i := 1; i < 16; i++ { | for i := 1; i < 16; i++ { | ||||
lookup[i].Mul(&lookup[i-1], xx) | lookup[i].Mul(&lookup[i-1], xx) | ||||
@@ -498,49 +425,3 @@ func (x Fp751Element) vartimeEq(y Fp751Element) bool { | |||||
return eq | return eq | ||||
} | } | ||||
// Read an Fp751Element from little-endian bytes and convert to Montgomery form. | |||||
// | |||||
// The input byte slice must be at least 94 bytes long. | |||||
func (x *Fp751Element) montgomeryFormFromBytes(input []byte) { | |||||
if len(input) < 94 { | |||||
panic("input byte slice too short") | |||||
} | |||||
var a Fp751Element | |||||
for i := 0; i < 94; i++ { | |||||
// set i = j*8 + k | |||||
j := i / 8 | |||||
k := uint64(i % 8) | |||||
a[j] |= uint64(input[i]) << (8 * k) | |||||
} | |||||
var aRR fp751X2 | |||||
fp751Mul(&aRR, &a, &montgomeryRsq) // = a*R*R | |||||
fp751MontgomeryReduce(x, &aRR) // = a*R mod p | |||||
} | |||||
// Given an Fp751Element in Montgomery form, convert to little-endian bytes. | |||||
// | |||||
// The output byte slice must be at least 94 bytes long. | |||||
func (x *Fp751Element) toBytesFromMontgomeryForm(output []byte) { | |||||
if len(output) < 94 { | |||||
panic("output byte slice too short") | |||||
} | |||||
var a Fp751Element | |||||
var aR fp751X2 | |||||
copy(aR[:], x[:]) // = a*R | |||||
fp751MontgomeryReduce(&a, &aR) // = a mod p in [0, 2p) | |||||
fp751StrongReduce(&a) // = a mod p in [0, p) | |||||
// 8*12 = 96, but we drop the last two bytes since p is 751 < 752=94*8 bits. | |||||
for i := 0; i < 94; i++ { | |||||
// set i = j*8 + k | |||||
j := i / 8 | |||||
k := uint64(i % 8) | |||||
// Need parens because Go's operator precedence would interpret | |||||
// a[j] >> 8*k as (a[j] >> 8) * k | |||||
output[i] = byte(a[j] >> (8 * k)) | |||||
} | |||||
} |
@@ -39,30 +39,6 @@ | |||||
#define REG_P2 SI | #define REG_P2 SI | ||||
#define REG_P3 DX | #define REG_P3 DX | ||||
// We can't write MOVQ $0, AX because Go's assembler incorrectly | |||||
// optimizes this to XOR AX, AX, which clobbers the carry flags. | |||||
// | |||||
// This bug was defined to be "correct" behaviour (cf. | |||||
// https://github.com/golang/go/issues/12405 ) by declaring that the MOV | |||||
// pseudo-instruction clobbers flags, although this fact is mentioned | |||||
// nowhere in the documentation for the Go assembler. | |||||
// | |||||
// Defining MOVQ to clobber flags has the effect that it is never safe | |||||
// to interleave MOVQ with ADCQ and SBBQ instructions. Since this is | |||||
// required to write a carry chain longer than registers' working set, | |||||
// all of the below code therefore relies on the unspecified and | |||||
// undocumented behaviour that MOV won't clobber flags, except in the | |||||
// case of the above-mentioned bug. | |||||
// | |||||
// However, there's also no specification of which instructions | |||||
// correspond to machine instructions, and which are | |||||
// pseudo-instructions (i.e., no specification of what the assembler | |||||
// actually does), so this doesn't seem much worse than usual. | |||||
// | |||||
// Avoid the bug by dropping the bytes for `mov eax, 0` in directly: | |||||
#define ZERO_AX_WITHOUT_CLOBBERING_FLAGS BYTE $0xB8; BYTE $0; BYTE $0; BYTE $0; BYTE $0; | |||||
TEXT ·fp751StrongReduce(SB), NOSPLIT, $0-8 | TEXT ·fp751StrongReduce(SB), NOSPLIT, $0-8 | ||||
MOVQ x+0(FP), REG_P1 | MOVQ x+0(FP), REG_P1 | ||||
@@ -322,7 +298,7 @@ TEXT ·fp751AddReduced(SB), NOSPLIT, $0-24 | |||||
MOVQ R8, (72)(REG_P3) | MOVQ R8, (72)(REG_P3) | ||||
MOVQ R9, (80)(REG_P3) | MOVQ R9, (80)(REG_P3) | ||||
MOVQ R10, (88)(REG_P3) | MOVQ R10, (88)(REG_P3) | ||||
ZERO_AX_WITHOUT_CLOBBERING_FLAGS | |||||
MOVQ $0, AX | |||||
SBBQ $0, AX | SBBQ $0, AX | ||||
MOVQ P751X2_0, SI | MOVQ P751X2_0, SI | ||||
@@ -425,7 +401,7 @@ TEXT ·fp751SubReduced(SB), NOSPLIT, $0-24 | |||||
MOVQ (88)(REG_P1), AX | MOVQ (88)(REG_P1), AX | ||||
SBBQ (88)(REG_P2), AX | SBBQ (88)(REG_P2), AX | ||||
MOVQ AX, (88)(REG_P3) | MOVQ AX, (88)(REG_P3) | ||||
ZERO_AX_WITHOUT_CLOBBERING_FLAGS | |||||
MOVQ $0, AX | |||||
SBBQ $0, AX | SBBQ $0, AX | ||||
MOVQ P751X2_0, SI | MOVQ P751X2_0, SI | ||||
@@ -2625,7 +2601,7 @@ TEXT ·fp751X2SubLazy(SB), NOSPLIT, $0-24 | |||||
MOVQ DI, (184)(REG_P3) | MOVQ DI, (184)(REG_P3) | ||||
// Now the carry flag is 1 if x-y < 0. If so, add p*2^768. | // Now the carry flag is 1 if x-y < 0. If so, add p*2^768. | ||||
ZERO_AX_WITHOUT_CLOBBERING_FLAGS | |||||
MOVQ $0, AX | |||||
SBBQ $0, AX | SBBQ $0, AX | ||||
// Load p into registers: | // Load p into registers: | ||||
@@ -35,9 +35,13 @@ func radix64ToBigInt(x []uint64) *big.Int { | |||||
return val | return val | ||||
} | } | ||||
func (x *PrimeFieldElement) toBigInt() *big.Int { | |||||
func VartimeEq(x,y *PrimeFieldElement) bool { | |||||
return x.A.vartimeEq(y.A) | |||||
} | |||||
func (x *Fp751Element) toBigInt() *big.Int { | |||||
// Convert from Montgomery form | // Convert from Montgomery form | ||||
return x.A.toBigIntFromMontgomeryForm() | |||||
return x.toBigIntFromMontgomeryForm() | |||||
} | } | ||||
func (x *Fp751Element) toBigIntFromMontgomeryForm() *big.Int { | func (x *Fp751Element) toBigIntFromMontgomeryForm() *big.Int { | ||||
@@ -64,8 +68,8 @@ func TestPrimeFieldElementToBigInt(t *testing.T) { | |||||
// sage: assert(xR < 2*p) | // sage: assert(xR < 2*p) | ||||
// sage: (xR / R) % p | // sage: (xR / R) % p | ||||
xBig, _ := new(big.Int).SetString("4469946751055876387821312289373600189787971305258234719850789711074696941114031433609871105823930699680637820852699269802003300352597419024286385747737509380032982821081644521634652750355306547718505685107272222083450567982240", 10) | xBig, _ := new(big.Int).SetString("4469946751055876387821312289373600189787971305258234719850789711074696941114031433609871105823930699680637820852699269802003300352597419024286385747737509380032982821081644521634652750355306547718505685107272222083450567982240", 10) | ||||
if xBig.Cmp(x.toBigInt()) != 0 { | |||||
t.Error("Expected", xBig, "found", x.toBigInt()) | |||||
if xBig.Cmp(x.A.toBigInt()) != 0 { | |||||
t.Error("Expected", xBig, "found", x.A.toBigInt()) | |||||
} | } | ||||
} | } | ||||
@@ -121,7 +125,6 @@ func TestOneExtensionFieldToBytes(t *testing.T) { | |||||
x.One() | x.One() | ||||
x.ToBytes(xBytes[:]) | x.ToBytes(xBytes[:]) | ||||
if xBytes[0] != 1 { | if xBytes[0] != 1 { | ||||
t.Error("Expected 1, got", xBytes[0]) | t.Error("Expected 1, got", xBytes[0]) | ||||
} | } | ||||
@@ -249,101 +252,16 @@ func TestExtensionFieldElementBatch3Inv(t *testing.T) { | |||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
// Prime Field | // Prime Field | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
func TestPrimeFieldElementSetUint64VersusBigInt(t *testing.T) { | |||||
setUint64RoundTrips := func(x uint64) bool { | |||||
z := new(PrimeFieldElement).SetUint64(x).toBigInt().Uint64() | |||||
return x == z | |||||
} | |||||
if err := quick.Check(setUint64RoundTrips, quickCheckConfig); err != nil { | |||||
t.Error(err) | |||||
} | |||||
} | |||||
func TestPrimeFieldElementAddVersusBigInt(t *testing.T) { | |||||
addMatchesBigInt := func(x, y PrimeFieldElement) bool { | |||||
z := new(PrimeFieldElement) | |||||
z.Add(&x, &y) | |||||
check := new(big.Int) | |||||
check.Add(x.toBigInt(), y.toBigInt()) | |||||
check.Mod(check, cln16prime) | |||||
return check.Cmp(z.toBigInt()) == 0 | |||||
} | |||||
if err := quick.Check(addMatchesBigInt, quickCheckConfig); err != nil { | |||||
t.Error(err) | |||||
} | |||||
} | |||||
func TestPrimeFieldElementSubVersusBigInt(t *testing.T) { | |||||
subMatchesBigInt := func(x, y PrimeFieldElement) bool { | |||||
z := new(PrimeFieldElement) | |||||
z.Sub(&x, &y) | |||||
check := new(big.Int) | |||||
check.Sub(x.toBigInt(), y.toBigInt()) | |||||
check.Mod(check, cln16prime) | |||||
return check.Cmp(z.toBigInt()) == 0 | |||||
} | |||||
if err := quick.Check(subMatchesBigInt, quickCheckConfig); err != nil { | |||||
t.Error(err) | |||||
} | |||||
} | |||||
func TestPrimeFieldElementInv(t *testing.T) { | |||||
inverseIsCorrect := func(x PrimeFieldElement) bool { | |||||
z := new(PrimeFieldElement) | |||||
z.Inv(&x) | |||||
// Now z = (1/x), so (z * x) * x == x | |||||
z.Mul(z, &x).Mul(z, &x) | |||||
return z.VartimeEq(&x) | |||||
} | |||||
// This is more expensive; run fewer tests | |||||
var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))} | |||||
if err := quick.Check(inverseIsCorrect, quickCheckConfig); err != nil { | |||||
t.Error(err) | |||||
} | |||||
} | |||||
func TestPrimeFieldElementSqrt(t *testing.T) { | |||||
inverseIsCorrect := func(x PrimeFieldElement) bool { | |||||
// Construct y = x^2 so we're sure y is square. | |||||
y := new(PrimeFieldElement) | |||||
y.Square(&x) | |||||
z := new(PrimeFieldElement) | |||||
z.Sqrt(y) | |||||
// Now z = sqrt(y), so z^2 == y | |||||
z.Square(z) | |||||
return z.VartimeEq(y) | |||||
} | |||||
// This is more expensive; run fewer tests | |||||
var quickCheckConfig = &quick.Config{MaxCount: (1 << (8 + quickCheckScaleFactor))} | |||||
if err := quick.Check(inverseIsCorrect, quickCheckConfig); err != nil { | |||||
t.Error(err) | |||||
} | |||||
} | |||||
func TestPrimeFieldElementMulVersusBigInt(t *testing.T) { | func TestPrimeFieldElementMulVersusBigInt(t *testing.T) { | ||||
mulMatchesBigInt := func(x, y PrimeFieldElement) bool { | mulMatchesBigInt := func(x, y PrimeFieldElement) bool { | ||||
z := new(PrimeFieldElement) | z := new(PrimeFieldElement) | ||||
z.Mul(&x, &y) | z.Mul(&x, &y) | ||||
check := new(big.Int) | check := new(big.Int) | ||||
check.Mul(x.toBigInt(), y.toBigInt()) | |||||
check.Mul(x.A.toBigInt(), y.A.toBigInt()) | |||||
check.Mod(check, cln16prime) | check.Mod(check, cln16prime) | ||||
return check.Cmp(z.toBigInt()) == 0 | |||||
return check.Cmp(z.A.toBigInt()) == 0 | |||||
} | } | ||||
if err := quick.Check(mulMatchesBigInt, quickCheckConfig); err != nil { | if err := quick.Check(mulMatchesBigInt, quickCheckConfig); err != nil { | ||||
@@ -357,10 +275,10 @@ func TestPrimeFieldElementP34VersusBigInt(t *testing.T) { | |||||
z := new(PrimeFieldElement) | z := new(PrimeFieldElement) | ||||
z.P34(&x) | z.P34(&x) | ||||
check := x.toBigInt() | |||||
check := x.A.toBigInt() | |||||
check.Exp(check, p34, cln16prime) | check.Exp(check, p34, cln16prime) | ||||
return check.Cmp(z.toBigInt()) == 0 | |||||
return check.Cmp(z.A.toBigInt()) == 0 | |||||
} | } | ||||
// This is more expensive; run fewer tests | // This is more expensive; run fewer tests | ||||
@@ -370,26 +288,6 @@ func TestPrimeFieldElementP34VersusBigInt(t *testing.T) { | |||||
} | } | ||||
} | } | ||||
func TestFp751ElementConditionalSwap(t *testing.T) { | |||||
var one = Fp751Element{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} | |||||
var two = Fp751Element{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2} | |||||
var x = one | |||||
var y = two | |||||
fp751ConditionalSwap(&x, &y, 0) | |||||
if !(x == one && y == two) { | |||||
t.Error("Found", x, "expected", one) | |||||
} | |||||
fp751ConditionalSwap(&x, &y, 1) | |||||
if !(x == two && y == one) { | |||||
t.Error("Found", x, "expected", two) | |||||
} | |||||
} | |||||
// Package-level storage for this field element is intended to deter | // Package-level storage for this field element is intended to deter | ||||
// compiler optimizations. | // compiler optimizations. | ||||
var benchmarkFp751Element Fp751Element | var benchmarkFp751Element Fp751Element | ||||
@@ -452,51 +350,6 @@ func BenchmarkPrimeFieldElementMul(b *testing.B) { | |||||
} | } | ||||
} | } | ||||
func BenchmarkPrimeFieldElementInv(b *testing.B) { | |||||
z := &PrimeFieldElement{A: bench_x} | |||||
w := new(PrimeFieldElement) | |||||
for n := 0; n < b.N; n++ { | |||||
w.Inv(z) | |||||
} | |||||
} | |||||
func BenchmarkPrimeFieldElementSqrt(b *testing.B) { | |||||
z := &PrimeFieldElement{A: bench_x} | |||||
w := new(PrimeFieldElement) | |||||
for n := 0; n < b.N; n++ { | |||||
w.Sqrt(z) | |||||
} | |||||
} | |||||
func BenchmarkPrimeFieldElementSquare(b *testing.B) { | |||||
z := &PrimeFieldElement{A: bench_x} | |||||
w := new(PrimeFieldElement) | |||||
for n := 0; n < b.N; n++ { | |||||
w.Square(z) | |||||
} | |||||
} | |||||
func BenchmarkPrimeFieldElementAdd(b *testing.B) { | |||||
z := &PrimeFieldElement{A: bench_x} | |||||
w := new(PrimeFieldElement) | |||||
for n := 0; n < b.N; n++ { | |||||
w.Add(z, z) | |||||
} | |||||
} | |||||
func BenchmarkPrimeFieldElementSub(b *testing.B) { | |||||
z := &PrimeFieldElement{A: bench_x} | |||||
w := new(PrimeFieldElement) | |||||
for n := 0; n < b.N; n++ { | |||||
w.Sub(z, z) | |||||
} | |||||
} | |||||
// --- field operation functions | // --- field operation functions | ||||
func BenchmarkFp751Multiply(b *testing.B) { | func BenchmarkFp751Multiply(b *testing.B) { | ||||
@@ -3,68 +3,17 @@ package p751toolbox | |||||
// Tools used for testing and debugging | // Tools used for testing and debugging | ||||
import ( | import ( | ||||
"bytes" | |||||
"fmt" | "fmt" | ||||
) | ) | ||||
func printHex(vector []byte) (out string) { | |||||
var buffer bytes.Buffer | |||||
buffer.WriteString("0x") | |||||
len := len(vector) | |||||
for i := len - 1; i >= 0; i-- { | |||||
buffer.WriteString(fmt.Sprintf("%02x", vector[i])) | |||||
} | |||||
buffer.WriteString("\n") | |||||
return buffer.String() | |||||
} | |||||
func (element Fp751Element) String() string { | |||||
var out [94]byte | |||||
element.toBytesFromMontgomeryForm(out[:]) | |||||
return fmt.Sprintf("%s", printHex(out[:])) | |||||
} | |||||
func (primeElement PrimeFieldElement) String() string { | func (primeElement PrimeFieldElement) String() string { | ||||
return fmt.Sprintf("%s", primeElement.A.String()) | |||||
return fmt.Sprintf("%X", primeElement.A.toBigInt().String()) | |||||
} | } | ||||
func (extElement ExtensionFieldElement) String() string { | func (extElement ExtensionFieldElement) String() string { | ||||
var out [188]byte | |||||
extElement.ToBytes(out[:]) | |||||
return fmt.Sprintf("A: %sB: %s", printHex(out[:94]), printHex(out[94:])) | |||||
return fmt.Sprintf("\nA: %X\nB: %X", extElement.A.toBigInt().String(), extElement.B.toBigInt().String()) | |||||
} | } | ||||
func (point ProjectivePoint) String() string { | func (point ProjectivePoint) String() string { | ||||
return fmt.Sprintf("X:\n%sZ:\n%s", point.X.String(), point.Z.String()) | return fmt.Sprintf("X:\n%sZ:\n%s", point.X.String(), point.Z.String()) | ||||
} | } | ||||
func (point ProjectivePrimeFieldPoint) String() string { | |||||
return fmt.Sprintf("X:\n%sZ:\n%s", point.X.String(), point.Z.String()) | |||||
} | |||||
func (point Fp751Element) PrintHex() { | |||||
fmt.Printf("\t") | |||||
for i := 0; i < fp751NumWords/2; i++ { | |||||
fmt.Printf("0x%0.16X, ", point[i]) | |||||
} | |||||
fmt.Printf("\n\t\t") | |||||
for i := fp751NumWords / 2; i < fp751NumWords; i++ { | |||||
fmt.Printf("0x%0.16X, ", point[i]) | |||||
} | |||||
fmt.Printf("\n") | |||||
} | |||||
func (extElement ExtensionFieldElement) PrintHex() { | |||||
fmt.Printf("\t[r]: ") | |||||
extElement.A.PrintHex() | |||||
fmt.Printf("\t[u]: ") | |||||
extElement.B.PrintHex() | |||||
} | |||||
func (point ProjectivePoint) PrintHex() { | |||||
fmt.Printf("X:") | |||||
point.X.PrintHex() | |||||
fmt.Printf("Z:") | |||||
point.X.PrintHex() | |||||
fmt.Printf("\n") | |||||
} |
@@ -164,19 +164,14 @@ func (prv *PrivateKey) Generate(rand io.Reader) error { | |||||
return err | return err | ||||
} | } | ||||
// Generates public key corresponding to prv. KeyVariant of generated public key | |||||
// is same as PrivateKey. Fails only if prv was wrongly initialized. | |||||
// Constant time for properly initialzied PrivateKey | |||||
func GeneratePublicKey(prv *PrivateKey) (*PublicKey, error) { | |||||
if prv == nil { | |||||
return nil, errors.New("sidh: invalid arguments") | |||||
} | |||||
// Generates public key. | |||||
// | |||||
// Constant time. | |||||
func (prv *PrivateKey) GeneratePublicKey() (*PublicKey) { | |||||
if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A { | if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A { | ||||
return publicKeyGenA(prv), nil | |||||
} else { | |||||
return publicKeyGenB(prv), nil | |||||
return publicKeyGenA(prv) | |||||
} | } | ||||
return publicKeyGenB(prv) | |||||
} | } | ||||
// Computes a shared secret which is a j-invariant. Function requires that pub has | // Computes a shared secret which is a j-invariant. Function requires that pub has | ||||
@@ -231,19 +231,13 @@ func publicKeyGenA(prv *PrivateKey) (pub *PublicKey) { | |||||
// Load points for A | // Load points for A | ||||
xPA.FromAffine(&prv.params.A.Affine_P) | xPA.FromAffine(&prv.params.A.Affine_P) | ||||
xPA.Z.One() | |||||
xQA.FromAffine(&prv.params.A.Affine_Q) | xQA.FromAffine(&prv.params.A.Affine_Q) | ||||
xQA.Z.One() | |||||
xRA.FromAffine(&prv.params.A.Affine_R) | xRA.FromAffine(&prv.params.A.Affine_R) | ||||
xRA.Z.One() | |||||
// Load points for B | // Load points for B | ||||
xRB.FromAffine(&prv.params.B.Affine_R) | xRB.FromAffine(&prv.params.B.Affine_R) | ||||
xRB.Z.One() | |||||
xQB.FromAffine(&prv.params.B.Affine_Q) | xQB.FromAffine(&prv.params.B.Affine_Q) | ||||
xQB.Z.One() | |||||
xPB.FromAffine(&prv.params.B.Affine_P) | xPB.FromAffine(&prv.params.B.Affine_P) | ||||
xPB.Z.One() | |||||
// Find isogeny kernel | // Find isogeny kernel | ||||
tmp.A.Zero() | tmp.A.Zero() | ||||
@@ -279,19 +273,13 @@ func publicKeyGenB(prv *PrivateKey) (pub *PublicKey) { | |||||
// Load points for B | // Load points for B | ||||
xRB.FromAffine(&prv.params.B.Affine_R) | xRB.FromAffine(&prv.params.B.Affine_R) | ||||
xRB.Z.One() | |||||
xQB.FromAffine(&prv.params.B.Affine_Q) | xQB.FromAffine(&prv.params.B.Affine_Q) | ||||
xQB.Z.One() | |||||
xPB.FromAffine(&prv.params.B.Affine_P) | xPB.FromAffine(&prv.params.B.Affine_P) | ||||
xPB.Z.One() | |||||
// Load points for A | // Load points for A | ||||
xPA.FromAffine(&prv.params.A.Affine_P) | xPA.FromAffine(&prv.params.A.Affine_P) | ||||
xPA.Z.One() | |||||
xQA.FromAffine(&prv.params.A.Affine_Q) | xQA.FromAffine(&prv.params.A.Affine_Q) | ||||
xQA.Z.One() | |||||
xRA.FromAffine(&prv.params.A.Affine_R) | xRA.FromAffine(&prv.params.A.Affine_R) | ||||
xRA.Z.One() | |||||
tmp.A.Zero() | tmp.A.Zero() | ||||
tmp.C.One() | tmp.C.One() | ||||
@@ -93,10 +93,8 @@ func testKeygen(s *SidhParams, t *testing.T) { | |||||
expPubA := convToPub(PkA, KeyVariant_SIDH_A) | expPubA := convToPub(PkA, KeyVariant_SIDH_A) | ||||
expPubB := convToPub(PkB, KeyVariant_SIDH_B) | expPubB := convToPub(PkB, KeyVariant_SIDH_B) | ||||
pubA, err := GeneratePublicKey(alicePrivate) | |||||
checkErr(t, err, "public key A generation failed") | |||||
pubB, err := GeneratePublicKey(bobPrivate) | |||||
checkErr(t, err, "public key B generation failed") | |||||
pubA := alicePrivate.GeneratePublicKey() | |||||
pubB := bobPrivate.GeneratePublicKey() | |||||
if !bytes.Equal(pubA.Export(), expPubA.Export()) { | if !bytes.Equal(pubA.Export(), expPubA.Export()) { | ||||
t.Fatalf("unexpected value of public key A") | t.Fatalf("unexpected value of public key A") | ||||
@@ -119,11 +117,8 @@ func testRoundtrip(s *SidhParams, t *testing.T) { | |||||
checkErr(t, err, "key generation failed") | checkErr(t, err, "key generation failed") | ||||
// Generate public keys | // Generate public keys | ||||
pubA, err := GeneratePublicKey(prvA) | |||||
checkErr(t, err, "") | |||||
pubB, err := GeneratePublicKey(prvB) | |||||
checkErr(t, err, "") | |||||
pubA := prvA.GeneratePublicKey() | |||||
pubB := prvB.GeneratePublicKey() | |||||
// Derive shared secret | // Derive shared secret | ||||
s1, err := DeriveSecret(prvB, pubA) | s1, err := DeriveSecret(prvB, pubA) | ||||
@@ -317,7 +312,7 @@ func BenchmarkAliceKeyGenPub(b *testing.B) { | |||||
prv := NewPrivateKey(params.Id, KeyVariant_SIDH_A) | prv := NewPrivateKey(params.Id, KeyVariant_SIDH_A) | ||||
prv.Generate(rand.Reader) | prv.Generate(rand.Reader) | ||||
for n := 0; n < b.N; n++ { | for n := 0; n < b.N; n++ { | ||||
GeneratePublicKey(prv) | |||||
prv.GeneratePublicKey() | |||||
} | } | ||||
} | } | ||||
@@ -325,7 +320,7 @@ func BenchmarkBobKeyGenPub(b *testing.B) { | |||||
prv := NewPrivateKey(params.Id, KeyVariant_SIDH_B) | prv := NewPrivateKey(params.Id, KeyVariant_SIDH_B) | ||||
prv.Generate(rand.Reader) | prv.Generate(rand.Reader) | ||||
for n := 0; n < b.N; n++ { | for n := 0; n < b.N; n++ { | ||||
GeneratePublicKey(prv) | |||||
prv.GeneratePublicKey() | |||||
} | } | ||||
} | } | ||||
@@ -71,7 +71,7 @@ func Encrypt(rng io.Reader, pub *PublicKey, ptext []byte) ([]byte, error) { | |||||
return nil, err | return nil, err | ||||
} | } | ||||
pkA, _ := GeneratePublicKey(skA) // Never fails | |||||
pkA := skA.GeneratePublicKey() | |||||
return encrypt(skA, pkA, pub, ptext) | return encrypt(skA, pkA, pub, ptext) | ||||
} | } | ||||
@@ -152,7 +152,7 @@ func Encapsulate(rng io.Reader, pub *PublicKey) (ctext []byte, secret []byte, er | |||||
return nil, nil, err | return nil, nil, err | ||||
} | } | ||||
pkA, _ := GeneratePublicKey(skA) // Never fails | |||||
pkA := skA.GeneratePublicKey() | |||||
ctext, err = encrypt(skA, pkA, pub, ptext) | ctext, err = encrypt(skA, pkA, pub, ptext) | ||||
if err != nil { | if err != nil { | ||||
return nil, nil, err | return nil, nil, err | ||||
@@ -197,7 +197,7 @@ func Decapsulate(prv *PrivateKey, pub *PublicKey, ctext []byte) ([]byte, error) | |||||
skA.Import(r) | skA.Import(r) | ||||
// Never fails | // Never fails | ||||
pkA, _ := GeneratePublicKey(skA) | |||||
pkA := skA.GeneratePublicKey() | |||||
c0 := pkA.Export() | c0 := pkA.Export() | ||||
h = cshake.NewCShake256(nil, H) | h = cshake.NewCShake256(nil, H) | ||||
@@ -77,7 +77,7 @@ func TestPKEKeyGeneration(t *testing.T) { | |||||
sk := NewPrivateKey(params.Id, KeyVariant_SIKE) | sk := NewPrivateKey(params.Id, KeyVariant_SIKE) | ||||
err = sk.Generate(rand.Reader) | err = sk.Generate(rand.Reader) | ||||
checkErr(t, err, "PEK key generation") | checkErr(t, err, "PEK key generation") | ||||
pk, _ := GeneratePublicKey(sk) | |||||
pk := sk.GeneratePublicKey() | |||||
// Try to encrypt | // Try to encrypt | ||||
ct, err := Encrypt(rand.Reader, pk, msg[:]) | ct, err := Encrypt(rand.Reader, pk, msg[:]) | ||||
@@ -99,7 +99,7 @@ func TestNegativePKE(t *testing.T) { | |||||
err = sk.Generate(rand.Reader) | err = sk.Generate(rand.Reader) | ||||
checkErr(t, err, "key generation") | checkErr(t, err, "key generation") | ||||
pk, _ := GeneratePublicKey(sk) | |||||
pk := sk.GeneratePublicKey() | |||||
ct, err := Encrypt(rand.Reader, pk, msg[:39]) | ct, err := Encrypt(rand.Reader, pk, msg[:39]) | ||||
if err == nil { | if err == nil { | ||||
@@ -152,7 +152,7 @@ func TestKEMKeyGeneration(t *testing.T) { | |||||
// Generate key | // Generate key | ||||
sk := NewPrivateKey(params.Id, KeyVariant_SIKE) | sk := NewPrivateKey(params.Id, KeyVariant_SIKE) | ||||
checkErr(t, sk.Generate(rand.Reader), "error: key generation") | checkErr(t, sk.Generate(rand.Reader), "error: key generation") | ||||
pk, _ := GeneratePublicKey(sk) | |||||
pk := sk.GeneratePublicKey() | |||||
// calculated shared secret | // calculated shared secret | ||||
ct, ss_e, err := Encapsulate(rand.Reader, pk) | ct, ss_e, err := Encapsulate(rand.Reader, pk) | ||||
@@ -168,7 +168,7 @@ func TestKEMKeyGeneration(t *testing.T) { | |||||
func TestNegativeKEM(t *testing.T) { | func TestNegativeKEM(t *testing.T) { | ||||
sk := NewPrivateKey(params.Id, KeyVariant_SIKE) | sk := NewPrivateKey(params.Id, KeyVariant_SIKE) | ||||
checkErr(t, sk.Generate(rand.Reader), "error: key generation") | checkErr(t, sk.Generate(rand.Reader), "error: key generation") | ||||
pk, _ := GeneratePublicKey(sk) | |||||
pk := sk.GeneratePublicKey() | |||||
ct, ss_e, err := Encapsulate(rand.Reader, pk) | ct, ss_e, err := Encapsulate(rand.Reader, pk) | ||||
checkErr(t, err, "pre-requisite for a test failed") | checkErr(t, err, "pre-requisite for a test failed") | ||||
@@ -201,7 +201,7 @@ func TestNegativeKEM(t *testing.T) { | |||||
func TestNegativeKEMSameWrongResult(t *testing.T) { | func TestNegativeKEMSameWrongResult(t *testing.T) { | ||||
sk := NewPrivateKey(params.Id, KeyVariant_SIKE) | sk := NewPrivateKey(params.Id, KeyVariant_SIKE) | ||||
checkErr(t, sk.Generate(rand.Reader), "error: key generation") | checkErr(t, sk.Generate(rand.Reader), "error: key generation") | ||||
pk, _ := GeneratePublicKey(sk) | |||||
pk := sk.GeneratePublicKey() | |||||
ct, encSs, err := Encapsulate(rand.Reader, pk) | ct, encSs, err := Encapsulate(rand.Reader, pk) | ||||
checkErr(t, err, "pre-requisite for a test failed") | checkErr(t, err, "pre-requisite for a test failed") | ||||
@@ -261,7 +261,7 @@ func testKeygen(pk, sk []byte) bool { | |||||
} | } | ||||
// Generate public key | // Generate public key | ||||
pubKey, _ := GeneratePublicKey(prvKey) | |||||
pubKey := prvKey.GeneratePublicKey() | |||||
return bytes.Equal(pubKey.Export(), pk) | return bytes.Equal(pubKey.Export(), pk) | ||||
} | } | ||||