Jacobian coordinates (#95)

* Add projective-> affine bench

* Add conditional copy and div2 benches

* Fp4 benchmarks

* Constant-time Jacobian addition

* Jacobian doubling

* Use a simpler Add+Dbl complete formula

* Update tests

* Fix conditional negate

* Rollaback complete addition, we were only handling curve coef a == 0
This commit is contained in:
Mamy Ratsimbazafy 2020-10-02 00:01:09 +02:00 committed by GitHub
parent 0effd66dbd
commit 986245b5c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 2433 additions and 283 deletions

View File

@ -10,7 +10,9 @@ import
# Internals
../constantine/config/curves,
../constantine/arithmetic,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/elliptic/[
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian],
# Helpers
../helpers/static_for,
./bench_elliptic_template,
@ -44,18 +46,30 @@ proc main() =
staticFor i, 0, AvailableCurves.len:
const curve = AvailableCurves[i]
addBench(ECP_ShortW_Proj[Fp[curve]], Iters)
addBench(ECP_ShortW_Jac[Fp[curve]], Iters)
mixedAddBench(ECP_ShortW_Proj[Fp[curve]], Iters)
doublingBench(ECP_ShortW_Proj[Fp[curve]], Iters)
doublingBench(ECP_ShortW_Jac[Fp[curve]], Iters)
separator()
affFromProjBench(ECP_ShortW_Proj[Fp[curve]], MulIters)
affFromJacBench(ECP_ShortW_Jac[Fp[curve]], MulIters)
separator()
scalarMulUnsafeDoubleAddBench(ECP_ShortW_Proj[Fp[curve]], MulIters)
scalarMulUnsafeDoubleAddBench(ECP_ShortW_Jac[Fp[curve]], MulIters)
separator()
scalarMulGenericBench(ECP_ShortW_Proj[Fp[curve]], window = 2, MulIters)
scalarMulGenericBench(ECP_ShortW_Proj[Fp[curve]], window = 3, MulIters)
scalarMulGenericBench(ECP_ShortW_Proj[Fp[curve]], window = 4, MulIters)
scalarMulGenericBench(ECP_ShortW_Proj[Fp[curve]], window = 5, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve]], window = 2, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve]], window = 3, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve]], window = 4, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve]], window = 5, MulIters)
separator()
scalarMulEndo(ECP_ShortW_Proj[Fp[curve]], MulIters)
scalarMulEndoWindow(ECP_ShortW_Proj[Fp[curve]], MulIters)
scalarMulEndo(ECP_ShortW_Jac[Fp[curve]], MulIters)
scalarMulEndoWindow(ECP_ShortW_Jac[Fp[curve]], MulIters)
separator()
separator()

View File

@ -11,7 +11,9 @@ import
../constantine/config/curves,
../constantine/arithmetic,
../constantine/towers,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/elliptic/[
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian],
# Helpers
../helpers/static_for,
./bench_elliptic_template,
@ -45,20 +47,30 @@ proc main() =
staticFor i, 0, AvailableCurves.len:
const curve = AvailableCurves[i]
addBench(ECP_ShortW_Proj[Fp2[curve]], Iters)
addBench(ECP_ShortW_Jac[Fp2[curve]], Iters)
mixedAddBench(ECP_ShortW_Proj[Fp2[curve]], Iters)
doublingBench(ECP_ShortW_Proj[Fp2[curve]], Iters)
doublingBench(ECP_ShortW_Jac[Fp2[curve]], Iters)
separator()
affFromProjBench(ECP_ShortW_Proj[Fp2[curve]], MulIters)
affFromJacBench(ECP_ShortW_Jac[Fp2[curve]], MulIters)
separator()
scalarMulUnsafeDoubleAddBench(ECP_ShortW_Proj[Fp2[curve]], MulIters)
scalarMulUnsafeDoubleAddBench(ECP_ShortW_Jac[Fp2[curve]], MulIters)
separator()
scalarMulGenericBench(ECP_ShortW_Proj[Fp2[curve]], window = 2, MulIters)
scalarMulGenericBench(ECP_ShortW_Proj[Fp2[curve]], window = 3, MulIters)
scalarMulGenericBench(ECP_ShortW_Proj[Fp2[curve]], window = 4, MulIters)
scalarMulGenericBench(ECP_ShortW_Proj[Fp2[curve]], window = 5, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp2[curve]], window = 2, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp2[curve]], window = 3, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp2[curve]], window = 4, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp2[curve]], window = 5, MulIters)
separator()
scalarMulEndo(ECP_ShortW_Proj[Fp2[curve]], MulIters)
scalarMulEndo(ECP_ShortW_Jac[Fp2[curve]], MulIters)
separator()
separator()
separator()
main()
notes()

View File

@ -152,6 +152,20 @@ proc doublingBench*(T: typedesc, iters: int) =
bench("EC Double " & G1_or_G2, T, iters):
r.double(P)
proc affFromProjBench*(T: typedesc, iters: int) =
const G1_or_G2 = when T.F is Fp: "G1" else: "G2"
var r {.noInit.}: ECP_ShortW_Aff[T.F]
let P = rng.random_unsafe(T)
bench("EC Projective to Affine " & G1_or_G2, T, iters):
r.affineFromProjective(P)
proc affFromJacBench*(T: typedesc, iters: int) =
const G1_or_G2 = when T.F is Fp: "G1" else: "G2"
var r {.noInit.}: ECP_ShortW_Aff[T.F]
let P = rng.random_unsafe(T)
bench("EC Jacobian to Affine " & G1_or_G2, T, iters):
r.affineFromJacobian(P)
proc scalarMulGenericBench*(T: typedesc, window: static int, iters: int) =
const bits = T.F.C.getCurveOrderBitwidth()
const G1_or_G2 = when T.F is Fp: "G1" else: "G2"

View File

@ -141,6 +141,17 @@ proc negBench*(T: typedesc, iters: int) =
bench("Negation", T, iters):
r.neg(x)
proc ccopyBench*(T: typedesc, iters: int) =
var r: T
let x = rng.random_unsafe(T)
bench("Conditional Copy", T, iters):
r.ccopy(x, CtFalse)
proc div2Bench*(T: typedesc, iters: int) =
var x = rng.random_unsafe(T)
bench("Division by 2", T, iters):
x.div2()
proc mulBench*(T: typedesc, iters: int) =
var r: T
let x = rng.random_unsafe(T)

View File

@ -44,6 +44,8 @@ proc main() =
addBench(Fp[curve], Iters)
subBench(Fp[curve], Iters)
negBench(Fp[curve], Iters)
ccopyBench(Fp[curve], Iters)
div2Bench(Fp[curve], Iters)
mulBench(Fp[curve], Iters)
sqrBench(Fp[curve], Iters)
invEuclidBench(Fp[curve], ExponentIters)

View File

@ -40,6 +40,8 @@ proc main() =
addBench(Fp2[curve], Iters)
subBench(Fp2[curve], Iters)
negBench(Fp2[curve], Iters)
ccopyBench(Fp2[curve], Iters)
div2Bench(Fp2[curve], Iters)
mulBench(Fp2[curve], Iters)
sqrBench(Fp2[curve], Iters)
invBench(Fp2[curve], InvIters)

51
benchmarks/bench_fp4.nim Normal file
View File

@ -0,0 +1,51 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/towers,
# Helpers
../helpers/static_for,
./bench_fields_template,
# Standard library
std/strutils
# ############################################################
#
# Benchmark of 𝔽p2 = 𝔽p[𝑖]
#
# ############################################################
const Iters = 1_000_000
const InvIters = 1000
const AvailableCurves = [
# Pairing-Friendly curves
BN254_Nogami,
BN254_Snarks,
BLS12_377,
BLS12_381
]
proc main() =
separator()
staticFor i, 0, AvailableCurves.len:
const curve = AvailableCurves[i]
addBench(Fp4[curve], Iters)
subBench(Fp4[curve], Iters)
negBench(Fp4[curve], Iters)
ccopyBench(Fp4[curve], Iters)
div2Bench(Fp4[curve], Iters)
mulBench(Fp4[curve], Iters)
sqrBench(Fp4[curve], Iters)
invBench(Fp4[curve], InvIters)
separator()
main()
notes()

View File

@ -29,6 +29,7 @@ const testDesc: seq[tuple[path: string, useGMP: bool]] = @[
# Field
("tests/t_io_fields", false),
("tests/t_finite_fields.nim", false),
("tests/t_finite_fields_conditional_arithmetic.nim", false),
("tests/t_finite_fields_mulsquare.nim", false),
("tests/t_finite_fields_sqrt.nim", false),
("tests/t_finite_fields_powinv.nim", false),
@ -49,32 +50,53 @@ const testDesc: seq[tuple[path: string, useGMP: bool]] = @[
("tests/t_fp4_frobenius.nim", false),
# Elliptic curve arithmetic G1
("tests/t_ec_wstrass_prj_g1_add_double.nim", false),
("tests/t_ec_wstrass_prj_g1_mul_sanity.nim", false),
("tests/t_ec_wstrass_prj_g1_mul_distri.nim", false),
("tests/t_ec_wstrass_prj_g1_mul_vs_ref.nim", false),
("tests/t_ec_wstrass_prj_g1_mixed_add.nim", false),
# Elliptic curve arithmetic G2
("tests/t_ec_wstrass_prj_g2_add_double_bn254_snarks.nim", false),
("tests/t_ec_wstrass_prj_g2_mul_sanity_bn254_snarks.nim", false),
("tests/t_ec_wstrass_prj_g2_mul_distri_bn254_snarks.nim", false),
("tests/t_ec_wstrass_prj_g2_mul_vs_ref_bn254_snarks.nim", false),
("tests/t_ec_shortw_prj_g1_add_double.nim", false),
("tests/t_ec_shortw_prj_g1_mul_sanity.nim", false),
("tests/t_ec_shortw_prj_g1_mul_distri.nim", false),
("tests/t_ec_shortw_prj_g1_mul_vs_ref.nim", false),
("tests/t_ec_shortw_prj_g1_mixed_add.nim", false),
("tests/t_ec_wstrass_prj_g2_add_double_bls12_381.nim", false),
("tests/t_ec_wstrass_prj_g2_mul_sanity_bls12_381.nim", false),
("tests/t_ec_wstrass_prj_g2_mul_distri_bls12_381.nim", false),
("tests/t_ec_wstrass_prj_g2_mul_vs_ref_bls12_381.nim", false),
("tests/t_ec_wstrass_prj_g2_add_double_bls12_377.nim", false),
("tests/t_ec_wstrass_prj_g2_mul_sanity_bls12_377.nim", false),
("tests/t_ec_wstrass_prj_g2_mul_distri_bls12_377.nim", false),
("tests/t_ec_wstrass_prj_g2_mul_vs_ref_bls12_377.nim", false),
("tests/t_ec_shortw_jac_g1_add_double.nim", false),
("tests/t_ec_shortw_jac_g1_mul_sanity.nim", false),
("tests/t_ec_shortw_jac_g1_mul_distri.nim", false),
("tests/t_ec_shortw_jac_g1_mul_vs_ref.nim", false),
# Elliptic curve arithmetic G2
("tests/t_ec_shortw_prj_g2_add_double_bn254_snarks.nim", false),
("tests/t_ec_shortw_prj_g2_mul_sanity_bn254_snarks.nim", false),
("tests/t_ec_shortw_prj_g2_mul_distri_bn254_snarks.nim", false),
("tests/t_ec_shortw_prj_g2_mul_vs_ref_bn254_snarks.nim", false),
("tests/t_ec_shortw_prj_g2_add_double_bls12_381.nim", false),
("tests/t_ec_shortw_prj_g2_mul_sanity_bls12_381.nim", false),
("tests/t_ec_shortw_prj_g2_mul_distri_bls12_381.nim", false),
("tests/t_ec_shortw_prj_g2_mul_vs_ref_bls12_381.nim", false),
("tests/t_ec_shortw_prj_g2_add_double_bls12_377.nim", false),
("tests/t_ec_shortw_prj_g2_mul_sanity_bls12_377.nim", false),
("tests/t_ec_shortw_prj_g2_mul_distri_bls12_377.nim", false),
("tests/t_ec_shortw_prj_g2_mul_vs_ref_bls12_377.nim", false),
("tests/t_ec_shortw_jac_g2_add_double_bn254_snarks.nim", false),
("tests/t_ec_shortw_jac_g2_mul_sanity_bn254_snarks.nim", false),
("tests/t_ec_shortw_jac_g2_mul_distri_bn254_snarks.nim", false),
("tests/t_ec_shortw_jac_g2_mul_vs_ref_bn254_snarks.nim", false),
("tests/t_ec_shortw_jac_g2_add_double_bls12_381.nim", false),
("tests/t_ec_shortw_jac_g2_mul_sanity_bls12_381.nim", false),
("tests/t_ec_shortw_jac_g2_mul_distri_bls12_381.nim", false),
("tests/t_ec_shortw_jac_g2_mul_vs_ref_bls12_381.nim", false),
("tests/t_ec_shortw_jac_g2_add_double_bls12_377.nim", false),
("tests/t_ec_shortw_jac_g2_mul_sanity_bls12_377.nim", false),
("tests/t_ec_shortw_jac_g2_mul_distri_bls12_377.nim", false),
("tests/t_ec_shortw_jac_g2_mul_vs_ref_bls12_377.nim", false),
# Elliptic curve arithmetic vs Sagemath
("tests/t_ec_frobenius.nim", false),
("tests/t_ec_sage_bn254.nim", false),
("tests/t_ec_sage_bls12_377.nim", false),
("tests/t_ec_sage_bls12_381.nim", false),
# Edge cases highlighted by past bugs
("tests/t_ec_wstrass_prj_edge_cases.nim", false),
("tests/t_ec_shortw_prj_edge_cases.nim", false),
# Pairing
("tests/t_pairing_mul_fp12_by_lines.nim", false),
("tests/t_pairing_cyclotomic_fp12.nim", false),
@ -399,6 +421,21 @@ task bench_fp2_gcc_noasm, "Run benchmark 𝔽p2 with gcc - no Assembly":
task bench_fp2_clang_noasm, "Run benchmark 𝔽p2 with clang - no Assembly":
runBench("bench_fp2", "clang", useAsm = false)
task bench_fp4, "Run benchmark with 𝔽p4 your default compiler":
runBench("bench_fp4")
task bench_fp4_gcc, "Run benchmark 𝔽p4 with gcc":
runBench("bench_fp4", "gcc")
task bench_fp4_clang, "Run benchmark 𝔽p4 with clang":
runBench("bench_fp4", "clang")
task bench_fp4_gcc_noasm, "Run benchmark 𝔽p4 with gcc - no Assembly":
runBench("bench_fp4", "gcc", useAsm = false)
task bench_fp4_clang_noasm, "Run benchmark 𝔽p4 with clang - no Assembly":
runBench("bench_fp4", "clang", useAsm = false)
task bench_fp6, "Run benchmark with 𝔽p6 your default compiler":
runBench("bench_fp6")

View File

@ -234,6 +234,38 @@ func div2*(a: var Fp) {.inline.} =
## Modular division by 2
a.mres.div2_modular(Fp.C.getPrimePlus1div2())
# ############################################################
#
# Field arithmetic conditional
#
# ############################################################
func cneg*(r: var Fp, a: Fp, ctl: SecretBool) =
## Constant-time in-place conditional negation
## The negation is only performed if ctl is "true"
r.neg(a)
r.ccopy(a, not ctl)
func cneg*(a: var Fp, ctl: SecretBool) =
## Constant-time in-place conditional negation
## The negation is only performed if ctl is "true"
var t = a
a.cneg(t, ctl)
func cadd*(a: var Fp, b: Fp, ctl: SecretBool) =
## Constant-time in-place conditional addition
## The addition is only performed if ctl is "true"
var t = a
t += b
a.ccopy(t, ctl)
func csub*(a: var Fp, b: Fp, ctl: SecretBool) =
## Constant-time in-place conditional substraction
## The substraction is only performed if ctl is "true"
var t = a
t -= b
a.ccopy(t, ctl)
# ############################################################
#
# Field arithmetic exponentiation

View File

@ -192,32 +192,6 @@ func add*(a: var Limbs, w: SecretWord): Carry =
for i in 1 ..< a.len:
addC(result, a[i], a[i], Zero, result)
func cadd*(a: var Limbs, b: Limbs, ctl: SecretBool): Carry =
## Limbs conditional addition
## Returns the carry
##
## if ctl is true: a <- a + b
## if ctl is false: a <- a
## The carry is always computed whether ctl is true or false
##
## Time and memory accesses are the same whether a copy occurs or not
result = Carry(0)
var sum: SecretWord
for i in 0 ..< a.len:
addC(result, sum, a[i], b[i], result)
ctl.ccopy(a[i], sum)
func cadd*(a: var Limbs, w: SecretWord, ctl: SecretBool): Borrow =
## Limbs conditional addition, sub a number that fits in a word
## Returns the borrow
result = Carry(0)
var diff: SecretWord
addC(result, diff, a[0], w, result)
ctl.ccopy(a[0], diff)
for i in 1 ..< a.len:
addC(result, diff, a[i], Zero, result)
ctl.ccopy(a[i], diff)
func sum*(r: var Limbs, a, b: Limbs): Carry =
## Sum `a` and `b` into `r`
## `r` is initialized/overwritten
@ -248,32 +222,6 @@ func sub*(a: var Limbs, w: SecretWord): Borrow =
for i in 1 ..< a.len:
subB(result, a[i], a[i], Zero, result)
func csub*(a: var Limbs, b: Limbs, ctl: SecretBool): Borrow =
## Limbs conditional substraction
## Returns the borrow
##
## if ctl is true: a <- a - b
## if ctl is false: a <- a
## The borrow is always computed whether ctl is true or false
##
## Time and memory accesses are the same whether a copy occurs or not
result = Borrow(0)
var diff: SecretWord
for i in 0 ..< a.len:
subB(result, diff, a[i], b[i], result)
ctl.ccopy(a[i], diff)
func csub*(a: var Limbs, w: SecretWord, ctl: SecretBool): Borrow =
## Limbs conditional substraction, sub a number that fits in a word
## Returns the borrow
result = Borrow(0)
var diff: SecretWord
subB(result, diff, a[0], w, result)
ctl.ccopy(a[0], diff)
for i in 1 ..< a.len:
subB(result, diff, a[i], Zero, result)
ctl.ccopy(a[i], diff)
func diff*(r: var Limbs, a, b: Limbs): Borrow =
## Diff `a` and `b` into `r`
## `r` is initialized/overwritten
@ -286,6 +234,49 @@ func diff*(r: var Limbs, a, b: Limbs): Borrow =
for i in 0 ..< a.len:
subB(result, r[i], a[i], b[i], result)
# Conditional arithmetic
# ------------------------------------------------------------
func cadd*(a: var Limbs, b: Limbs, ctl: SecretBool): Carry =
## Limbs conditional addition
## Returns the carry
##
## if ctl is true: a <- a + b
## if ctl is false: a <- a
## The carry is always computed whether ctl is true or false
##
## Time and memory accesses are the same whether a copy occurs or not
var t = a
result = t.add(b)
a.ccopy(t, ctl)
func cadd*(a: var Limbs, w: SecretWord, ctl: SecretBool): Borrow =
## Limbs conditional addition, sub a number that fits in a word
## Returns the borrow
var t = a
result = t.add(w)
a.ccopy(t, ctl)
func csub*(a: var Limbs, b: Limbs, ctl: SecretBool): Borrow =
## Limbs conditional substraction
## Returns the borrow
##
## if ctl is true: a <- a - b
## if ctl is false: a <- a
## The borrow is always computed whether ctl is true or false
##
## Time and memory accesses are the same whether a copy occurs or not
var t = a
result = t.sub(b)
a.ccopy(t, ctl)
func csub*(a: var Limbs, w: SecretWord, ctl: SecretBool): Borrow =
## Limbs conditional substraction, sub a number that fits in a word
## Returns the borrow
var t = a
result = t.sub(w)
a.ccopy(t, ctl)
func cneg*(a: var Limbs, ctl: CTBool) =
## Conditional negation.
## Negate if ``ctl`` is true

View File

@ -140,9 +140,17 @@ We use the complete addition law from Bos2014 for Jacobian coordinates, note tha
http://indigo.ie/~mscott/twists.pdf
- Faster Pairing Computations on Curves withHigh-Degree Twists\
Craig Costello and Tanja Lange and Michael Naehrig, 2009,
Craig Costello and Tanja Lange and Michael Naehrig, 2009
https://eprint.iacr.org/2009/615
- Weierstraß Elliptic Curves and Side-Channel Attacks\
Éric Brier and Marc Joye, 2002\
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.2.273&rep=rep1&type=pdf
- Efficient Elliptic Curve Exponentiation Using Mixed Coordinates\
Henri Cohen, Atsuko Miyaji, Takatoshi Ono, 1998\
https://link.springer.com/content/pdf/10.1007%2F3-540-49649-1_6.pdf
- Complete systems of Two Addition Laws for Elliptic Curve\
Bosma and Lenstra, 1995
Bosma and Lenstra, 1995\
http://www.mat.uniroma3.it/users/pappa/CORSI/CR510_13_14/BosmaLenstra.pdf

View File

@ -218,10 +218,10 @@ func nDimMultiScalarRecoding[M, L: static int](
k[j].div2()
k[j] += SecretWord (bji and b[0][i])
func buildLookupTable[M: static int, F](
P: ECP_ShortW_Proj[F],
endomorphisms: array[M-1, ECP_ShortW_Proj[F]],
lut: var array[1 shl (M-1), ECP_ShortW_Proj[F]],
func buildLookupTable[M: static int, EC](
P: EC,
endomorphisms: array[M-1, EC],
lut: var array[1 shl (M-1), EC],
) =
## Build the lookup table from the base point P
## and the curve endomorphism
@ -271,8 +271,8 @@ func secretLookup[T](dst: var T, table: openArray[T], index: SecretWord) =
let selector = SecretWord(i) == index
dst.ccopy(table[i], selector)
func scalarMulEndo*[scalBits](
P: var ECP_ShortW_Proj,
func scalarMulEndo*[scalBits; EC](
P: var EC,
scalar: BigInt[scalBits]
) =
## Elliptic Curve Scalar Multiplication
@ -333,7 +333,7 @@ func scalarMulEndo*[scalBits](
P.cneg(isNeg0)
# 4. Precompute lookup table
var lut {.noInit.}: array[1 shl (M-1), ECP_ShortW_Proj]
var lut {.noInit.}: array[1 shl (M-1), typeof(P)]
buildLookupTable(P, endomorphisms, lut)
# TODO: Montgomery simultaneous inversion (or other simultaneous inversion techniques)
# so that we use mixed addition formulas in the main loop
@ -394,10 +394,10 @@ func scalarMulEndo*[scalBits](
# - 0t10 -> 0b10 is 2
# - 0t11 -> 0b11 is 3
func buildLookupTable_m2w2[F](
P0: ECP_ShortW_Proj[F],
P1: ECP_ShortW_Proj[F],
lut: var array[8, ECP_ShortW_Proj[F]],
func buildLookupTable_m2w2[EC](
P0: EC,
P1: EC,
lut: var array[8, EC],
) =
## Build a lookup table for GLV with 2-dimensional decomposition
## and window of size 2
@ -463,8 +463,8 @@ func computeRecodedLength(bitWidth, window: int): int =
let lw = (bitWidth + window - 1) div window + 1 + 1
result = (lw mod window) + lw
func scalarMulGLV_m2w2*[scalBits](
P0: var ECP_ShortW_Proj,
func scalarMulGLV_m2w2*[scalBits; EC](
P0: var EC,
scalar: BigInt[scalBits]
) =
## Elliptic Curve Scalar Multiplication
@ -497,7 +497,7 @@ func scalarMulGLV_m2w2*[scalBits](
# in the GLV representation at the low low price of 1 bit
# 4. Precompute lookup table
var lut {.noInit.}: array[8, ECP_ShortW_Proj]
var lut {.noInit.}: array[8, EC]
buildLookupTable_m2w2(P0, P1, lut)
# TODO: Montgomery simultaneous inversion (or other simultaneous inversion techniques)
# so that we use mixed addition formulas in the main loop

View File

@ -12,7 +12,6 @@ import
../arithmetic,
../towers,
../io/io_bigints,
./ec_shortweierstrass_projective,
./ec_endomorphism_accel
# ############################################################
@ -62,9 +61,9 @@ func getWindowLen(bufLen: int): uint =
while (1 shl result) + 1 > bufLen:
dec result
func scalarMulPrologue(
P: var ECP_ShortW_Proj,
scratchspace: var openarray[ECP_ShortW_Proj]
func scalarMulPrologue[EC](
P: var EC,
scratchspace: var openarray[EC]
): uint =
## Setup the scratchspace then set P to infinity
## Returns the fixed-window size for scalar mul with window optimization
@ -83,10 +82,10 @@ func scalarMulPrologue(
# Set a to infinity
P.setInf()
func scalarMulDoubling(
P: var ECP_ShortW_Proj,
func scalarMulDoubling[EC](
P: var EC,
exponent: openArray[byte],
tmp: var ECP_ShortW_Proj,
tmp: var EC,
window: uint,
acc, acc_len: var uint,
e: var int
@ -128,10 +127,10 @@ func scalarMulDoubling(
return (k, bits)
func scalarMulGeneric(
P: var ECP_ShortW_Proj,
func scalarMulGeneric[EC](
P: var EC,
scalar: openArray[byte],
scratchspace: var openArray[ECP_ShortW_Proj]
scratchspace: var openArray[EC]
) =
## Elliptic Curve Scalar Multiplication
##
@ -210,7 +209,7 @@ func scalarMulGeneric(
scratchspace[0].sum(P, scratchspace[1])
P.ccopy(scratchspace[0], SecretWord(bits).isNonZero())
func scalarMulGeneric*(P: var ECP_ShortW_Proj, scalar: BigInt, window: static int = 5) =
func scalarMulGeneric*[EC](P: var EC, scalar: BigInt, window: static int = 5) =
## Elliptic Curve Scalar Multiplication
##
## P <- [k] P
@ -222,13 +221,13 @@ func scalarMulGeneric*(P: var ECP_ShortW_Proj, scalar: BigInt, window: static in
## A window size will reserve 2^window of scratch space to accelerate
## the scalar multiplication.
var
scratchSpace: array[1 shl window, ECP_ShortW_Proj]
scratchSpace: array[1 shl window, EC]
scalarCanonicalBE: array[(scalar.bits+7) div 8, byte] # canonical big endian representation
scalarCanonicalBE.exportRawUint(scalar, bigEndian) # Export is constant-time
P.scalarMulGeneric(scalarCanonicalBE, scratchSpace)
func scalarMul*(
P: var ECP_ShortW_Proj,
func scalarMul*[EC](
P: var EC,
scalar: BigInt
) {.inline.} =
## Elliptic Curve Scalar Multiplication
@ -240,11 +239,11 @@ func scalarMul*(
## - Cofactor to be cleared
## - 0 <= scalar < curve order
## this will not automatically
when BigInt.bits <= ECP_ShortW_Proj.F.C.getCurveOrderBitwidth() and
ECP_ShortW_Proj.F.C in {BN254_Snarks, BLS12_377, BLS12_381}:
when ECP_ShortW_Proj.F is Fp:
when BigInt.bits <= EC.F.C.getCurveOrderBitwidth() and
EC.F.C in {BN254_Snarks, BLS12_377, BLS12_381}:
when EC.F is Fp:
P.scalarMulGLV_m2w2(scalar)
elif ECP_ShortW_Proj.F is Fp2:
elif EC.F is Fp2:
P.scalarMulEndo(scalar)
else: # Curves defined on Fp^m with m > 2
{.error: "Unreachable".}

View File

@ -107,7 +107,4 @@ func neg*(P: var ECP_ShortW_Aff) =
func cneg*(P: var ECP_ShortW_Aff, ctl: CTBool) =
## Conditional negation.
## Negate if ``ctl`` is true
var Q{.noInit.}: typeof(P)
Q.x = P.x
Q.y.neg(P.y)
P.ccopy(Q, ctl)
P.y.cneg(ctl)

View File

@ -0,0 +1,610 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
../primitives,
../config/[common, curves],
../arithmetic,
../towers,
./ec_shortweierstrass_affine
import ../io/io_fields
# ############################################################
#
# Elliptic Curve in Short Weierstrass form
# with Jacobian Coordinates
#
# ############################################################
type ECP_ShortW_Jac*[F] = object
## Elliptic curve point for a curve in Short Weierstrass form
## y² = x³ + a x + b
##
## over a field F
##
## in Jacobian coordinates (X, Y, Z)
## corresponding to (x, y) with X = xZ² and Y = yZ³
##
## Note that jacobian coordinates are not unique
x*, y*, z*: F
func `==`*[F](P, Q: ECP_ShortW_Jac[F]): SecretBool =
## Constant-time equality check
## This is a costly operation
# Reminder: the representation is not unique
var z1z1 {.noInit.}, z2z2 {.noInit.}: F
var a{.noInit.}, b{.noInit.}: F
z1z1.square(P.z)
z2z2.square(Q.z)
a.prod(P.x, z2z2)
b.prod(Q.x, z1z1)
result = a == b
a.prod(P.y, Q.z)
b.prod(Q.y, P.z)
a *= z2z2
b *= z1z1
result = result and a == b
func isInf*(P: ECP_ShortW_Jac): SecretBool =
## Returns true if P is an infinity point
## and false otherwise
##
## Note: the jacobian coordinates equation is
## Y² = X³ + aXZ⁴ + bZ⁶
## A "zero" point is any point with coordinates X and Z = 0
## Y can be anything
result = P.z.isZero()
func setInf*(P: var ECP_ShortW_Jac) =
## Set ``P`` to infinity
P.x.setOne()
P.y.setOne()
P.z.setZero()
func ccopy*(P: var ECP_ShortW_Jac, Q: ECP_ShortW_Jac, ctl: SecretBool) =
## Constant-time conditional copy
## If ctl is true: Q is copied into P
## if ctl is false: Q is not copied and P is unmodified
## Time and memory accesses are the same whether a copy occurs or not
for fP, fQ in fields(P, Q):
ccopy(fP, fQ, ctl)
func trySetFromCoordsXandZ*[F](P: var ECP_ShortW_Jac[F], x, z: F): SecretBool =
## Try to create a point the elliptic curve
## Y² = X³ + aXZ⁴ + bZ⁶ (Jacobian coordinates)
## y² = x³ + a x + b (affine coordinate)
## return true and update `P` if `x` leads to a valid point
## return false otherwise, in that case `P` is undefined.
##
## Note: Dedicated robust procedures for hashing-to-curve
## will be provided, this is intended for testing purposes.
P.y.curve_eq_rhs(x)
# TODO: supports non p ≡ 3 (mod 4) modulus like BLS12-377
result = sqrt_if_square(P.y)
var z2 {.noInit.}: F
z2.square(z)
P.x.prod(x, z2)
P.y *= z2
P.y *= z
P.z = z
func trySetFromCoordX*[F](P: var ECP_ShortW_Jac[F], x: F): SecretBool =
## Try to create a point the elliptic curve
## y² = x³ + a x + b (affine coordinate)
##
## The `Z` coordinates is set to 1
##
## return true and update `P` if `x` leads to a valid point
## return false otherwise, in that case `P` is undefined.
##
## Note: Dedicated robust procedures for hashing-to-curve
## will be provided, this is intended for testing purposes.
P.y.curve_eq_rhs(x)
# TODO: supports non p ≡ 3 (mod 4) modulus like BLS12-377
result = sqrt_if_square(P.y)
P.x = x
P.z.setOne()
func neg*(P: var ECP_ShortW_Jac, Q: ECP_ShortW_Jac) =
## Negate ``P``
P.x = Q.x
P.y.neg(Q.y)
P.z = Q.z
func neg*(P: var ECP_ShortW_Jac) =
## Negate ``P``
P.y.neg()
func cneg*(P: var ECP_ShortW_Jac, ctl: CTBool) =
## Conditional negation.
## Negate if ``ctl`` is true
P.y.cneg(ctl)
func sum*[F](
r: var ECP_ShortW_Jac[F],
P, Q: ECP_ShortW_Jac[F]
) =
## Elliptic curve point addition for Short Weierstrass curves in Jacobian coordinates
##
## R = P + Q
##
## Short Weierstrass curves have the following equation in Jacobian coordinates
## Y² = X³ + aXZ⁴ + bZ⁶
## from the affine equation
## y² = x³ + a x + b
##
## ``r`` is initialized/overwritten with the sum
##
## Implementation is constant-time, in particular it will not expose
## that P == Q or P == -Q or P or Q are the infinity points
## to simple side-channel attacks (SCA)
## This is done by using a "complete" or "exception-free" addition law.
#
# Implementation, see write-up at the bottom.
# We fuse addition and doubling with condition copy by swapping
# terms with the following table
#
# | Addition, Cohen et al, 1998 | Doubling, Cohen et al, 1998 | Doubling = -3 | Doubling a = 0 |
# | 12M + 4S + 6add + 1*2 | 3M + 6S + 1*a + 4add + 1*2 + 1*3 + 1half | | |
# | ----------------------------- | -----------------------------------------| ----------------- | -------------- |
# | Z₁Z₁ = Z₁² | Z₁Z₁ = Z₁² | | |
# | Z₂Z₂ = Z₂² | | | |
# | | | | |
# | U₁ = X₁*Z₂Z₂ | | | |
# | U₂ = X₂*Z₁Z₁ | | | |
# | S₁ = Y₁*Z₂*Z₂Z₂ | | | |
# | S₂ = Y₂*Z₁*Z₁Z₁ | | | |
# | H = U₂-U₁ # P=-Q, P=Inf, P=Q | | | |
# | R = S₂-S₁ # Q=Inf | | | |
# | | | | |
# | HH = H² | YY = Y₁² | | |
# | V = U₁*HH | S = X₁*YY | | |
# | HHH = H*HH | M = (3*X₁²+a*ZZ²)/2 | 3(X₁-ZZ)(X₁+ZZ)/2 | 3X₁²/2 |
# | | | | |
# | X₃ = R²-HHH-2*V | X₃ = M²-2*S | | |
# | Y₃ = R*(V-X₃)-S₁*HHH | Y₃ = M*(S-X₃)-YY*YY | | |
# | Z₃ = Z₁*Z₂*H | Z₃ = Y₁*Z₁ | | |
var Z1Z1 {.noInit.}, U1 {.noInit.}, S1 {.noInit.}, H {.noInit.}, R {.noinit.}: F
block: # Addition-only, check for exceptional cases
var Z2Z2 {.noInit.}, U2 {.noInit.}, S2 {.noInit.}: F
Z2Z2.square(Q.z)
S1.prod(Q.z, Z2Z2)
S1 *= P.y # S₁ = Y₁*Z₂³
U1.prod(P.x, Z2Z2) # U₁ = X₁*Z₂²
Z1Z1.square(P.z)
S2.prod(P.z, Z1Z1)
S2 *= Q.y # S₂ = Y₂*Z₁³
U2.prod(Q.x, Z1Z1) # U₂ = X₂*Z₁²
H.diff(U2, U1) # H = U₂-U₁
R.diff(S2, S1) # R = S₂-S₁
# Exceptional cases
# Expressing H as affine, if H == 0, P == Q or -Q
# H = U₂-U₁ = X₂*Z₁² - X₁*Z₂² = x₂*Z₂²*Z₁² - x₁*Z₁²*Z₂²
# if H == 0 && R == 0, P = Q -> doubling
# if only H == 0, P = -Q -> infinity, implied in Z₃ = Z₁*Z₂*H = 0
# if only R == 0, P and Q are related by the cubic root endomorphism
let isDbl = H.isZero() and R.isZero()
# Rename buffers under the form (add_or_dbl)
template R_or_M: untyped = R
template H_or_Y: untyped = H
template V_or_S: untyped = U1
var HH_or_YY {.noInit.}: F
var HHH_or_Mpre {.noInit.}: F
H_or_Y.ccopy(P.y, isDbl) # H (add) or Y₁ (dbl)
HH_or_YY.square(H_or_Y) # H² (add) or Y₁² (dbl)
V_or_S.ccopy(P.x, isDbl) # U₁ (add) or X₁ (dbl)
V_or_S *= HH_or_YY # V = U₁*HH (add) or S = X₁*YY (dbl)
block: # Compute M for doubling
when F.C.getCoefA() == 0:
var a = H
var b = HH_or_YY
a.ccopy(P.x, isDbl) # H or X₁
b.ccopy(P.x, isDbl) # HH or X₁
HHH_or_Mpre.prod(a, b) # HHH or X₁²
var M = HHH_or_Mpre # Assuming on doubling path
M.div2() # X₁²/2
M += HHH_or_Mpre # 3X₁²/2
R_or_M.ccopy(M, isDbl)
elif F.C.getCoefA() == -3:
var a{.noInit.}, b{.noInit.}: F
a.sum(P.x, Z1Z1)
b.diff(P.z, Z1Z1)
a.ccopy(H_or_Y, not isDbl) # H or X₁+ZZ
b.ccopy(HH_or_YY, not isDbl) # HH or X₁-ZZ
HHH_or_Mpre.prod(a, b) # HHH or X₁²-ZZ²
var M = HHH_or_Mpre # Assuming on doubling path
M.div2() # (X₁²-ZZ²)/2
M += HHH_or_Mpre # 3(X₁²-ZZ²)/2
R_or_M.ccopy(M, isDbl)
else:
# TODO: Costly `a` coefficients can be computed
# by merging their computation with Z₃ = Z₁*Z₂*H (add) or Z₃ = Y₁*Z₁ (dbl)
var a = H
var b = HH
a.ccopy(P.x, isDbl)
b.ccopy(P.x, isDbl)
HHH_or_Mpre.prod(a, b) # HHH or X₁²
# Assuming doubling path
a.square(HHH_or_Mpre)
a *= HHH_or_Mpre # a = 3X₁²
b.square(Z1Z1)
b *= F.C.getCoefA() # b = αZZ, with α the "a" coefficient of the curve
a += b
a.div2()
R_or_M.ccopy(a, isDbl) # (3X₁² - αZZ)/2
# Let's count our horses, at this point:
# - R_or_M is set with R (add) or M (dbl)
# - HHH_or_Mpre contains HHH (add) or garbage precomputation (dbl)
# - V_or_S is set with V = U₁*HH (add) or S = X₁*YY (dbl)
block: # Finishing line
var t {.noInit.}: F
t.double(V_or_S)
r.x.square(R_or_M)
r.x -= t # X₃ = R²-2*V (add) or M²-2*S (dbl)
r.x.csub(HHH_or_Mpre, not isDbl) # X₃ = R²-HHH-2*V (add) or M²-2*S (dbl)
V_or_S -= r.x # V-X₃ (add) or S-X₃ (dbl)
r.y.prod(R_or_M, V_or_S) # Y₃ = R(V-X₃) (add) or M(S-X₃) (dbl)
HHH_or_Mpre.ccopy(HH_or_YY, isDbl) # HHH (add) or YY (dbl)
S1.ccopy(HH_or_YY, isDbl) # S1 (add) or YY (dbl)
HHH_or_Mpre *= S1 # HHH*S1 (add) or YY² (dbl)
r.y -= HHH_or_Mpre # Y₃ = R(V-X₃)-S₁*HHH (add) or M(S-X₃)-YY² (dbl)
t = Q.z
t.ccopy(H_or_Y, isDbl) # Z₂ (add) or Y₁ (dbl)
t *= P.z # Z₁Z₂ (add) or Y₁Z₁ (dbl)
r.z.prod(t, H_or_Y) # Z₁Z₂H (add) or garbage (dbl)
r.z.ccopy(t, isDbl) # Z₁Z₂H (add) or Y₁Z₁ (dbl)
# if P or R were infinity points they would have spread 0 with Z₁Z₂
block: # Infinity points
r.ccopy(Q, P.isInf())
r.ccopy(P, Q.isInf())
func double*[F](
r: var ECP_ShortW_Jac[F],
P: ECP_ShortW_Jac[F]
) =
## Elliptic curve point doubling for Short Weierstrass curves in projective coordinate
##
## R = [2] P
##
## Short Weierstrass curves have the following equation in Jacobian coordinates
## Y² = X³ + aXZ⁴ + bZ⁶
## from the affine equation
## y² = x³ + a x + b
##
## ``r`` is initialized/overwritten with the sum
##
## Implementation is constant-time.
when F.C.getCoefA() == 0:
# "dbl-2009-l" doubling formula - https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
#
# Cost: 2M + 5S + 6add + 3*2 + 1*3 + 1*8.
# Source: 2009.04.01 Lange.
# Explicit formulas:
#
# A = X₁²
# B = Y₁²
# C = B²
# D = 2*((X₁+B)²-A-C)
# E = 3*A
# F = E²
# X₃ = F-2*D
# Y₃ = E*(D-X₃)-8*C
# Z₃ = 2*Y₁*Z₁
#
var A {.noInit.}, B{.noInit.}, C {.noInit.}, D{.noInit.}: F
A.square(P.x)
B.square(P.y)
C.square(B)
D.sum(P.x, B)
D.square()
D -= A
D -= C
D *= 2 # D = 2*((X₁+B)²-A-C)
A *= 3 # E = 3*A
r.x.square(A) # F = E²
B.double(D)
r.x -= B # X₃ = F-2*D
B.diff(D, r.x) # (D-X₃)
r.y.prod(A, B) # E*(D-X₃)
C *= 8
r.y -= C # Y₃ = E*(D-X₃)-8*C
r.z.prod(P.y, P.z)
r.z *= 2 # Z₃ = 2*Y₁*Z₁
else:
{.error: "Not implemented.".}
func `+=`*(P: var ECP_ShortW_Jac, Q: ECP_ShortW_Jac) =
## In-place point addition
# TODO test for aliasing support
var tmp {.noInit.}: ECP_ShortW_Jac
tmp.sum(P, Q)
P = tmp
func double*(P: var ECP_ShortW_Jac) =
var tmp {.noInit.}: ECP_ShortW_Jac
tmp.double(P)
P = tmp
func diff*(r: var ECP_ShortW_Jac,
P, Q: ECP_ShortW_Jac
) =
## r = P - Q
## Can handle r and Q aliasing
var nQ = Q
nQ.neg()
r.sum(P, nQ)
func affineFromJacobian*[F](aff: var ECP_ShortW_Aff[F], jac: ECP_ShortW_Jac) =
var invZ {.noInit.}, invZ2: F
invZ.inv(jac.z)
invZ2.square(invZ)
aff.x.prod(jac.x, invZ2)
aff.y.prod(jac.y, invZ)
aff.y.prod(jac.y, invZ2)
func projectiveFromJacobian*[F](jac: var ECP_ShortW_Jac, aff: ECP_ShortW_Aff[F]) {.inline.} =
jac.x = aff.x
jac.y = aff.y
jac.z.setOne()
# ############################################################
# #
# Deriving efficient and complete Jacobian formulae #
# #
# ############################################################
#
# We are looking for a complete addition formula,
# that minimize overhead over classic addition formulae
# from the litterature
# and can handle all inputs.
#
# We recall the basic affine addition and doubling formulae
#
# ```
# P + Q = R
# (Px, Py) + (Qx, Qy) = (Rx, Ry)
#
# with
# Rx = λ² - Px - Qx
# Ry = λ(Px - Rx) - Py
# and
# λadd = (Qy - Py) / (Px - Qx)
# λdbl = (3 Px² + a) / (2 Px)
# ```
#
# Which is also called the "chord-and-tangent" group law.
# Notice that if Px == Qx, addition is undefined, this can happen in 2 cases
# - P == Q, in that case we need to double
# - P == -Q, since -(x,y) = (x,-y) for elliptic curves. In that case we need infinity.
#
# Concretely, that means that it is non-trivial to make the code constant-time
# whichever case we are.
# Furthermore, Renes et al 2015 which introduced complete addition formulae for projective coordinates
# demonstrated that such a law cannot be as efficient for the Jacobian coordinates we are interested in.
#
# Since we can't rely on math, we will need to rely on implementation "details" to achieve our goals.
# First we look back in history at Brier and Joye 2002 unified formulae which uses the same code for addition and doubling:
#
# ```
# λ = ((x₁+x₂)² - x₁x₂ + a)/(y₁+y₂)
# x₃ = λ² - (x₁+x₂)
# 2y₃= λ(x₁+x₂-2x₃) - (y₁+y₂)
# ```
#
# Alas we traded exceptions depending on the same coordinate x
# for exceptions on negated coordinate y.
# This can still happen for P=-Q but also for "unrelated" numbers.
# > We recall that curves with equation `y² = x³ + b` are chosen so that there exist a cubic root of unity modulo r the curve order.
# > Hence x³ ≡ 1 (mod r), we call that root ω
# > And so we have y² = (ωx)³ + b describing a valid point with coordinate (ωx, y)
# > Hence the unified formula cannot handle (x, y) + (ωx, -y)
# > All pairings curves and secp256k1 have that equation form.
#
# Now, all hope is not lost, we recall that unlike in math,
# in actual implementation we havean excellent tool called conditional copy
# so that we can ninja-swap our terms
# provided addition and doubling are resembling each other.
#
# So let's look at the current state of the art formulae.
# I have added the spots where we can detect special conditions like infinity points, doubling and negation,
# and reorganized doubling operations so that they match multiplication/squarings in the addition law
#
# Let's look first at Cohen et al, 1998 formulae
#
# ```
# | Addition - Cohen et al | Doubling any a - Cohen et al | Doubling = -3 | Doubling a = 0 |
# | 12M + 4S + 6add + 1*2 | 3M + 6S + 1*a + 4add + 2*2 + 1*3 + 1*4 + 1*8 | | |
# |------------------------------|----------------------------------------------|-----------------|-------|
# | Z₁Z₁ = Z₁² | Z₁Z₁ = Z₁² | | |
# | Z₂Z₂ = Z₂² | | | |
# | | | | |
# | U₁ = X₁*Z₂Z₂ | | | |
# | U₂ = X₂*Z₁Z₁ | | | |
# | S₁ = Y₁*Z₂*Z₂Z₂ | | | |
# | S₂ = Y₂*Z₁*Z₁Z₁ | | | |
# | H = U₂-U₁ # P=-Q, P=Inf, P=Q | | | |
# | F = S₂-S₁ # Q=Inf | | | |
# | | | | |
# | HH = H² | YY = Y₁² | | |
# | HHH = H*HH | M = 3*X₁²+a*ZZ² | 3(X₁-Z₁)(X₁+Z₁) | 3*X₁² |
# | V = U₁*HH | S = 4*X₁*YY | | |
# | | | | |
# | X₃ = R²-HHH-2*V | X₃ = M²-2*S | | |
# | Y₃ = R*(V-X₃)-S₁*HHH | Y₃ = M*(S-X₃)-8*YY² | | |
# | Z₃ = Z₁*Z₂*H | Z₃ = 2*Y₁*Z₁ | | |
# ```
#
# This is very promising, as the expensive multiplies and squares n doubling all have a corresponding sister operation.
# Now for Bernstein et al 2007 formulae.
#
# ```
# | Addition - Bernstein et al | Doubling any a - Bernstein et al | Doubling = -3 | Doubling a = 0 |
# | 11M + 5S + 9add + 4*2 | 1M + 8S + 1*a + 10add + 2*2 + 1*3 + 1*8 | | |
# |----------------------------------|-----------------------------------------------------|-----------------|-------|
# | Z₁Z₁ = Z₁² | Z₁Z₁ = Z₁² | | |
# | Z₂Z₂ = Z₂² | | | |
# | | | | |
# | U₁ = X₁*Z₂Z₂ | | | |
# | U₂ = X₂*Z₁Z₁ | | | |
# | S₁ = Y₁*Z₂*Z₂Z₂ | | | |
# | S₂ = Y₂*Z₁*Z₁Z₁ | | | |
# | H = U₂-U₁ # P=-Q, P=Inf, P=Q | | | |
# | R = 2*(S₂-S₁) # Q=Inf | | | |
# | | | | |
# | | XX = X₁² (no matching op in addition, extra square) | | |
# | | YYYY (no matching op in addition, extra 2 squares) | | |
# | | | | |
# | I = (2*H)² | YY = Y₁² | | |
# | J = H*I | M = 3*X₁²+a*ZZ² | 3(X₁-Z₁)(X₁+Z₁) | 3*X₁² |
# | V = U₁*I | S = 2*((X₁+YY)²-XX-YYYY) = 4*X₁*YY | | |
# | | | | |
# | X₃ = R²-J-2*V | X₃ = M²-2*S | | |
# | Y₃ = R*(V-X₃)-2*S₁*J | Y₃ = M*(S-X₃)-8*YYYY | | |
# | Z₃ = ((Z₁+Z₂)²-Z₁Z₁-Z₂Z₂)*H | Z₃ = (Y₁+Z₁)² - YY - ZZ = 2*Y₁*Z₁ | | |
# ```
#
# Bernstein et al rewrites multiplication into squaring and 2 substraction.
#
# The first thing to note is that we can't use that trick to compute S in doubling
# and keep doubling resembling addition as we have not computed XX or YYYY yet
# and have no auspicious place to do so before.
#
# The second thing to note is that in the addition, they had to scale Z₃ by 2
# which scaled X₃ by 4 and Y₃ by 8, leading to the doubling in I, r coefficients
#
# Ultimately, it saves 1 mul but it costs 1S 3A 3*2. Here are some benchmarks for reference
#
# | Operation | Fp[BLS12_381] (cycles) | Fp2[BLS12_381] (cycles) | Fp4[BLS12_381] (cycles) |
# |-----------|------------------------|-------------------------|-------------------------|
# | Add | 14 | 24 | 47 |
# | Sub | 12 | 24 | 46 |
# | Ccopy | 5 | 10 | 20 |
# | Div2 | 14 | 23 | 42 |
# | Mul | 81 | 337 | 1229 |
# | Sqr | 81 | 231 | 939 |
#
# On G1 this is not good enough
# On G2 it is still not good enough
# On G4 (BLS24) or G8 (BLS48) we can revisit the decision.
#
# Let's focus back to Cohen formulae
#
# ```
# | Addition - Cohen et al | Doubling any a - Cohen et al | Doubling = -3 | Doubling a = 0 |
# | 12M + 4S + 6add + 1*2 | 3M + 6S + 1*a + 4add + 2*2 + 1*3 + 1*4 + 1*8 | | |
# |------------------------------|----------------------------------------------|-----------------|-------|
# | Z₁Z₁ = Z₁² | Z₁Z₁ = Z₁² | | |
# | Z₂Z₂ = Z₂² | | | |
# | | | | |
# | U₁ = X₁*Z₂Z₂ | | | |
# | U₂ = X₂*Z₁Z₁ | | | |
# | S₁ = Y₁*Z₂*Z₂Z₂ | | | |
# | S₂ = Y₂*Z₁*Z₁Z₁ | | | |
# | H = U₂-U₁ # P=-Q, P=Inf, P=Q | | | |
# | R = S₂-S₁ # Q=Inf | | | |
# | | | | |
# | HH = H² | YY = Y₁² | | |
# | HHH = H*HH | M = 3*X₁²+a*ZZ² | 3(X₁-Z₁)(X₁+Z₁) | 3*X₁² |
# | V = U₁*HH | S = 4*X₁*YY | | |
# | | | | |
# | X₃ = R²-HHH-2*V | X₃ = M²-2*S | | |
# | Y₃ = R*(V-X₃)-S₁*HHH | Y₃ = M*(S-X₃)-8*YY² | | |
# | Z₃ = Z₁*Z₂*H | Z₃ = 2*Y₁*Z₁ | | |
# ```
#
# > Reminder: Jacobian coordinates are related to affine coordinate
# > the following way (X, Y) <-> (X Z², Y Z³, Z)
#
# The 2, 4, 8 coefficients in respectively `Z₃=2Y₁Z₁`, `S=4X₁YY` and `Y₃=M(S-X₃)-8YY²`
# are not in line with the addition.
# 2 solutions:
# - either we scale the addition Z₃ by 2, which will scale X₃ by 4 and Y₃ by 8 just like Bernstein et al.
# - or we scale the doubling Z₃ by ½, which will scale X₃ by ¼ and Y₃ by ⅛. This is what Bos et al 2014 does for a=-3 curves.
#
# We generalize their approach to all curves and obtain
#
# ```
# | Addition (Cohen et al) | Doubling any a (adapted Bos et al, Cohen et al) | Doubling = -3 | Doubling a = 0 |
# | 12M + 4S + 6add + 1*2 | 3M + 6S + 1*a + 4add + 1*2 + 1*3 + 1half | | |
# | ----------------------------- | ----------------------------------------------- | ----------------- | -------------- |
# | Z₁Z₁ = Z₁² | Z₁Z₁ = Z₁² | | |
# | Z₂Z₂ = Z₂² | | | |
# | | | | |
# | U₁ = X₁*Z₂Z₂ | | | |
# | U₂ = X₂*Z₁Z₁ | | | |
# | S₁ = Y₁*Z₂*Z₂Z₂ | | | |
# | S₂ = Y₂*Z₁*Z₁Z₁ | | | |
# | H = U₂-U₁ # P=-Q, P=Inf, P=Q | | | |
# | R = S₂-S₁ # Q=Inf | | | |
# | | | | |
# | HH = H² | YY = Y₁² | | |
# | HHH = H*HH | M = (3*X₁²+a*ZZ²)/2 | 3(X₁-Z₁)(X₁+Z₁)/2 | 3X₁²/2 |
# | V = U₁*HH | S = X₁*YY | | |
# | | | | |
# | X₃ = R²-HHH-2*V | X₃ = M²-2*S | | |
# | Y₃ = R*(V-X₃)-S₁*HHH | Y₃ = M*(S-X₃)-YY² | | |
# | Z₃ = Z₁*Z₂*H | Z₃ = Y₁*Z₁ | | |
# ```
#
# So we actually replaced 1 doubling, 1 quadrupling, 1 octupling by 1 halving, which has the same cost as doubling/addition.
# We could use that for elliptic curve over Fp and Fp2.
# For elliptic curve over Fp4 and Fp8 (BLS24 and BLS48) the gap between multiplication and square is large enough
# that replacing a multiplication by squaring + 2 substractions and extra bookkeeping is worth it,
# we could use this formula instead:
#
# ```
# | Addition (adapted Bernstein et al) | Doubling any a (adapted Bernstein) | Doubling = -3 | Doubling a = 0 |
# | 11M + 5S + 9add + 4*2 | 2M + 7S + 1*a + 7add + 2*2+1*3+1*4+1*8 | | |
# | ---------------------------------- | ---------------------------------------- | --------------- | -------------- |
# | Z₁Z₁ = Z₁² | Z₁Z₁ = Z₁² | | |
# | Z₂Z₂ = Z₂² | | | |
# | | | | |
# | U₁ = X₁*Z₂Z₂ | | | |
# | U₂ = X₂*Z₁Z₁ | | | |
# | S₁ = Y₁*Z₂*Z₂Z₂ | | | |
# | S₂ = Y₂*Z₁*Z₁Z₁ | | | |
# | H = U₂-U₁ # P=-Q, P=Inf, P=Q | | | |
# | R = 2*(S₂-S₁) # Q=Inf | | | |
# | | | | |
# | I = (2*H)² | YY = Y₁² | | |
# | J = H*I | M = 3*X₁²+a*ZZ² | 3(X₁-Z₁)(X₁+Z₁) | 3*X₁² |
# | V = U₁*I | S = 4*X₁*YY | | |
# | | | | |
# | X₃ = R²-J-2*V | X₃ = M²-2*S | | |
# | Y₃ = R*(V-X₃)-2*S₁*J | Y₃ = M*(S-X₃)-8*YY² | | |
# | Z₃ = ((Z₁+Z₂)²-Z₁Z₁-Z₂Z₂)*H | Z₃ = (Y₁+Z₁)² - YY - ZZ | | |
# ```

View File

@ -34,6 +34,7 @@ type ECP_ShortW_Proj*[F] = object
func `==`*[F](P, Q: ECP_ShortW_Proj[F]): SecretBool =
## Constant-time equality check
## This is a costly operation
# Reminder: the representation is not unique
var a{.noInit.}, b{.noInit.}: F
@ -117,17 +118,13 @@ func neg*(P: var ECP_ShortW_Proj) =
func cneg*(P: var ECP_ShortW_Proj, ctl: CTBool) =
## Conditional negation.
## Negate if ``ctl`` is true
var Q{.noInit.}: typeof(P)
Q.x = P.x
Q.y.neg(P.y)
Q.z = P.z
P.ccopy(Q, ctl)
P.y.cneg(ctl)
func sum*[F](
r: var ECP_ShortW_Proj[F],
P, Q: ECP_ShortW_Proj[F]
) =
## Elliptic curve point addition for Short Weierstrass curves in projective coordinate
## Elliptic curve point addition for Short Weierstrass curves in projective coordinates
##
## R = P + Q
##

View File

@ -13,7 +13,8 @@ import
../towers,
../elliptic/[
ec_shortweierstrass_affine,
ec_shortweierstrass_projective
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian
]
# No exceptions allowed
@ -26,7 +27,7 @@ import
#
# ############################################################
func toHex*(P: ECP_ShortW_Proj): string =
func toHex*[EC](P: EC): string =
## Stringify an elliptic curve point to Hex
## Note. Leading zeros are not removed.
## Result is prefixed with 0x
@ -40,8 +41,13 @@ func toHex*(P: ECP_ShortW_Proj): string =
##
## This proc output may change format in the future
var aff {.noInit.}: ECP_ShortW_Aff[ECP_ShortW_Proj.F]
aff.affineFromProjective(P)
var aff {.noInit.}: ECP_ShortW_Aff[EC.F]
when EC is ECP_ShortW_Proj:
aff.affineFromProjective(P)
elif EC is ECP_ShortW_Jac:
aff.affineFromJacobian(P)
else:
aff = P
result = "ECP[" & $aff.F & "](\n x: "
result.appendHex(aff.x, bigEndian)
@ -49,7 +55,7 @@ func toHex*(P: ECP_ShortW_Proj): string =
result.appendHex(aff.y, bigEndian)
result &= "\n)"
func fromHex*(dst: var ECP_ShortW_Proj, x, y: string): bool {.raises: [ValueError].}=
func fromHex*(dst: var (ECP_ShortW_Proj or ECP_ShortW_Jac), x, y: string): bool {.raises: [ValueError].}=
## Convert hex strings to a G1 curve point
## Returns `false`
## if there is no point with coordinates (`x`, `y`) on the curve
@ -60,7 +66,7 @@ func fromHex*(dst: var ECP_ShortW_Proj, x, y: string): bool {.raises: [ValueErro
dst.z.setOne()
return bool(isOnCurve(dst.x, dst.y))
func fromHex*(dst: var ECP_ShortW_Proj, x0, x1, y0, y1: string): bool {.raises: [ValueError].}=
func fromHex*(dst: var (ECP_ShortW_Proj or ECP_ShortW_Jac), x0, x1, y0, y1: string): bool {.raises: [ValueError].}=
## Convert hex strings to a G2 curve point
## Returns `false`
## if there is no point with coordinates (`x`, `y`) on the curve

View File

@ -108,7 +108,7 @@ func neg*(r: var ExtensionField, a: ExtensionField) =
fR.neg(fA)
func neg*(a: var ExtensionField) =
## Field out-of-place negation
## Field in-place negation
for fA in fields(a):
fA.neg()
@ -172,6 +172,25 @@ func diffAlias*(r: var CubicExt, a, b: CubicExt) =
r.c1.diffAlias(a.c1, b.c1)
r.c2.diffAlias(a.c2, b.c2)
# Conditional arithmetic
# -------------------------------------------------------------------
func cneg*(a: var ExtensionField, ctl: SecretBool) =
## Constant-time in-place conditional negation
## Only negate if ctl is true
for fA in fields(a):
fA.cneg(ctl)
func cadd*(a: var ExtensionField, b: ExtensionField, ctl: SecretBool) =
## Constant-time in-place conditional addition
for fA, fB in fields(a, b):
fA.cadd(fB, ctl)
func csub*(a: var ExtensionField, b: ExtensionField, ctl: SecretBool) =
## Constant-time in-place conditional substraction
for fA, fB in fields(a, b):
fA.csub(fB, ctl)
# Multiplication by a small integer known at compile-time
# -------------------------------------------------------------------

View File

@ -10,7 +10,10 @@ import
../constantine/arithmetic/bigints,
../constantine/primitives,
../constantine/config/[common, curves],
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
../constantine/elliptic/[
ec_shortweierstrass_affine,
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian],
../constantine/io/io_bigints
# ############################################################
@ -226,7 +229,7 @@ func random_long01Seq[T](rng: var RngState, a: var T, C: static Curve) =
# Elliptic curves
# ------------------------------------------------------------
func random_unsafe[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_ShortW_Aff[F])) =
func random_unsafe[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_ShortW_Aff[F] or ECP_ShortW_Jac[F])) =
## Initialize a random curve point with Z coordinate == 1
## Unsafe: for testing and benchmarking purposes only
var fieldElem {.noInit.}: F
@ -238,7 +241,7 @@ func random_unsafe[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_Short
rng.random_unsafe(fieldElem, F.C)
success = trySetFromCoordX(a, fieldElem)
func random_unsafe_with_randZ[F](rng: var RngState, a: var ECP_ShortW_Proj[F]) =
func random_unsafe_with_randZ[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_ShortW_Jac[F])) =
## Initialize a random curve point with Z coordinate being random
## Unsafe: for testing and benchmarking purposes only
var Z{.noInit.}: F
@ -251,7 +254,7 @@ func random_unsafe_with_randZ[F](rng: var RngState, a: var ECP_ShortW_Proj[F]) =
rng.random_unsafe(fieldElem, F.C)
success = trySetFromCoordsXandZ(a, fieldElem, Z)
func random_highHammingWeight[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_ShortW_Aff[F])) =
func random_highHammingWeight[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_ShortW_Aff[F] or ECP_ShortW_Jac[F])) =
## Initialize a random curve point with Z coordinate == 1
## This will be generated with a biaised RNG with high Hamming Weight
## to trigger carry bugs
@ -264,7 +267,7 @@ func random_highHammingWeight[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] o
rng.random_highHammingWeight(fieldElem, F.C)
success = trySetFromCoordX(a, fieldElem)
func random_highHammingWeight_with_randZ[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_ShortW_Aff[F])) =
func random_highHammingWeight_with_randZ[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_ShortW_Jac[F])) =
## Initialize a random curve point with Z coordinate == 1
## This will be generated with a biaised RNG with high Hamming Weight
## to trigger carry bugs
@ -278,7 +281,7 @@ func random_highHammingWeight_with_randZ[F](rng: var RngState, a: var (ECP_Short
rng.random_highHammingWeight(fieldElem, F.C)
success = trySetFromCoordsXandZ(a, fieldElem, Z)
func random_long01Seq[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_ShortW_Aff[F])) =
func random_long01Seq[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_ShortW_Aff[F] or ECP_ShortW_Jac[F])) =
## Initialize a random curve point with Z coordinate == 1
## This will be generated with a biaised RNG
## that produces long bitstrings of 0 and 1
@ -292,7 +295,7 @@ func random_long01Seq[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_Sh
rng.random_long01Seq(fieldElem, F.C)
success = trySetFromCoordX(a, fieldElem)
func random_long01Seq_with_randZ[F](rng: var RngState, a: var ECP_ShortW_Proj[F]) =
func random_long01Seq_with_randZ[F](rng: var RngState, a: var (ECP_ShortW_Proj[F] or ECP_ShortW_Jac[F])) =
## Initialize a random curve point with Z coordinate == 1
## This will be generated with a biaised RNG
## that produces long bitstrings of 0 and 1
@ -313,7 +316,7 @@ func random_long01Seq_with_randZ[F](rng: var RngState, a: var ECP_ShortW_Proj[F]
func random_unsafe*(rng: var RngState, T: typedesc): T =
## Create a random Field or Extension Field or Curve Element
## Unsafe: for testing and benchmarking purposes only
when T is (ECP_ShortW_Proj or ECP_ShortW_Aff):
when T is (ECP_ShortW_Proj or ECP_ShortW_Aff or ECP_ShortW_Jac):
rng.random_unsafe(result)
elif T is SomeNumber:
cast[T](rng.next()) # TODO: Rely on casting integer actually converting in C (i.e. uint64->uint32 is valid)
@ -322,7 +325,7 @@ func random_unsafe*(rng: var RngState, T: typedesc): T =
else: # Fields
rng.random_unsafe(result, T.C)
func random_unsafe_with_randZ*(rng: var RngState, T: typedesc[ECP_ShortW_Proj]): T =
func random_unsafe_with_randZ*(rng: var RngState, T: typedesc[ECP_ShortW_Proj or ECP_ShortW_Jac]): T =
## Create a random curve element with a random Z coordinate
## Unsafe: for testing and benchmarking purposes only
rng.random_unsafe_with_randZ(result)
@ -330,7 +333,7 @@ func random_unsafe_with_randZ*(rng: var RngState, T: typedesc[ECP_ShortW_Proj]):
func random_highHammingWeight*(rng: var RngState, T: typedesc): T =
## Create a random Field or Extension Field or Curve Element
## Skewed towards high Hamming Weight
when T is (ECP_ShortW_Proj or ECP_ShortW_Aff):
when T is (ECP_ShortW_Proj or ECP_ShortW_Aff or ECP_ShortW_Jac):
rng.random_highHammingWeight(result)
elif T is SomeNumber:
cast[T](rng.next()) # TODO: Rely on casting integer actually converting in C (i.e. uint64->uint32 is valid)
@ -339,7 +342,7 @@ func random_highHammingWeight*(rng: var RngState, T: typedesc): T =
else: # Fields
rng.random_highHammingWeight(result, T.C)
func random_highHammingWeight_with_randZ*(rng: var RngState, T: typedesc[ECP_ShortW_Proj]): T =
func random_highHammingWeight_with_randZ*(rng: var RngState, T: typedesc[ECP_ShortW_Proj or ECP_ShortW_Jac]): T =
## Create a random curve element with a random Z coordinate
## Skewed towards high Hamming Weight
rng.random_highHammingWeight_with_randZ(result)
@ -347,7 +350,7 @@ func random_highHammingWeight_with_randZ*(rng: var RngState, T: typedesc[ECP_Sho
func random_long01Seq*(rng: var RngState, T: typedesc): T =
## Create a random Field or Extension Field or Curve Element
## Skewed towards long bitstrings of 0 or 1
when T is (ECP_ShortW_Proj or ECP_ShortW_Aff):
when T is (ECP_ShortW_Proj or ECP_ShortW_Aff or ECP_ShortW_Jac):
rng.random_long01Seq(result)
elif T is SomeNumber:
cast[T](rng.next()) # TODO: Rely on casting integer actually converting in C (i.e. uint64->uint32 is valid)
@ -356,7 +359,7 @@ func random_long01Seq*(rng: var RngState, T: typedesc): T =
else: # Fields
rng.random_long01Seq(result, T.C)
func random_long01Seq_with_randZ*(rng: var RngState, T: typedesc[ECP_ShortW_Proj]): T =
func random_long01Seq_with_randZ*(rng: var RngState, T: typedesc[ECP_ShortW_Proj or ECP_ShortW_Jac]): T =
## Create a random curve element with a random Z coordinate
## Skewed towards long bitstrings of 0 or 1
rng.random_long01Seq_with_randZ(result)

View File

@ -10,7 +10,6 @@ import
# Internals
../../constantine/config/[common, curves],
../../constantine/arithmetic,
../../constantine/elliptic/ec_shortweierstrass_projective,
../../constantine/io/io_bigints
# Support files for testing Elliptic Curve arithmetic
@ -26,8 +25,8 @@ iterator unpack(scalarByte: byte): bool =
yield bool((scalarByte and 0b00000010) shr 1)
yield bool( scalarByte and 0b00000001)
func unsafe_ECmul_double_add*(
P: var ECP_ShortW_Proj,
func unsafe_ECmul_double_add*[EC](
P: var EC,
scalar: BigInt,
) =
## **Unsafe** Elliptic Curve Scalar Multiplication

View File

@ -14,7 +14,10 @@ import
../constantine/arithmetic,
../constantine/towers,
../constantine/io/[io_bigints, io_ec],
../constantine/elliptic/[ec_shortweierstrass_projective, ec_scalar_mul, ec_endomorphism_accel],
../constantine/elliptic/[
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian,
ec_scalar_mul, ec_endomorphism_accel],
# Test utilities
./support/ec_reference_scalar_mult
@ -22,13 +25,13 @@ echo "\n------------------------------------------------------\n"
proc test(
id: int,
EC: typedesc[ECP_ShortW_Proj],
EC: typedesc[ECP_ShortW_Proj or ECP_ShortW_Jac],
Px, Py: string,
scalar: string,
Qx, Qy: string
) =
test "test " & $id:
test "test " & $id & " - " & $EC:
var P: EC
let pOK = P.fromHex(Px, Py)
doAssert pOK
@ -156,16 +159,118 @@ suite "Scalar Multiplication (cofactor cleared): BLS12_377 implementation vs Sag
Qy = "191628b702ebef397bb7c52102ee4522f864ff594b24dc385ece081e8066bcde20aa5c7dfd00fb1f3cea221b3ad4ea2"
)
# ----------------------------------------
test(
id = 0,
EC = ECP_ShortW_Jac[Fp[BLS12_377]],
Px = "4e7e6dfa01ed0ceb6e66708b07cb5c6cd30a42eeb13d7b76f8d103a0a4d491450be6f526fc12f15209b792220c041e",
Py = "c782515159b7e7b9371e0e0caa387951317e993b1625d91869d4346621058a0960ef1b8b6eabb33cd5719694908a05",
scalar = "cf815cb4d44d3d691b7c82a40b4b70caa9b0e8fe9586648abf3f1e2e639ca1b",
Qx = "4a1203db4af8f0efc18c7ceb24999eb6e0dbdfc8f44a9edd5ba2f9eced38e81ecae287ab1c184eea8e8753d1178604",
Qy = "f7509cdce5de473e37f36c69d93ff1b2ab04c3ae25a3b5e41f2c138cdcc69ed5eaf4ac95a7a857eef336ebac19bcd3"
)
test(
id = 1,
EC = ECP_ShortW_Jac[Fp[BLS12_377]],
Px = "13d735b28405253dcc0bc60bcdc13633475ffc187d38a9b97655b0d0fa1d56c4548f11ea0a795391ee85c953aaf9b83",
Py = "1693101123fd13a20f9c0569c52c29507ba1c8b6dd412660bc82e7974022f1a10f9137b4ba59d3f0aab67027cefec19",
scalar = "913aa7b9fa2f940b70b6dcf538cc08da1a369809ab86a8ee49cead0ed6bfef6",
Qx = "10e0e8582ec3456f7569473892c23997d004f2542d914fa75db8f1798ed8ce505836e8b7af5cf1503e14d85fadd65ee",
Qy = "d5151ae60e43100e20aad7eaf8659e690e8034910d7717078031520fcbf6f9a00b22c6a9894aec88c9182f13335639"
)
test(
id = 2,
EC = ECP_ShortW_Jac[Fp[BLS12_377]],
Px = "6dd2211113cada09d3b96848cbf21ed14f6fc238b581c0afd49aa776980101e4ee279a256ce8f1428d3ed3f70afd85",
Py = "3b406b4433a3f44f8e196012f50c520e876412fbcae2651916f133c1fd3899c79f676e1abba01d84bab7ad100c9295",
scalar = "4cf47669aeb0f30b6c6c5aa02808a87dc787fba22da32875e614a54a50b6a0c",
Qx = "3caf55e1f82d746df2bf47defbee127a3e6f7e79a9575929704b25489ffb801dbce07999acbddfd79352b0633a2708",
Qy = "3fc275c136b07456f0b6ee814508876037add5e95357fae6b4195744ba5ccccaf93581e34feb2babe652a9a704731b"
)
test(
id = 3,
EC = ECP_ShortW_Jac[Fp[BLS12_377]],
Px = "18648abbe3261f93cbf679777eac66e419035041a967d1e6a0f0afdb92810d7122e0984f1d6efc8fe518500464ee803",
Py = "7b6f518d4d06309aad4d60d29118310b6c8b17c7bf5db2251f4701b13b89a8c0f04bb5d0386785e55ffbbd7ecc445e",
scalar = "69498486a06c18f836a8e9ed507bbb563d6d03545e03e08f628e8fbd2e5d098",
Qx = "6a871d872673879fd23ec8c150f8d63e8130dc60343fc0c2ec9ff1b02e769e20eeec0288102ccec6ff2f6ac6973b4",
Qy = "cd95a31afa4f0bbcc063a1585fec4a6c51812b2baaee42a04525fd55b3a9db3bdb7cbc77f7cd32f42d2e0eb26ddfa2"
)
test(
id = 4,
EC = ECP_ShortW_Jac[Fp[BLS12_377]],
Px = "745e9944549522486f3446676cc62fb666682e10c661a13b8110b42cb9a37676b6f33a46f9495f4fafb342d5809db5",
Py = "bc595854bc42ccec60dd9ec573608d736aa59996cef1c2e8f6c5d424f525a6f3e3d4beeedfac6b959dbd71ced95b13",
scalar = "6e08d8714102a5aa3e9f46e33c70a759c27253c7b0196c3e46c7cb42671197e",
Qx = "18a967a80785de8ec6ac9d98cffa06a8c633b5fa0f36431a32f7bd955946edc3d55f79bfdf5335db405560a6cbe2415",
Qy = "4552ff2eb6ade0c6b33c3603460d9d62099201d842c9883b33b7ed1147cb17268338a77a9417776ddbd774e91a8d2"
)
test(
id = 5,
EC = ECP_ShortW_Jac[Fp[BLS12_377]],
Px = "f7b56cf212a8906ed77a758164c0bd05ce1fbd3ee3c4357e7a09b3aedc748a29ace254f1f6df35b8cb74361060337f",
Py = "2640ef641d20fea19b28947833e53faceeafa57a8761b807049f3d707d70c01f1c69a57edd993d301a64517bf47f77",
scalar = "a5c46d7a52938fed7f3093d5867f65361dc8b48c83bd7db490c26736196e20e",
Qx = "434f024c4afd7b9a44375011d663af0ae0fe79442e9caf36518e053bb13d49998ec1d2da4bc1c4a812812119b3221f",
Qy = "32c959e2a678cf93f77e621fdf887454a5f9cb7a67f29065669f48234c25e321ceb5758dfba987431a0c2caec94616"
)
test(
id = 6,
EC = ECP_ShortW_Jac[Fp[BLS12_377]],
Px = "43b387c12e4cc91fb1a5593b7671356dceb0fe6e6ac666d5bac94f2a44c8db54976b649a678aae038b21144de04e23",
Py = "1a6366a50f1f9ba64eef73d82bec86177bf184be048a9d66326ccb0122203569ddcb8cf74445cadaff7f47a66d1b1a2",
scalar = "bddd07231bc7fe89ee4a859a00ea1f9d236be9e7fd561303d566904c1b0a07c",
Qx = "8ddb7a959483b51a1471de988146b7d5b166f660734b4d55166c5a23d781e923261927b1012dce73b822bb6e56bfd2",
Qy = "dc7178bf5597ef31209a5b0409fc42c64b81260a0046a562ca08c7a9dc67b444c25e94fb97b9a6bb4c137cadd81021"
)
test(
id = 7,
EC = ECP_ShortW_Jac[Fp[BLS12_377]],
Px = "6984c9385a67081f97b3d33444077466cca1d0442a4da8c083a0957578e0b21011435b126a5ab143da9da1cf5b216f",
Py = "18a87c7f5f6c5a8101773e63956b9addd4becf5177acc560d548e5331638121934842fdc9f654b3f456a7df5a2e471a",
scalar = "b72c41a6ffaff0aacb5d62e3dcb16acfec66b6a9639e19d3128fd43c18e7dbe",
Qx = "19279201c3c7a9d50b546aa99d3e1a6625fe2a7bc64a09625b683534638b9e87b9102d4dba6684956b6be7668a658c6",
Qy = "195f15ad1edc05f8b289c7eee7bd8f78116a2d5ba8b83643d9e7cb2cdc6550bcf8c2145008e900ca9cba4d5040e9f4"
)
test(
id = 8,
EC = ECP_ShortW_Jac[Fp[BLS12_377]],
Px = "efc34595823e7333616f7768bc82f407268df6f029bf4c94d15f1785dc7ccc08f22e7301dfc48dadc0ea383c8bb3e",
Py = "2459bd9f71977ef122d2102e8bfd07a5737066075058cfa8bcaa9f9690ed065919c844363ceaea6f9bb650906a535f",
scalar = "8f90f6ab0ffa6e4acc601b44c062745f2935b3dc153d0da07977470080d5c18",
Qx = "35d08b33e02579581905941975c8b1cc5be1c9670a7f7ef390daa363b0abd3571a802d8c27f156fba40573094f6c7a",
Qy = "111ba3bdfa4260dc2b636479edb1fcf2fc9478aa722da0118908e1db1551cf7e131c8521b2f3708ef670684dbe8d181"
)
test(
id = 9,
EC = ECP_ShortW_Jac[Fp[BLS12_377]],
Px = "3eec93c2a9c5fd03f0de5ede2fdac9e361090fbaea38e4a0f1828745f1d14a057d9fd7c46b9168bd95a45a182a3a62",
Py = "e912dc7e95f90d91e3274ec5639edacb88be1b092c47c13d31a29ecd579885cc09f197f8207d23b2260ab10c94d5f5",
scalar = "203300e949aff816d084a388f07c74b9152bb11b523543afd65c805a389980",
Qx = "8c23ae9c51e7c92c6a59f0ed07a59f148b4d79394fc026931c264612041eedd3782e4f249bbfad1799212788c1a00d",
Qy = "191628b702ebef397bb7c52102ee4522f864ff594b24dc385ece081e8066bcde20aa5c7dfd00fb1f3cea221b3ad4ea2"
)
proc test(
id: int,
EC: typedesc[ECP_ShortW_Proj],
EC: typedesc[ECP_ShortW_Proj or ECP_ShortW_Jac],
Px0, Px1, Py0, Py1: string,
scalar: string,
Qx0, Qx1, Qy0, Qy1: string
) =
test "test " & $id:
test "test " & $id & " - " & $EC:
var P: EC
let pOK = P.fromHex(Px0, Px1, Py0, Py1)
doAssert pOK
@ -329,3 +434,145 @@ suite "Scalar Multiplication G2: BLS12-381 implementation vs SageMath" & " [" &
Qy0 = "a784902a14ad39adcfdc52bc30d8b8711b93dd869af2375a1f408ba8610b5c558bbebfe9f8f9875954780f4b4262c0",
Qy1 = "fb1c766957c89e4d67747549f650070983e6c19d0208b7e65478e4dd4f72fc54fca450d96329182e3f00d16ae0f3a"
)
# -----------------
test(
id = 0,
EC = ECP_ShortW_Jac[Fp2[BLS12_377]],
Px0 = "267401f3ef554fe74ae131d56a10edf14ae40192654901b4618d2bf7af22e77c2a9b79e407348dbd4aad13ca73b33a",
Px1 = "12dcca838f46a3e0418e5dd8b978362757a16bfd78f0b77f4a1916ace353938389ae3ea228d0eb5020a0aaa58884aec",
Py0 = "11799118d2e054aabd9f74c0843fecbdc1c0d56f61c61c5854c2507ae2416e48a6b2cd3bc8bf7495a4d3d8270eafe2b",
Py1 = "823b9f8fb9f8297734a14359fa2c2a0de275e7e638197eaaaa7cff28f9cb3101bdabb570016672455f1ecae625e294",
scalar = "9d432eb58ec68bbc09d10961451d99c7796fb2f795eca603d6feaf3e2a1634b",
Qx0 = "12cfcb50345d43271d2a20e8208789c8ca82f2b8732fae4e7cccd87eb0883741d5e77166971c38c54170bf7635ca2f3",
Qx1 = "17467c786368f2f6eabd78f1c24aa668eae9cd00f6045bfd86b1b3c40966f023a71927026ae5a1281b432ac980d2b6b",
Qy0 = "6f5f1068b6e6a8fafd96894d8b0a8548acee24319d8e2d8b6e6982b1ced8970d9fe33155e74b33d6c2a7835196ca9",
Qy1 = "dc3c7c91c712f9a2631d2b5e49497d8cdf2ea4b30859b43edd716e84cd6a8b61e63cf708d263a7845913cdfb9c7f3b"
)
test(
id = 1,
EC = ECP_ShortW_Jac[Fp2[BLS12_377]],
Px0 = "3a3055d6a46901c1b2227a0e334ffa9f654e62a6d3608f3a672e5816f9e9b04c0e668c3e9f8c807b269422afdc7de9",
Px1 = "25803bd55f37b254865d5fc7ac9843fb306c2eb09d34ee0c4ecb705b5e10f6911f07fd707a2e28681a421f45b1a4d",
Py0 = "15a0594a3c9dddc535472c4827aa443774a06f77bec2d20837c6574aa5fac35a279bac756531fa75f979a7a97f297d6",
Py1 = "15e8c3e013cbc64110f075295f39a4f85c9591a52b8e4903047b1f4b44bb5216b6339788c82fd90e82b1027756e7987",
scalar = "a0067f5b4294fbacd24730fed25c936a08b5f1a77824149ad6c2ce476518d17",
Qx0 = "6280dbf019f8d94acac4a39213e03f221be732849b45437edef7617460e83f972883c20791a86670a8a4c6c0125629",
Qx1 = "ab3a185addbd6c7db907170d75bd2f1997666e93d8cedbef9e10a103110d4ea09d9a889f505d7026e5c498b0355c1",
Qy0 = "1a6dd15b4c2bd6bd97858e5a75ac4365f8becaa885c4e3267d0ae256655cd057061d61b2b9acbd10bdf678a9c1e7f8c",
Qy1 = "16204b5825eec903cb7798cb62ccadb9004032d72bb815958fcd2f613c77e147656449fdaa210994338978676ad6b0e"
)
test(
id = 2,
EC = ECP_ShortW_Jac[Fp2[BLS12_377]],
Px0 = "18ebf549cd24a64badff4ec177205be121757b68589020434aba816756d2e6fa95fdb389c8639d4bf77575122e1c04e",
Px1 = "11cd0f0976658a6f2ec113034428ef1605befdaa5642944f5c4e571b24fc166c368c30473e25ab148209be4c0b4e37",
Py0 = "1190d818317495201732feb2cfc8f507adac6273debff46bb6aea4a3f3e3fe7d28d893c90b21a6f28d2fbc72d9fc528",
Py1 = "df5fcb2daa302a5c64aeef96835e0a6b39f5d7bf0e70cc10401f966745a6b3fa682b7e5b45d9295e744e1dd7855fd4",
scalar = "7a49802ba58c87c30b631b2f90a3b876c7143e09b542c9c14706bddf9bd4117",
Qx0 = "6cdff80576d8695a646f915caba5bc6748eee1707bb0d4ebcabaf8d236b780aef6a953a07f48ef4696f02db4906c71",
Qx1 = "6b64ca5f0d46702e7e9e7beb1993b698c9b3e9991f545241d5fd44a27dc692d5f5a4c2fe6871af0653128f960307d4",
Qy0 = "cfad02b664495d42d1c6b598306229c67bcf76cc923abb13ae038c90e959a7611161a98d607729577d55ec18bf1e74",
Qy1 = "e433d9dd7d47d94e9f61a5bc27a688c63efa05408d6fd40a5c4e2711a37d011dc80f5dbaaafd939a07235c770feead"
)
test(
id = 3,
EC = ECP_ShortW_Jac[Fp2[BLS12_377]],
Px0 = "52b54c30c1dcadbcb698d0cb7fd65de1eb8f7590c7afe46e019bdc9e0ef8bc4c060339220d3615e4b1f2b12ffa6d83",
Px1 = "dd53b483c2ab1aaa7ed22ef619b5e979237ae95476436f2c51c8b70da39a4e54a989f10f6d12ee098154911aa052f6",
Py0 = "2a8c96662a7c76cb7d8ca6571a5b99abfd2d7343dd668425e5fa4a8c880b313b70f09a15a825fac63ae7065c0c51d",
Py1 = "7bd93bb9d5bfdd15636a34a13385e9abbc1088ecc02c86cbc733122ccbbb657ec8d75e47102ce46d35a9612c01fc3d",
scalar = "e0c564e69ad68343fd4ec3d4dafdf6a92f44c13fc70a9aad95d10b2c96ee747",
Qx0 = "126f6039b7031b73a7f926bd443ace416f62e56f03864d660bbe1f1a2a994672d408f9936293f367d3fb5d8e275ad40",
Qx1 = "1654a2c26479ace1eb68e279eceac6aa10680549b09f42d288767f6296c98ba4299fa6df37a946b88823a5deebc231c",
Qy0 = "23026839059191f71e2abcf582234aa2ce4b4225c3d503e8fc6c119df1168192e894f33ed48bc571e5527365dd92b5",
Qy1 = "11f8fcce53f5e3211290e6c72736eb1c9d2e159dd243f3e493c430f0411864e109af09a3b9379c4b332815e012caa80"
)
test(
id = 4,
EC = ECP_ShortW_Jac[Fp2[BLS12_377]],
Px0 = "fb6dd822e327a60c9e55d760c4f5d26783617a06f868835c2f46e902108eaca5d60fd64c0a0c8a6dc12f9352dfef33",
Px1 = "85e97eef3b4e42a93b8421644e9334f4543a25a36ccd41d448c385146baf3b1efbaeac49c202b04cdbf8b50f3fd962",
Py0 = "8db78b315a524f17ac3d69333604e6bc8aa0b2f138f9adf7edb19f49c847eda6b64df9fe2576b7687e7b55cb5f0bd0",
Py1 = "d4a0c7e5e7aaacab0e0e60c6c49624971a161de4f0daa7968f80998fb7b4761b1196964b26fefa9337fd133784e3d9",
scalar = "1abce9e9c079c686864304d479d68087db33f9edb3f7b2e4655fe0c1da4993f",
Qx0 = "1238814ea497bc1b65ba1c0fbfc394427b10b2d8783bf6a04e01505bc165b577cb2366c19c24c555235ff9b16e7233a",
Qx1 = "b156205cad5d2d97d24c45fe218cd412f47248f26d579fb368af5ba2d80b8c95e2a68f4c84540a8b78b2f0a33a48a4",
Qy0 = "12154ce4a569b39ccfe464a7559b8baf03d3fb6462e67dc0c4ae79a3c33b7756e0c558eff64f9558ebd6500086684f8",
Qy1 = "74571a18fc091f4d77cc7d363bf7a34ab4d0dca86c160b261b383e416f68fa553d7b8b8f6317c8e340ce454daffb5f"
)
test(
id = 5,
EC = ECP_ShortW_Jac[Fp2[BLS12_377]],
Px0 = "b56e23f2558c3c124f024952e1858067223541f51a8885d161133beb7bf8d64f22163769e604afbf7fbfb02e1fcb43",
Px1 = "e10c4366d667b40488a9ae32daf3e2a5cc8ddf25ed407afe1a38b855f3ac4f7ea20455924e71369eed07114613b633",
Py0 = "f42d3ab4716d10384bcdfec38cba997c2bafb8d8de32a47225a3e2d2835be1ad02a63323d3dd4145db21e3cbf5cc7a",
Py1 = "15f48a901f3dfd3b812a455f1297e8311c4608869ea02d3d16e9aafdf610d7e72f34b02830de8cc0d0f4e909af5827d",
scalar = "401e70df8ccaa504da72b1d649c067f3b752156dcea5b48dcb601710ab0baa3",
Qx0 = "949099ea1ece1be6fa3f3537e8ba39587b40003fb409a4beb831bb1d9d999b7c621b9a1ced3223f710e0bd05f4a018",
Qx1 = "cdfc0d47788bca3672126e0facc05c19a4fb24a43eee32c8e08a6e5152f6af1d7c2efa48907046f90a721ed28fcf7",
Qy0 = "11d608a01cfe1a40806b9951f85a7bb1b6df6e4c4e2c7c50c17e8fad6ed397a430aff9b4742408367d6536fe503692a",
Qy1 = "19c25d8a782b9d8d9f067d345fd03afe50439c82f99a06abca790f2fae944677d8095d2e276fcb7a75cfb2cbccf89d7"
)
test(
id = 6,
EC = ECP_ShortW_Jac[Fp2[BLS12_377]],
Px0 = "137001541ab8a479362ee39f818fc38788231e5288ceea5ebe0c08d0bbca3be9519aa415bde98428df26d361b7311ea",
Px1 = "411b1a4f0abb9fd255a7ae26ac39c1f2c88a48f82c7623b6f225aec9755206e27084b23cbc98f31399405a6599dc54",
Py0 = "833ef097986116cab669c4fddff9b831535d100644f732fb0da0a2dce17d69beaeed67230dd66392e840679afbae1e",
Py1 = "f63e809bd55617c31570d686dbc9b94b3cb96c154f9983181cb913a0671c0c16143332087e44a0283ebf01eea6d73b",
scalar = "10697220c755c800861d377c55b22ae48c25dc144e1fa7a1e5bbdf82993aa33c",
Qx0 = "10fc7772bb2bc946e3ff659c01a0452ebf5dd1472bd1aa71e198597fd05361bf0d173817f91fcb8a1b96b46c35d2675",
Qx1 = "d7b00ddf32f9d8e549c05dd605931ef737d8a4bc62795f73044482957b8093b1cdad0f55c7d4edf6f59594a13f9b67",
Qy0 = "148756a592dec0bf2fda41ac219c4a891ef427665ba1cf47b58bed4996cf8937fb07929c041f10e8a55b2238944fd30",
Qy1 = "e4a240f5c32dab76575ace4d035cbd1e2b87d7585fee7bfde9c88e918a7ad2cd8eb4982acfacfac58c33c8a54ddac7"
)
test(
id = 7,
EC = ECP_ShortW_Jac[Fp2[BLS12_377]],
Px0 = "1580ffccc21b057dfe4831f950cbb8f1436f999df657404ecec20225a929a5d56920e8662abc426de23402643087308",
Px1 = "8bf8ff20713a9054aa1cce9635eb3d6ac8371fc052b747a8414595708ff9462d64a0a11ff2c1c5121f4ecc5f22df5e",
Py0 = "e7a5f7df0cec03de25da415fdda485ecc1443b95352e47b23e5506b820c9bc9ea9c2d9e99dd48e1f74e1befe58ce80",
Py1 = "12b5638a0f7e508016fddd2dae2d84736efa59c53f2a5d979b9a29fc7c9c406407bb5f5788bcea3529ac1a763c72e8b",
scalar = "bd936c7066316d3f86b077419a0c0fb9867d4612208241fc004b548f1f54fad",
Qx0 = "69e3411725062858ca7e5fc4d648037baf10e34ba6830ff0090e7188932112b9458c4f4b82f2f0f06c6501fcdaa86c",
Qx1 = "127b75c55c90a872c1d749d05609d2499065ac3c9eb96bd6a9816bd7a2315795ddf40944baef1907676395df306860e",
Qy0 = "13fd0e314159909d3091e382017b35ec21ee2004e9082cd24338817046ed2202ffed52e7714cf436b953f95f49f9856",
Qy1 = "5a8ccdf4a1600fafcc86c646d83199c41cbfebf7a1fa2b1cb9c408352be46a33d0f411b175348f42382d170e17ec2b"
)
test(
id = 8,
EC = ECP_ShortW_Jac[Fp2[BLS12_377]],
Px0 = "10898a074b6931cc4ada152b64dd1c6b2bb47912e6502b9e88f638e489c144f8aa9b9f915bb428e082ec84676607f40",
Px1 = "18484823648fe1699468e2d265cd2f2e381a0e67f35f8d192259e2a14573692b4e1fbdeed639e9b6eb0731be820b166",
Py0 = "1840bc6fcb224efe00e32f827fa4f9694cd4186493089c66a936e912b50346b75542b6edbe51ba95c88d3b0fcac34ed",
Py1 = "18cb4201510933776a28ff1c44d356ceab065880f5242d8cc7cdf86874568df679b20f34b6a216d0047d2e1c1a16b85",
scalar = "bdb46c0eece9c8bac8a382def90b522b1d5197f09cf9f7cd98b710845ddb7b4",
Qx0 = "102779766b0068b176e118348e4163e89e3171e6eaad0e47f00cad626f8db025ec3ea990363813882c3dcfcbb642240",
Qx1 = "131eb563d2b0145eee52ee7586acd0254f103f02a20de3bf0202d1cffec2c3628501ec20f9f2ae5f461b59604afc04c",
Qy0 = "1463527db149d2c76f30c082786edb3fe1a9c7f4e04f9496e7adb40aab89340d9792f7d75cf3f5f81b0a28f09625175",
Qy1 = "f3190261db082c207ccd88a3ba762d2c0ba330548444afca03c8535ff11c7c90659a867dda3712a83f02ad184eb24a"
)
test(
id = 9,
EC = ECP_ShortW_Jac[Fp2[BLS12_377]],
Px0 = "13c3a392307124afb5f219ba0f8062fa9b75654d3fff12bc924592d284af550f039b6ac58880d2c6fea146b3982f03c",
Px1 = "188169bc937fcc20cc9c289adef30580188f64ecb126faadb5b888f31b813727ff7046d1a19b81abeea6609b8b208c6",
Py0 = "2f9bde8fdd43c5f4de30f335a480dca3bf0858464d8368984406f10ddc1ecabb15fcfd11cebd4fef426e7ca9411221",
Py1 = "25505653e199c354f2da8a13ed9de47f9b51a06ad2fa8826c4b8a9c61c6e75268807d7053e06bfc2899d1a3d6deeb4",
scalar = "91c6249ee16ef94d0b905575982419a7cf31d125775e7ede5c0ab4f86defd33",
Qx0 = "1967547943b197311a7d6723dcc37c3e649f173cec1c88ffca27df86518b3392ae0ee13dbca375c928b94d129226852",
Qx1 = "18b793916195f2d7d2a47c3f8243e5bdc239e78a3eb26971dac01b5f4ce14081a06529ab66cda8e8d5537808223fd00",
Qy0 = "a784902a14ad39adcfdc52bc30d8b8711b93dd869af2375a1f408ba8610b5c558bbebfe9f8f9875954780f4b4262c0",
Qy1 = "fb1c766957c89e4d67747549f650070983e6c19d0208b7e65478e4dd4f72fc54fca450d96329182e3f00d16ae0f3a"
)

View File

@ -14,7 +14,11 @@ import
../constantine/arithmetic,
../constantine/towers,
../constantine/io/[io_bigints, io_ec],
../constantine/elliptic/[ec_shortweierstrass_projective, ec_scalar_mul, ec_endomorphism_accel],
../constantine/elliptic/[
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian,
ec_scalar_mul,
ec_endomorphism_accel],
# Test utilities
./support/ec_reference_scalar_mult
@ -22,13 +26,13 @@ echo "\n------------------------------------------------------\n"
proc test(
id: int,
EC: typedesc[ECP_ShortW_Proj],
EC: typedesc[ECP_ShortW_Proj or ECP_ShortW_Jac],
Px, Py: string,
scalar: string,
Qx, Qy: string
) =
test "test " & $id:
test "test " & $id & " - " & $EC:
var P: EC
let pOK = P.fromHex(Px, Py)
doAssert pOK
@ -156,16 +160,118 @@ suite "Scalar Multiplication (cofactor cleared): BLS12_381 implementation vs Sag
Qy = "96d80593b42fe44e64793e490b1257af0aa26b36773aac93c3686fdb14975917cf60a1a19e32623218d0722dbb88a85"
)
# -----
test(
id = 0,
EC = ECP_ShortW_Jac[Fp[BLS12_381]],
Px = "f9679bb02ee7f352fff6a6467a5e563ec8dd38c86a48abd9e8f7f241f1cdd29d54bc3ddea3a33b62e0d7ce22f3d244a",
Py = "50189b992cf856846b30e52205ff9ef72dc081e9680726586231cbc29a81a162120082585f401e00382d5c86fb1083f",
scalar = "f7e60a832eb77ac47374bc93251360d6c81c21add62767ff816caf11a20d8db",
Qx = "c344f3bcc86df380186311fa502b7943a436a629380f8ee1960515522eedc58fe67ddd47615487668bcf12842c524d8",
Qy = "189e0c154f2631ad26e24ca73d84fb60a21d385fe205df04cf9f2f6fc0c3aa72afe9fbea71a930fa71d9bbfddb2fa571"
)
test(
id = 1,
EC = ECP_ShortW_Jac[Fp[BLS12_381]],
Px = "17d71835ff84f150fabf5c77ac90bf7f6249143abd1f5d8a46a76f243d424d82e1e258fc7983ba8af97a2462adebe090",
Py = "d3e108ee1332067cbe4f4193eae10381acb69f493b40e53d9dee59506b49c6564c9056494a7f987982eb4069512c1c6",
scalar = "5f10367bdae7aa872d90b5ac209321ce5a15181ce22848d032a8d452055cbfd0",
Qx = "21073bee733a07b15d83afcd4e6ee11b01e6137fd5ad4589c5045e12d79a9a9490a3ebc59f30633a60fc3635a3c1e51",
Qy = "eb7a97a9d3dfff1667b8fa559bdcdf37c7767e6afb8ca93ad9dd44feb93761e10aa2c4c1a79728a21cd4a6f705398b5"
)
test(
id = 2,
EC = ECP_ShortW_Jac[Fp[BLS12_381]],
Px = "f92c9572692e8f3d450483a7a9bb4694e3b54c9cd09441a4dd7f579b0a6984e47f8090c31c172b33d87f3de186d6b58",
Py = "286ede4cb2ae19ead4932d5550c5d3ec8ce3a3ada5e1ed6d202e93dd1b16d3513f0f9b62adc6323f18e272a426ee955",
scalar = "4c321d72220c098fc0fd52306de98f8be9446bf854cf1e4d8dbae62375d18faf",
Qx = "4bb385e937582ae32aa7ba89632fcef2eace3f7b57309d979cf35298a430de9ef4d9ac5ba2335c1a4b6e7e5c38d0036",
Qy = "1801154d3a7b0daea772345b7f72a4c88c9677743f267da63490dad4dece2ecc9ec02d4d4d063086ee5d356aa2db914e"
)
test(
id = 3,
EC = ECP_ShortW_Jac[Fp[BLS12_381]],
Px = "ec23ff3435b8ebd5e8e0a879d432e11eb974161664b1341fd28f1ffc4c228bf6ada2ae4a565f18c9b66f67a7573502d",
Py = "10c4b647be08db0b49b75320ae891f9f9c5d7bb7c798947e800d681d205d1b24b12e4dfa993d1bd16851b00356627cc1",
scalar = "1738857afb76c55f615c2a20b44ca90dcb3267d804ec23fddea431dbee4eb37f",
Qx = "dc7ae7801152918ee3c13590407b4242a80d0b855a0bf585d3dc30719601d2d5d9e01e99ae735003ecb7c20ef48265",
Qy = "142c01a6aa390426a4ce2f36df43f86442732c35d4e05e5b67f3623832944f0ea5a29138624cb939330652a3cfb282b5"
)
test(
id = 4,
EC = ECP_ShortW_Jac[Fp[BLS12_381]],
Px = "df127083c2a5ef2388b02af913c0e4002a52a82db9e5ecbf23ee4f557d3b61c91ebcfe9d4973070b46bc5ea6897bca1",
Py = "318960aeea262ec23ffdd42ec1ba72ae6fa2186a1e2a0fc2659073fb7b5adfb50d581a4d998a94d1accf78b1b3a0163",
scalar = "19c47811813444020c999a2b263940b5054cf45bb8ad8e086ff126bfcd5507e1",
Qx = "5f93c42fd76a29063efa2ee92607e0b3ae7edc4e419b3914661e5162d6beaeb96a34d2007ff817bc102651f61dca8d1",
Qy = "18dde8666bb1d0a379719d7d1b1512de809b70e49d9553303274ea872e56f7f39da551d6bcb7c57ae88ec7dc1fb354a4"
)
test(
id = 5,
EC = ECP_ShortW_Jac[Fp[BLS12_381]],
Px = "101123de23c0f240c583c2368c4118dc942db219c55f58cf54acd500c1fcfa06f651ad75319ebf840cbdb6bddea7fde4",
Py = "5268587d4b844b0708e0336d1bbf48da185aaf5b948eccc3b565d00a856dd55882b9bb31c52af0e275b168cb35eb7b0",
scalar = "43ffcda71e45a3e90b7502d92b30a0b06c54c95a91aa21e0438677b1c2714ecb",
Qx = "f9871b682c1c76c7f4f0a7ca57ad876c10dc108b65b76987264873278d9f54db95101c173aed06d07062efc7d47ca0c",
Qy = "20d9628d611e72a4251a1f2357d4f53e68e4915383b6a0d126273d216b1a8c5e2cb7b2688ad702ef1682f4c5228fcd9"
)
test(
id = 6,
EC = ECP_ShortW_Jac[Fp[BLS12_381]],
Px = "1457ba1bae6eb3afae3261941c65c93e3ae7d784907d15b8d559100da5e13fd29e4a4d6e3103b781a95237b7b2d80a8e",
Py = "6a869a47cb48d01e7d29660932afd7617720262b55de5f430b8aa3d74f9fd2b9d3a07ce192425da58014764fc9532cd",
scalar = "64ad0d6c36dba5368e71f0010aebf860288f54611e5aaf18082bae7a404ebfd8",
Qx = "93e540e26190e161038d985d40f2ab897cbc2346be7d8f2b201a689b59d4020a8740e252606f2f79ba0e121ccc9976d",
Qy = "10568d68f1b993aa1eded3869eda14e509f1cb4d8553bdf97feee175467cea4c0c1316fdb4e5a68440ad04b96b2d3bfc"
)
test(
id = 7,
EC = ECP_ShortW_Jac[Fp[BLS12_381]],
Px = "2615f843e8fe68d4c337bcf83b2cf13cbae638edd0740f1eac520dc2146afa3b8d36c540878c1d207ef913634b1e593",
Py = "1787d6eeeceb6e7793073f0bbe7bae522529c126b650c43d5d41e732c581a57df1bfb818061b7b4e6c9145da5df2c43e",
scalar = "b0ac3d0e685583075aa46c03a00859dfbec24ccb36e2cae3806d82275adcc03",
Qx = "d95ed29c2e15fd2205d83a71478341d6022deb93af4d49f704437678a72ce141d2f6043aa0e34e26f60d17e16b97053",
Qy = "b37cbded112c84116b74ff311b10d148f3e203cb88d4a011b096c74cd2bfdb27255727de4aa8299ae10b32d661d48a7"
)
test(
id = 8,
EC = ECP_ShortW_Jac[Fp[BLS12_381]],
Px = "10bc0c4e1ed87246a9d4d7d38546369f275a245f6e1d3b882e8c9a7f05bc6ee8ff97a96a54084c2bef15ed8bfefb1465",
Py = "1782377e5f588576b5ab42fea224e88873dda957202f0c6d72ce8728c2d58dc654be77226fbda385d5f269354e4a176a",
scalar = "23941bb3c3659423d6fdafb7cff52e0e02de0ac91e64c537c6203d64905b63d0",
Qx = "83f1e7e8bd963c1ccd837dae7bc9336531aaf0aee717537a9a7e2712e220f74cdb73a99f331c0eb6b377be3dafc211f",
Qy = "cd87773d072b1305dfc85c2983aecae2ab316e5e8f31306c32d58d6ce2e431b12685d18c58b6a35ad2113c5b689eeb"
)
test(
id = 9,
EC = ECP_ShortW_Jac[Fp[BLS12_381]],
Px = "be4f9f721d98a761a5562bd80ea06f369e9cbb7d33bbb2f0191d4b77d0fd2a10c4083b54157b525f36c522ca3a6ca09",
Py = "166c315ecdd20acb3c5efcc7e038b17d0b37a06ffbf77873f15fc0cd091a1e4102a8b8bf5507919453759e744391b04d",
scalar = "4203156dcf70582ea8cbd0388104f47fd5a18ae336b2fed8458e1e4e74d7baf5",
Qx = "c72bc7087cd22993b7f6d2e49026abfde678a384073ed373b95df722b1ab658eb5ae42211e5528af606e38b59511bc6",
Qy = "96d80593b42fe44e64793e490b1257af0aa26b36773aac93c3686fdb14975917cf60a1a19e32623218d0722dbb88a85"
)
proc test(
id: int,
EC: typedesc[ECP_ShortW_Proj],
EC: typedesc[ECP_ShortW_Proj or ECP_ShortW_Jac],
Px0, Px1, Py0, Py1: string,
scalar: string,
Qx0, Qx1, Qy0, Qy1: string
) =
test "test " & $id:
test "test " & $id & " - " & $EC:
var P: EC
let pOK = P.fromHex(Px0, Px1, Py0, Py1)
doAssert pOK
@ -329,3 +435,145 @@ suite "Scalar Multiplication G2: BLS12-381 implementation vs SageMath" & " [" &
Qy0 = "1357e8db4a105bf81a94e9b9130a892b1ec78d564f77b2717451cce777c16a409cd19f450247c75882f1b84678d7c46d",
Qy1 = "14dd91161426cd5d831914706ee9f427512a789f4953f82538f3fb17553840eae31c992de2ed91a6695d291b5ef4c204"
)
# -----
test(
id = 0,
EC = ECP_ShortW_Jac[Fp2[BLS12_381]],
Px0 = "10fbddd49246ac4b0faa489e3474507ebc96a5da194b2f7a706fad6bf8435021e1598700088abfe0ae7343296c1b7f52",
Px1 = "324102fa5bd71d9048c3c6a6c62d1f35195d7067bf00dc5eaedd14eecc688383446aba4e8fda059d3f619f00be7890",
Py0 = "f3e974aafa7a3fb3a1209f3af4492c9d9c52f1ae738e1e08309dd0f438f131f8ddd8b934eb8ff2cb078b8c524c11fab",
Py1 = "15e75704edffe7b975cf1d3f27f1dceb89d02e5660650195e0288e5d26c5e9087c241d1bd3263c991d10e2695d1611f1",
scalar = "1f7bef2a74f3bf8ac0225a9edfa514bb5666b15e7be3e929059f2ef75f0035a6",
Qx0 = "1328e4ac12458f9e0c22e925d2fc5593eaf0c126154b484de986895030f830262f54493edcc26aa39c5ab8e714b784b3",
Qx1 = "14d375c704f9187984fe2d64d5517ce7c6eb09981cee68cd48370df21d7f4d0b19431347be3b9eae9d46605cb229e293",
Qy0 = "1580cb4fceea4e71e222945825d4352c97a02d3118ffbd0e006e467b1ff6d4207acd2bb58a197894e9870cbd1bfb369c",
Qy1 = "5df16d4223c040dffcd1912359cfae1f3a99e7f519b2aedaaeb6d77115c63acf309f9effc69d4d9a0d7de420dbf9f1a"
)
test(
id = 1,
EC = ECP_ShortW_Jac[Fp2[BLS12_381]],
Px0 = "4b472ab5d0995a22c95f0805eb459b147d2033b8c13c1c07c857a97e66952d4df3e3b5f346997cc7bd19886492fae83",
Px1 = "12228345592511c7327176258097c70dffad1ff53b37163cbd4747d0085ed0bcfe90b9150d2f7e49580a42110b1d9c6b",
Py0 = "19220ed4e423d3274a8e9a58624b8762d7831d6f65fcaf6718b933bf77a0c41d3bb713a2224dbc448cfc735101a5bb1e",
Py1 = "1d4c7565e4831130ae0ddd95aaad4033e57daab2518b3f0d934c7abc7db8614adbf39beaef5ebb85d34f5add8a6d341",
scalar = "b500f1fa8ffa8d1c0aa7d65054a9aaa0d9ed2fff83b40516def10b03cc80026",
Qx0 = "aaf3fc4e3c92df5b76863d64d19d26213757173c1a8ef4beddbee7c22f5a6a00418527f83c9ab5b17797cd2212d3d73",
Qx1 = "1643ce8e3a0f0997e949c04cb28aa77b7184033dd0056caee2488311e0a3567a0cd9d051ee531d6a83be8ac516c3f075",
Qy0 = "12923eb157d8ee0a940e100408250beded20e4185cbec484431f705ab605c452122c66d6f08e1b06305677dc872a024f",
Qy1 = "460b65406a6e3935dfd75977b12c02971d2673b9c23b032494e6684e08727f35da0407be6708e98cd309ff0c09be00d"
)
test(
id = 2,
EC = ECP_ShortW_Jac[Fp2[BLS12_381]],
Px0 = "11c9f03cd130f7b4d6675b902d9b4dddfa41577b7673c31a508760675ca083abedfe3f6c1c69eb46737d4877adb527c6",
Px1 = "c64be8d22d478378784c4f38e386635a8ab606d2b35101ebecfe97b3bb5132d26e9a7ea9690d07a78a22f458045a8c5",
Py0 = "6253c05b48fde95024644efd87cdf0cf15414c36c35625e383ea7b5ab839eaa783563918cd9e5e391ef1512a6ac28e0",
Py1 = "2d214172d2a0326ed45b60945c424ac30f416fa8c6e11f243034a9de26f4aaa69c0d4cc8405227f26c6ee4085ea5bd4",
scalar = "3638a1f09b542c9c14706bddf9bd411747489f3d398a5c286d28f3a950e33406",
Qx0 = "a6e22837968f191d848297f60b511acf4cc375e53161e7869b8d98455375d8ee69367513b3439b6c4ee66f9232badbb",
Qx1 = "10f95cc0c70943519c30c04a8625bb56c1656da634018b1e6e35786b610785f41978983c61e78d4be003074d7fd76660",
Qy0 = "bae732b1dd39cb84c7e0649ed641f9d275bfc45721e3ac35d6cd35faa356235ce0b69fa0f2882d6d2762ed8846368d6",
Qy1 = "bcab3bee59706e0f8c381d2a15a55ce6b2c38d1639b43852af2a62f1366d1cdb8433240cbb237750f2f3e0435b23141"
)
test(
id = 3,
EC = ECP_ShortW_Jac[Fp2[BLS12_381]],
Px0 = "5adc112fb04bf4ca642d5a7d7343ccd6b93546442d2fff5b9d32c15e456d54884cba49dd7f94ce4ddaad4018e55d0f2",
Px1 = "5d1c5bbf5d7a833dc76ba206bfa99c281fc37941be050e18f8c6d267b2376b3634d8ad6eb951e52a6d096315abd17d6",
Py0 = "15a959e54981fab9ac3c6f5bfd6fb60a50a916bd43d96a09922a54309b84812736581bfa728670cba864b08b9e391bb9",
Py1 = "f5d6d74f1dd3d9c07451340b8f6990fe93a28fe5e176564eb920bf17eb02df8b6f1e626eda5542ff415f89d51943001",
scalar = "6448f296d9b1a8d81319a0b789df04c587c6165776ccf39f50a354204aabe0da",
Qx0 = "689e9532c287233d12c3d7196361a06479ecb762a8542f6ba4003a5863d5731f3a0cd3fe4e1405aa3c6f9bd87c08b26",
Qx1 = "b74b46e87a05b7413282d63d63a2b1eeb23e8c482fa8097623888d4be2b90c7cdb49fcb93c74f2b98da15aa9382e285",
Qy0 = "44250df4c1e38bfd7fef6c61649afe7ab5d5252b98589d71f1a64efac5ae8ecf0ccafa173acaafc30a0b2a1616b08e4",
Qy1 = "173b324bb2e0596d0ab560c2a447a1867fea87c5712bd06f2503385b0e145509036c119440973396fc263a02838c8433"
)
test(
id = 4,
EC = ECP_ShortW_Jac[Fp2[BLS12_381]],
Px0 = "99f8b62e82892d323847f64ab2b422478d207b780fbb097cdca6a1a89e70ff09213dee8534eaf63dac9f7f7feff2548",
Px1 = "12e7b53d802fa9cd897b5470614d57b1620bfe53f36158466f83e7cc6a6cccb1ac7557a8d5a2208c7c1366835c2cba59",
Py0 = "115d6b7a8bc5628690ec750207b3252d4121c20c2106d0277cd41dee7b1d4ed1ff856883719bccb545054b9a745a53e2",
Py1 = "4b55174d273b358a72687d52956af3e94d97db8d2cc508b2a4ec5b0c0b4073b8fcc52eadaea35e3eae9a441b3f86cbc",
scalar = "150caebc321c53c0658c5cecb45e564620b57bfbad0f5d5a277be71a184937b7",
Qx0 = "3f474d7fa1ff31949c7b61f1ff71a7ccd282201ef88ef12fcd1fd3fef6a3ca18d8bb31fa7e9f4abc713f37e02abef3",
Qx1 = "cb94daed6079cbe5a628ae4c27e8ad31a17f14e68050e8ce1b03d5a3c0e6a6cc5a34b3115034349b2ebe8de6a2c441e",
Qy0 = "15b09aac63ac527ad719ee2bcebda6bb646044d9060c4f72280d41186798912b6e29b2f7782744b8cdce927a9c1b9340",
Qy1 = "5204820d6336aade860fb1cb983bcc66e10cfb352ea645b4cdf74e643e9fdf545609bd7181a67daac891f551a6ce566"
)
test(
id = 5,
EC = ECP_ShortW_Jac[Fp2[BLS12_381]],
Px0 = "7f56aa6111f341d6381090f058835b3d60200032b382108194188c40afe4225eb6fecaba734084283771923e004b5ca",
Px1 = "18abca4d9eca6d3ef3c720ca6b27f824fdd12dcac72c167f0212f707fa22752f291c9c20a4b92417d05c64207b8e6da6",
Py0 = "10e08fc323d2ef92c5fd9a0ba38e32e16068ac5a4a0f95b0390c2e8ad6caa446adebe16bbf628a0c2de007bfa1218317",
Py1 = "6394379cc76d50b41865b619007de5a7cda3bb7ae6fc696bf2f83e2de562039dab890a9e2b4d61045bac606f224ba42",
scalar = "138ecc47a9d5b6cf2a052731b8f016734614949862a9f2be703935a5e0cd43bd",
Qx0 = "19ec61da69ffdbf79411f041276d4e9fe02df31caa79406135a7522a12965364bb3549b7310393208082465feca7c9eb",
Qx1 = "457ddcc53f5338d34713a91ca4298896bfa7ede3b939cd1c8b320a4c9ba4c1038ac09740e5b428f5c15bdf18ca6af0b",
Qy0 = "9e334e01a81dc6da2004d2f13eec7c15ba0ab8fb8a9628ce24a0de073b251f955ee758f5b0a298c4fadd641610c7fe0",
Qy1 = "935bf9c37ed2ce17b9e5f8014816d8a1a3d8debfc72e39ea9121018f3a990561cfbc64c25621d16a921f458d7f40344"
)
test(
id = 6,
EC = ECP_ShortW_Jac[Fp2[BLS12_381]],
Px0 = "a8c5649d2df1bae84fd9e8bfcde5113937b3acea22d67ddfedaf1fb8de8c1ef4c70591cf505c24c31e54020c2c510c3",
Px1 = "a0553f98229a6a067489c3ee204161c11e96f421b3e9c145dc3865b03e9d4ff6cab14c5b5308ecd31173f954463690c",
Py0 = "b29d8dfe18dc41b4826c3a102c1bf8f306cb42433cc36ee38080f47a324c02a678f9daed0a2bc577c18b9865de029f0",
Py1 = "558cdabf11e37c5c5e8abd668bbdd71bb3f07f320948ccaac8a207359fffe38424bfd9b1ef1d24b28b2fbb9f76faff1",
scalar = "5668a2332db27199dcfb7cbdfca6317c2ff128db26d7df68483e0a095ec8e88f",
Qx0 = "490e99b9a27cb49b9446a7bedb8c22ef802cfdc3609cbecd8de4e227fdb72aeafb27c53d74361008ce9ea806e25dc85",
Qx1 = "1624f7ed9ca1fcfda7651608be2acb1d76cb37ab989c1aecf06a6401ee66afdddf283039496c2320dca4d720e8b8a337",
Qy0 = "c6fef37a864fa1602824a2128d4a62e3221413e1ded862f11347576f43c27d69b1957385ad6ba7a9168c05e6fc2ab85",
Qy1 = "11d4a696f8e366929fe0b7eae94702a89aef43725218f95e0bfe7d7abd726e884604838e4d7d670c9579431f9d8012e0"
)
test(
id = 7,
EC = ECP_ShortW_Jac[Fp2[BLS12_381]],
Px0 = "eb79d9e425feb105ec09ce60949721b12dac5e6721c8a6b505aa2d83270d2a3e6c6bcce16a1b510f6822504c5e86416",
Px1 = "9f5d2dc403a2e96c3f59c7bb98a36cc8be68500510fd88b09f55938efd192d9653f4bcfd1451518c535e9d1996a924",
Py0 = "114825899129828ee0b946811ff98a79af1b53c4511bc45a8e41a07a7d9600c824ed7c5cd608781d0a98a13e69b0c002",
Py1 = "57600cfce779277faf31d1b18a39c752c179a76b301cbdc317263c7e8770df0d5896c9dec84958bf558c16b5ec5869c",
scalar = "45b4bca2f783bba42b2d41a8d00f4c5f18a78738a5678fc3707523e7c62dafcb",
Qx0 = "71bee2c58caace914434607aff9c1730af2da8bd78d1a44215d9c7cc422623e9b65ba1fc7207de9d0af96f8211eda2b",
Qx1 = "80ea7a46f9352599f67bbbed1253b142422cb79af32b1a544e77ff02c25057396569182341e5492c4a520a756568a41",
Qy0 = "73470439d1202c87e54d9de94121f5e36371fe527eca699f48caba867111707a250b2b0357e79a8263babb907c9f43a",
Qy1 = "cf2f2cca752462c5fc2827b7871d517e50d7ecd819e0b9419f9b1e357874acca15c8f0a1f611aa243b9d21ce1962d3a"
)
test(
id = 8,
EC = ECP_ShortW_Jac[Fp2[BLS12_381]],
Px0 = "17ce8a849a475599245ad6b84cf5284cd15d6346ae52a833954ec50d5cf7f0be1cd8473fdc9dfd500d7f1d80bf6fa6ca",
Px1 = "15d8128bc60c8e83846bf6748982a7188df6393a9379b2959fa7e1cb72f1c1da066fe3a6d927f97ecec3725fac65eb10",
Py0 = "a05421595b36750e134b91500962201e9f57ac068732b9fb34ec50ff22f274d395d34d133e131e6dc7bc42d66149767",
Py1 = "178cb2541ce0c60b8860d59762daa6a5b55a0ca034aa18b1fcc6deb23aaa093fb2a6129db0d58de044c4bbb23f1fa298",
scalar = "6083671fcc66dc084ad73eba100830555fcfcc5eccaa6acb27cda0d3fa8d6f64",
Qx0 = "175a067a5cca1e18c2c60c1ed84a2d0fdad20ad8e2b9b67a13d8a173d6c097bd2bb8fa6d83ff5ab3668d56d39f34cbe0",
Qx1 = "14bdf8d62a088a6a71e5ea236bd3caa07934da726fc1f0b7ae462272c0778615734fac562a0293ae5da759dcfc78480c",
Qy0 = "59ead353a2a4189dd9dc0d93ac86d0f3f8fd60bf3db10fd77e4295b1dfaeccb28aa481b1efce7198093a7f2e8ba3617",
Qy1 = "a4661ce0260e251df9d2b01b5af29262e019b8ea12b3a0a2c4c125c09cadd906dcd8a25b7876e76892acfd74dfab8c5"
)
test(
id = 9,
EC = ECP_ShortW_Jac[Fp2[BLS12_381]],
Px0 = "13eb9e9906446be49345c08de406cd104d6bb9901ee12af0b80a8351027152d6f6d158d5a906e4a58c5602e97347cfd5",
Px1 = "1218df3f2a9cd7685325a4a7bb6a3636a458a52ea7f1e1d73c2429acb74a2a9beb838c109541120b095118c90868eb0f",
Py0 = "3ac16edac6898f11ff8ddb48fad6f59f4842cd427d72fa964171801be172b8ecd2fdffb4882d4aa6f1e730f6e53f8c5",
Py1 = "b2d251295859b1be1854b1db06eae2ff8e3879d8ba5d9f86f4bb805c65696b48d0771cf10150983e322bdf9eb659af1",
scalar = "644dc62869683f0c93f38eaef2ba6912569dc91ec2806e46b4a3dd6a4421dad1",
Qx0 = "1888f703e7525e4ac29788eb6e3afde14e4c8b36f74a3058ab7e991630cdb8332fb164766db6d14186ac7fa2e593f513",
Qx1 = "1496076ec35db3760a3cfe22a1759b01ac89b7ae21ccb9c4d7553a7881f4a610ef88a56b2e5a027ab49507fd710dd9ea",
Qy0 = "1357e8db4a105bf81a94e9b9130a892b1ec78d564f77b2717451cce777c16a409cd19f450247c75882f1b84678d7c46d",
Qy1 = "14dd91161426cd5d831914706ee9f427512a789f4953f82538f3fb17553840eae31c992de2ed91a6695d291b5ef4c204"
)

View File

@ -8,13 +8,17 @@
import
# Standard library
std/unittest,
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/towers,
../constantine/io/[io_bigints, io_ec],
../constantine/elliptic/[ec_shortweierstrass_projective, ec_scalar_mul, ec_endomorphism_accel],
../constantine/elliptic/[
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian,
ec_scalar_mul,
ec_endomorphism_accel],
# Test utilities
./support/ec_reference_scalar_mult
@ -22,13 +26,13 @@ echo "\n------------------------------------------------------\n"
proc test(
id: int,
EC: typedesc[ECP_ShortW_Proj],
EC: typedesc[ECP_ShortW_Proj or ECP_ShortW_Jac],
Px, Py: string,
scalar: string,
Qx, Qy: string
) =
test "test " & $id:
test "test " & $id & " - " & $EC:
var P: EC
let pOK = P.fromHex(Px, Py)
doAssert pOK
@ -156,15 +160,118 @@ suite "Scalar Multiplication G1: BN254 implementation vs SageMath" & " [" & $Wor
Qy = "bafa230a0f5cc2fa3cf07fa46312cb724fc944b097890fa60f2cf42a1be7963"
)
# --------------------------------------------------------------------------
test(
id = 0,
EC = ECP_ShortW_Jac[Fp[BN254_Snarks]],
Px = "22d3af0f3ee310df7fc1a2a204369ac13eb4a48d969a27fcd2861506b2dc0cd7",
Py = "1c994169687886ccd28dd587c29c307fb3cab55d796d73a5be0bbf9aab69912e",
scalar = "e08a292f940cfb361cc82bc24ca564f51453708c9745a9cf8707b11c84bc448",
Qx = "267c05cd49d681c5857124876748365313b9c285e783206f48513ce06d3df931",
Qy = "2fa00719ce37465dbe7037f723ed5df08c76b9a27a4dd80d86c0ee5157349b96"
)
test(
id = 1,
EC = ECP_ShortW_Jac[Fp[BN254_Snarks]],
Px = "2724750abe620fce759b6f18729e40f891a514160d477811a44b222372cc4ea3",
Py = "105cdcbe363921790a56bf2696e73642447c60b814827ca4dba86c814912c98a",
scalar = "2f5c2960850eabadab1e5595ff0bf841206885653e7f2024248b281a86744790",
Qx = "57d2dcbc665fb93fd5119bb982c29700d025423d60a42b5fe17210fd5a868fd",
Qy = "2abad564ff78fbc266dfb77bdd110b22271136b33ce5049fb3ca05107787abc"
)
test(
id = 2,
EC = ECP_ShortW_Jac[Fp[BN254_Snarks]],
Px = "39bc19c41835082f86ca046b71875b051575072e4d6a4aeedac31eee34b07df",
Py = "1fdbf42fc20421e1e775fd93ed1888d614f7e39067e7443f21b6a4817481c346",
scalar = "29e140c33f706c0111443699b0b8396d8ead339a3d6f3c212b08749cf2a16f6b",
Qx = "83895d1c7a2b15a5dfe9371983196591415182978e8ff0e83262e32d768c712",
Qy = "2ed8b88e1cd08814ce1d1929d0e4bba6fb5897f915b3525cf12349256da95499"
)
test(
id = 3,
EC = ECP_ShortW_Jac[Fp[BN254_Snarks]],
Px = "157a3e1ff9dabccced9746e19855a9438098be6d734f07d1c069aa1bd05b8d87",
Py = "1c96bf3e48bc1a6635d93d4f1302a0eba39bd907c5d861f2a9d0c714ee60f04d",
scalar = "29b05bd55963e262e0fa458c76297fb5be3ec1421fdb1354789f68fdce81dc2c",
Qx = "196aeca74447934eeaba0f2263177fcb7eb239985814f8ef2d7bf08677108c9",
Qy = "1f5aa4c7df4a9855113c63d8fd55c512c7e919b8ae0352e280bdb1009299c3b2"
)
test(
id = 4,
EC = ECP_ShortW_Jac[Fp[BN254_Snarks]],
Px = "2f260967d4cd5d15f98c0a0a9d5abaae0c70d3b8d83e1e884586cd6ece395fe7",
Py = "2a102c7aebdfaa999d5a99984148ada142f72f5d4158c10368a2e13dded886f6",
scalar = "1796de74c1edac90d102e7c33f3fad94304eaff4a67a018cae678774d377f6cd",
Qx = "28c73e276807863ecf4ae60b1353790f10f176ca8c55b3db774e33c569ef39d5",
Qy = "c386e24828cead255ec7657698559b23a26fc9bd5db70a1fe20b48ecfbd6db9"
)
test(
id = 5,
EC = ECP_ShortW_Jac[Fp[BN254_Snarks]],
Px = "1b4ccef57f4411360a02b8228e4251896c9492ff93a69ba3720da0cd46a04e83",
Py = "1fabcb215bd7c06ead2e6b0167497efc2cdd3dbacf69bcb0244142fd63c1e405",
scalar = "116741cd19dac61c5e77877fc6fef40f363b164b501dfbdbc09e17ea51d6beb0",
Qx = "192ca2e120b0f5296baf7cc47bfebbbc74748c8847bbdbe485bcb796de2622aa",
Qy = "8bc6b1aa4532c727be8fd21a8176d55bc721c727af327f601f7a8dff655b0b9"
)
test(
id = 6,
EC = ECP_ShortW_Jac[Fp[BN254_Snarks]],
Px = "2807c88d6759280d6bd83a54d349a533d1a66dc32f72cab8114ab707f10e829b",
Py = "dbf0d486aeed3d303880f324faa2605aa0219e35661bc88150470c7df1c0b61",
scalar = "2a5976268563870739ced3e6efd8cf53887e8e4426803377095708509dd156ca",
Qx = "2841f67de361436f64e582a134fe36ab7196334c758a07e732e1cf1ccb35a476",
Qy = "21fb9b8311e53832044be5ff024f737aee474bc504c7c158fe760cc999da8612"
)
test(
id = 7,
EC = ECP_ShortW_Jac[Fp[BN254_Snarks]],
Px = "2754a174a33a55f2a31573767e9bf5381b47dca1cbebc8b68dd4df58b3f1cc2",
Py = "f222f59c8893ad87c581dacb3f8b6e7c20e7a13bc5fb6e24262a3436d663b1",
scalar = "25d596bf6caf4565fbfd22d81f9cef40c8f89b1e5939f20caa1b28056e0e4f58",
Qx = "2b48dd3ace8e403c2905f00cdf13814f0dbecb0c0465e6455fe390cc9730f5a",
Qy = "fe65f0cd4ae0d2e459daa4163f32deed1250b5c384eb5aeb933162a41793d25"
)
test(
id = 8,
EC = ECP_ShortW_Jac[Fp[BN254_Snarks]],
Px = "273bf6c679d8e880034590d16c007bbabc6c65ed870a263b5d1ce7375c18fd7",
Py = "2904086cb9e33657999229b082558a74c19b2b619a0499afb2e21d804d8598ee",
scalar = "67a499a389129f3902ba6140660c431a56811b53de01d043e924711bd341e53",
Qx = "1d827e4569f17f068457ffc52f1c6ed7e2ec89b8b520efae48eff41827f79128",
Qy = "be8c488bb9587bcb0faba916277974afe12511e54fbd749e27d3d7efd998713"
)
test(
id = 9,
EC = ECP_ShortW_Jac[Fp[BN254_Snarks]],
Px = "ec892c09a5f1c68c1bfec7780a1ebd279739383f2698eeefbba745b3e717fd5",
Py = "23d273a1b9750fe1d4ebd4b7c25f4a8d7d94f6662c436305cca8ff2cdbd3f736",
scalar = "d2f09ceaa2638b7ac3d7d4aa9eff7a12e93dc85db0f9676e5f19fb86d6273e9",
Qx = "305d7692b141962a4a92038adfacc0d2691e5589ed097a1c661cc48c84e2b64e",
Qy = "bafa230a0f5cc2fa3cf07fa46312cb724fc944b097890fa60f2cf42a1be7963"
)
proc test(
id: int,
EC: typedesc[ECP_ShortW_Proj],
EC: typedesc[ECP_ShortW_Proj or ECP_ShortW_Jac],
Px0, Px1, Py0, Py1: string,
scalar: string,
Qx0, Qx1, Qy0, Qy1: string
) =
test "test " & $id:
test "test " & $id & " - " & $EC:
var P: EC
let pOK = P.fromHex(Px0, Px1, Py0, Py1)
doAssert pOK
@ -173,8 +280,6 @@ proc test(
let qOK = Q.fromHex(Qx0, Qx1, Qy0, Qy1)
let exponent = BigInt[EC.F.C.getCurveOrderBitwidth()].fromHex(scalar)
var exponentCanonical: array[(exponent.bits+7) div 8, byte]
exponentCanonical.exportRawUint(exponent, bigEndian)
var
impl = P
@ -330,3 +435,145 @@ suite "Scalar Multiplication G2: BN254 implementation vs SageMath" & " [" & $Wor
Qy0 = "2a8ecb09a01cd2f89b316e7569331e9da3bfbd8a40114913b3e5477442c0e4ef",
Qy1 = "282b14bc00df2dd1733e3187a9845ef3a123c17ce4f6154e5cad26c3b48d1b98"
)
# --------------------------------------------------------------------------
test(
id = 0,
EC = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Px0 = "1dcee2242ae85da43d02d38032b85836660f9a0a8777ab66c84ffbbde3ac3b25",
Px1 = "1e2eb4c305e3b6c36a4081888b7a953eb44804b8b5120306331f8c89a3bb950",
Py0 = "1db75f495edd522cae161ceeb86ca466ca2efd80ef979028d7aa39679de675fd",
Py1 = "b1b6edeb6a7689595098a58a916657dcc09f53f5fc1a1a64b34a2b80447692e",
scalar = "3075e23caee5579e5c96f1ca7b206862c2cf3ce21d79182d58b140074b7bd34",
Qx0 = "8d63bb4368f94f1629f33ef0c970b3a6fcec6979e423f54ce657f0493c08fde",
Qx1 = "29d1af77bb890dcb27e685198f23dffd5ae5733bd6dd55757dcb44ce8c396742",
Qy0 = "13c24efab7e517c2337ba9cbb8cfb2166666a44550fc4d314f4c81a4812fb8a",
Qy1 = "c3ad1f7a175fa21e1d18595f8fc793688e1a33feda902805a52569ea7a787bb"
)
test(
id = 1,
EC = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Px0 = "5ed8c937273562944e0f1ebfb40e6511202188c1cabf588ed38735016d37b32",
Px1 = "23f75e8322c4b540cd5b8fd144a89ab5206a040f498b7b59385770bc841cf012",
Py0 = "2150beef17f5c22a65a4129390f47eece8f0c7d0c516790ea2632e7fd594ed8",
Py1 = "78281fb396e2b923453fae943af96b57e8b283fc40b0be4be3a1750d0daf121",
scalar = "1eac341ad699cba0cb13ae35b8215bfe0f34e931f8e51e33bf90d9849767bb",
Qx0 = "1bb6e8c1be4d9da9ef294ab066c82bb6dd805efa0c73f289e25f5cc6fc4f12e4",
Qx1 = "8ca44ff91e6484ecadc2a866ec64031e71c4a9d7a902f4280bef3db4dbf1bc9",
Qy0 = "39d151a22c49d4c71c8258e9664ead46ddccd49c596056509d9f9e6055def62",
Qy1 = "b37a08b453b96880f435d9fb2555960571a76e72a9d0d0ec622b055b7c97cdb"
)
test(
id = 2,
EC = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Px0 = "2ac4b3d0a70d6686c63d9d63cce1370eafd4dc67f616c13582c6c64f6670513e",
Px1 = "f1daeb6a2581ba6c8027a645ab5c10e303db4aee85c70c8fe11f4c1adcc7029",
Py0 = "25807ff21967759cab64844741d006e2aa0221d9836613b1239da1a167d15131",
Py1 = "148dae725e508dbb43616972e2945f4868b2a193d828ed2efcf9c8a37b6b83f5",
scalar = "b29535765163b5d5f2d01c8fcde010d11f3f0f250a2cc84b8bc13dd9083356c",
Qx0 = "5f4b3a8a5fe74bf3f2ddc0bc2024f18c7958b2846dab1c602b8256a6035361a",
Qx1 = "ba3dad609b1ba8c78cbbfb7fae2d2f9398ef02265e3b4c0f3c8c18d8d0e59d6",
Qy0 = "2c226aee4621895d63df069c4b6951e2201ee1508d5d54e6ee860533b73b534a",
Qy1 = "2aa5384592339bff0a6e4664c931c0ec9f5a3d2fb2fff87a52245c0d95d3d130"
)
test(
id = 3,
EC = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Px0 = "2a028c1328bb0abf252edfbf7133b84eef2a5f20163fe61685b4b54229ca585d",
Px1 = "8f80ad79e8e7e79bbdc645d9f5b339c52dd99a901b90de2494492656f11a9d5",
Py0 = "1f04320578e31ffa2e2b59ad8fcb1aba622b5f307ac540cf2ccdab07dec56503",
Py1 = "2973900c0fdf651b64f5b1a990baec7c582e0743d501bdb991374776d6c73b28",
scalar = "2c02275a71bb41c911faf48cab4f7ac7fc6672a5c15586185c8cff3203181da0",
Qx0 = "2f39a0772a0bd75db3e6ec0745b18824118e534fdefec811d0a4ca2ca3ce7606",
Qx1 = "23e1601a4338502dbc619a8bde251114272ca87662a851a56035c81d46877d81",
Qy0 = "1f0ee85e7c590124f89319f2450f7b8421d9f6d6414fd3b5cc18d781b69b30c9",
Qy1 = "29e4ff75afecaf732419409a5e0d8e94df6acec29fb5b298c7aad5ceef63e5f9"
)
test(
id = 4,
EC = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Px0 = "1132e63c444e1abce6fc4c39bdf5be5caad586837cbf5ca9d3891482bdefe77",
Px1 = "22b71f598dab789f055fc9669ddf66f0d75f581af0e9e8863d7f95a51ef34862",
Py0 = "58e39050f64c9948d7238b99ecaee947cb934688a6e9f483c5c36b6e07aa31b",
Py1 = "2e64b920f498e12992f2a4ae3f9ced43f3f64705c9008169f3b930a760d055fb",
scalar = "24c5b2ce21615dca82231f5fb0fc8d05aa07c6df4bb5aa7c2381ac7b61a6290c",
Qx0 = "25a0637163a40813529e8a22a3e8be6db96f6dc1cdb8e1844729cad6be11668e",
Qx1 = "16de42461c4db7f9f72eb28bb16da850a42fc153dec64baf021f67f5564f36d8",
Qy0 = "27f2d743d3ce0c1f92c51110a6b9ca93a95693161f1d1cd85a0cf5a2492b4901",
Qy1 = "2c5a8df4fe93e31e374595c0605b1a8b93bb429232cf40f45c847739790c191e"
)
test(
id = 5,
EC = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Px0 = "6a20c456e80e2bfe37d8631d41ffed31cba5d1c411e816d64014d0088d16554",
Px1 = "9d1555c77222abd79e17e2806386c53aba9609375276e817f52f03dc3f75676",
Py0 = "127e76f384726e56dfaa46e6fde6dc644f5fd494d056191059e2bebc525ce835",
Py1 = "2d80f2570da62adc61d794ac17c251f9f9f3de2b45f39c8ede5a9e215e60363",
scalar = "263e44e282fe22216cc054a39e40d4e38e71780bdc84563c340bdaaf4562534b",
Qx0 = "6d7e15b98352e445d1bdacb48826e5a7e8cf854fb9bc18839b30a164a2a9c53",
Qx1 = "12aa3294f6a9bb17f91d5875a5a1aa559c29b06134c6d165d83c8e9e02947568",
Qy0 = "271b8b552e52bdd310c46e07327a18861c91a739da178be909f0a4fe53ae0d05",
Qy1 = "1f4f200de96541e826f0bd536b1401e05e2a7c5a96c567b6dff21a21119bbf7"
)
test(
id = 6,
EC = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Px0 = "4c591d080257375d6189340185c6fe4c1fa796722d07e1bec0b17080b6b1154",
Px1 = "241e2f2eb2a58afc2b5410d4ccbf75b53744ca1ac0bb28d7c60449f8d06204a4",
Py0 = "eaddea52f2e884a5e2635965ca4146b12127fe8a8883e07def8e8720f410781",
Py1 = "cc60dec6ad90e38c851924cf39ddd11b70eeb3fac95731eafd984e9aba2cae",
scalar = "1471f378000d557f0c33c1f8c8313edd53422479440cbd0fdc4cc55f1163deec",
Qx0 = "2a86b4867d7f63afdc09048210a3ef6d363c7896ccc1bb248f3aad4174e1f8fa",
Qx1 = "84c200018461c84ef9ce6de2c691b95cc2c41edc87107331f107ac49de76656",
Qy0 = "2ea1b6d71adb183d9a8dd319a21a679cb0b4e06bc96583d3a786f82b88b5e3ba",
Qy1 = "834e2ff738dcb5e8db7e4dae9336dede51524313b476019ea29ebadbb4ba12d"
)
test(
id = 7,
EC = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Px0 = "115e772198e3f0003e31c0a1c48b6ac870d96020a4d634b7f14c15422d001cfe",
Px1 = "1913447ff41836e0b6a3b01be670a2457e6119e02ae35903fb71be4369e269f7",
Py0 = "14cb779c640aad2731b93b07c623c621a5585d0374f0394e5332f20ac28ca49d",
Py1 = "13a4c4b67f5976431158be8137b5017127fdbc312dc49825dae218a9a7878817",
scalar = "411315458c0c0cb27a058faf15dcbf2e467128f9c958d92de37902e1912f81",
Qx0 = "243a8808a891428d01ef28a77d0766488a98272a5dd394b2992599ff522f264",
Qx1 = "1baebf873402812e4345a8b1783fd25272c64d6194bd9f50b32b8e67ee737dc7",
Qy0 = "1f1001ba8b8b27159568f72e80662e352adfc00c9341d8b4fb8ef6f75ff628d2",
Qy1 = "169af215aa2456c6a65e13ac4df1ba1c982ca791058612679ef26dcb8fb0a989"
)
test(
id = 8,
EC = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Px0 = "13faa1f28e6bfe89765c284e67face6ce0a29006ebc1551d4243e754c59f88ad",
Px1 = "640cebb80938dfcb998d84a8e5aafd47ffbcba0aa2f8c9b1c585baf119a8942",
Py0 = "1de793a9ef8f4dea5dad12fb09ddefa07ce197d4d7389a29ad3d8c6484582afe",
Py1 = "fc6e1f8bf75d1b7e48fdb6b2869c2de553663742c151b390cede6712da5a084",
scalar = "111e6f761ce48e22970752bd56cab93d47caa252d52948367b21163591f7b7b1",
Qx0 = "1c25702bf3b6f5fb453c6473b6dc2d67cd3cc21c65b589df1bfde254d50cffdd",
Qx1 = "14d03eb2075d6b5995240cc54a01ebe50b43933863f0316760226fbfa3a0280",
Qy0 = "1a075c9f2f6afa6e07e54b143a33c17e81d0ac8b91e0c8e0fdd5082bd6b9a72d",
Qy1 = "8e5ef57bb0f95fb6538dfaeac677977e3f3d6f49142c09584d8ec5c2ccd9b2d"
)
test(
id = 9,
EC = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Px0 = "2fc3da947b78ac524a57670cef36ca89f1dad71b337bc3c18305c582a59648ad",
Px1 = "2f7cc845d8c1ef0613f919d8c47f3c62f83608a45b1e186748ac5dcccd4c6baf",
Py0 = "18ddc4718a4161f72f8d188fc61a609a3d592e186a65f4158483b719ffb05b8f",
Py1 = "45b9c3629ed709784db63ff090e2e891c5b5c6b2222cb6afc56638d7389d689",
scalar = "6223903d4bc2adea7b0a0db92822b6c2638691e4388df93f567e11edd6f23",
Qx0 = "9ec612ab0cf4a48e1c15d22284bce8e34619bfb9afb688a9a7930afcc1bd0f3",
Qx1 = "d796e5f5ae1a15622d2284ada34166b9e7c717bd2ff9b2cf2c6e48c33db5ff2",
Qy0 = "2a8ecb09a01cd2f89b316e7569331e9da3bfbd8a40114913b3e5477442c0e4ef",
Qy1 = "282b14bc00df2dd1733e3187a9845ef3a123c17ce4f6154e5cad26c3b48d1b98"
)

View File

@ -0,0 +1,35 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/[type_fp, curves],
../constantine/elliptic/ec_shortweierstrass_jacobian,
# Test utilities
./t_ec_template
const
Iters = 8
run_EC_addition_tests(
ec = ECP_ShortW_Jac[Fp[BN254_Snarks]],
Iters = Iters,
moduleName = "test_ec_shortweierstrass_jacobian_g1_add_double_" & $BN254_Snarks
)
run_EC_addition_tests(
ec = ECP_ShortW_Jac[Fp[BLS12_381]],
Iters = Iters,
moduleName = "test_ec_shortweierstrass_jacobian_g1_add_double_" & $BLS12_381
)
run_EC_addition_tests(
ec = ECP_ShortW_Jac[Fp[BLS12_377]],
Iters = Iters,
moduleName = "test_ec_shortweierstrass_jacobian_g1_add_double_" & $BLS12_377
)

View File

@ -0,0 +1,36 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/[type_fp, curves],
../constantine/elliptic/ec_shortweierstrass_jacobian,
# Test utilities
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_distributive_tests(
ec = ECP_ShortW_Jac[Fp[BN254_Snarks]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g1_mul_distributive_" & $BN254_Snarks
)
run_EC_mul_distributive_tests(
ec = ECP_ShortW_Jac[Fp[BLS12_381]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g1_mul_distributive_" & $BLS12_381
)
run_EC_mul_distributive_tests(
ec = ECP_ShortW_Jac[Fp[BLS12_377]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g1_mul_distributive_" & $BLS12_377
)

View File

@ -0,0 +1,86 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/[arithmetic, primitives],
../constantine/io/[io_bigints, io_fields, io_ec],
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_jacobian, ec_scalar_mul],
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_sanity_tests(
ec = ECP_ShortW_Jac[Fp[BN254_Snarks]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g1_mul_sanity_" & $BN254_Snarks
)
suite "Order checks on BN254_Snarks":
test "EC mul [Order]P == Inf":
var rng: RngState
let seed = uint32(getTime().toUnix() and (1'i64 shl 32 - 1)) # unixTime mod 2^32
rng.seed(seed)
echo "test_ec_shortweierstrass_jacobian_g1_mul_sanity_extra_curve_order_mul_sanity xoshiro512** seed: ", seed
proc test(EC: typedesc, bits: static int, randZ: static bool) =
for _ in 0 ..< ItersMul:
when randZ:
let a = rng.random_unsafe_with_randZ(EC)
else:
let a = rng.random_unsafe(EC)
let exponent = EC.F.C.getCurveOrder()
var
impl = a
reference = a
impl.scalarMulGeneric(exponent)
reference.unsafe_ECmul_double_add(exponent)
check:
bool(impl.isInf())
bool(reference.isInf())
test(ECP_ShortW_Jac[Fp[BN254_Snarks]], bits = BN254_Snarks.getCurveOrderBitwidth(), randZ = false)
test(ECP_ShortW_Jac[Fp[BN254_Snarks]], bits = BN254_Snarks.getCurveOrderBitwidth(), randZ = true)
# TODO: BLS12 is using a subgroup of order "r" such as r*h = CurveOrder
# with h the curve cofactor
# instead of the full group
# test(Fp[BLS12_381], bits = BLS12_381.getCurveOrderBitwidth(), randZ = false)
# test(Fp[BLS12_381], bits = BLS12_381.getCurveOrderBitwidth(), randZ = true)
test "Not a point on the curve / not a square - #67":
var ax, ay: Fp[BN254_Snarks]
ax.fromHex"0x2a74c9ca553cd5f3437b41e77ca0c8cc77567a7eca5e7debc55b146b0bee324b"
ay.curve_eq_rhs(ax)
check:
bool not ay.isSquare()
bool not ay.sqrt_if_square()
run_EC_mul_sanity_tests(
ec = ECP_ShortW_Jac[Fp[BLS12_381]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g1_mul_sanity_" & $BLS12_381
)
run_EC_mul_sanity_tests(
ec = ECP_ShortW_Jac[Fp[BLS12_377]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g1_mul_sanity_" & $BLS12_377
)

View File

@ -0,0 +1,36 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/[type_fp, curves],
../constantine/elliptic/ec_shortweierstrass_jacobian,
# Test utilities
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_vs_ref_impl(
ec = ECP_ShortW_Jac[Fp[BN254_Snarks]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g1_mul_vs_ref_" & $BN254_Snarks
)
run_EC_mul_vs_ref_impl(
ec = ECP_ShortW_Jac[Fp[BLS12_381]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g1_mul_vs_ref_" & $BLS12_381
)
run_EC_mul_vs_ref_impl(
ec = ECP_ShortW_Jac[Fp[BLS12_377]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g1_mul_vs_ref_" & $BLS12_377
)

View File

@ -0,0 +1,24 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 8
run_EC_addition_tests(
ec = ECP_ShortW_Jac[Fp2[BLS12_377]],
Iters = Iters,
moduleName = "test_ec_shortweierstrass_jacobian_g2_add_double_" & $BLS12_377
)

View File

@ -0,0 +1,24 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 8
run_EC_addition_tests(
ec = ECP_ShortW_Jac[Fp2[BLS12_381]],
Iters = Iters,
moduleName = "test_ec_shortweierstrass_jacobian_g2_add_double_" & $BLS12_381
)

View File

@ -0,0 +1,24 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 8
run_EC_addition_tests(
ec = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Iters = Iters,
moduleName = "test_ec_shortweierstrass_jacobian_g2_add_double_" & $BN254_Snarks
)

View File

@ -0,0 +1,24 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
run_EC_mixed_add_impl(
ec = ECP_ShortW_Jac[Fp2[BLS12_377]],
Iters = Iters,
moduleName = "test_ec_shortweierstrass_jacobian_mixed_add_" & $BLS12_377
)

View File

@ -0,0 +1,24 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
run_EC_mixed_add_impl(
ec = ECP_ShortW_Jac[Fp2[BLS12_381]],
Iters = Iters,
moduleName = "test_ec_shortweierstrass_jacobian_mixed_add_" & $BLS12_381
)

View File

@ -0,0 +1,24 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
run_EC_mixed_add_impl(
ec = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
Iters = Iters,
moduleName = "test_ec_shortweierstrass_jacobian_mixed_add_" & $BN254_Snarks
)

View File

@ -0,0 +1,25 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_distributive_tests(
ec = ECP_ShortW_Jac[Fp2[BLS12_377]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g2_mul_distributive_" & $BLS12_377
)

View File

@ -0,0 +1,25 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_distributive_tests(
ec = ECP_ShortW_Jac[Fp2[BLS12_381]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g2_mul_distributive_" & $BLS12_381
)

View File

@ -0,0 +1,25 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_distributive_tests(
ec = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g2_mul_distributive_" & $BN254_Snarks
)

View File

@ -0,0 +1,56 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_sanity_tests(
ec = ECP_ShortW_Jac[Fp2[BLS12_377]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g2_mul_sanity_" & $BLS12_377
)
# TODO: the order on E'(Fp2) for BLS curves is ??? with r the order on E(Fp)
#
# test "EC mul [Order]P == Inf":
# var rng: RngState
# let seed = uint32(getTime().toUnix() and (1'i64 shl 32 - 1)) # unixTime mod 2^32
# rng.seed(seed)
# echo "test_ec_shortweierstrass_jacobian_g1_mul_sanity_extra_curve_order_mul_sanity xoshiro512** seed: ", seed
#
# proc test(EC: typedesc, bits: static int, randZ: static bool) =
# for _ in 0 ..< ItersMul:
# when randZ:
# let a = rng.random_unsafe_with_randZ(EC)
# else:
# let a = rng.random_unsafe(EC)
#
# let exponent = F.C.getCurveOrder()
#
# var
# impl = a
# reference = a
#
# impl.scalarMulGeneric(exponent)
# reference.unsafe_ECmul_double_add(exponent)
#
# check:
# bool(impl.isInf())
# bool(reference.isInf())
#
# test(ECP_ShortW_Jac[Fp2[BLS12_377]], bits = BLS12_377.getCurveOrderBitwidth(), randZ = false)
# test(ECP_ShortW_Jac[Fp2[BLS12_377]], bits = BLS12_377.getCurveOrderBitwidth(), randZ = true)

View File

@ -0,0 +1,56 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_sanity_tests(
ec = ECP_ShortW_Jac[Fp2[BLS12_381]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g2_mul_sanity_" & $BLS12_381
)
# TODO: the order on E'(Fp2) for BLS curves is ??? with r the order on E(Fp)
#
# test "EC mul [Order]P == Inf":
# var rng: RngState
# let seed = uint32(getTime().toUnix() and (1'i64 shl 32 - 1)) # unixTime mod 2^32
# rng.seed(seed)
# echo "test_ec_shortweierstrass_jacobian_g1_mul_sanity_extra_curve_order_mul_sanity xoshiro512** seed: ", seed
#
# proc test(EC: typedesc, bits: static int, randZ: static bool) =
# for _ in 0 ..< ItersMul:
# when randZ:
# let a = rng.random_unsafe_with_randZ(EC)
# else:
# let a = rng.random_unsafe(EC)
#
# let exponent = F.C.getCurveOrder()
#
# var
# impl = a
# reference = a
#
# impl.scalarMulGeneric(exponent)
# reference.unsafe_ECmul_double_add(exponent)
#
# check:
# bool(impl.isInf())
# bool(reference.isInf())
#
# test(ECP_ShortW_Jac[Fp2[BLS12_381]], bits = BLS12_381.getCurveOrderBitwidth(), randZ = false)
# test(ECP_ShortW_Jac[Fp2[BLS12_381]], bits = BLS12_381.getCurveOrderBitwidth(), randZ = true)

View File

@ -0,0 +1,56 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_sanity_tests(
ec = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g2_mul_sanity_" & $BN254_Snarks
)
# TODO: the order on E'(Fp2) for BN curve is r(2pr) with r the order on E(Fp)
#
# test "EC mul [Order]P == Inf":
# var rng: RngState
# let seed = uint32(getTime().toUnix() and (1'i64 shl 32 - 1)) # unixTime mod 2^32
# rng.seed(seed)
# echo "test_ec_shortweierstrass_jacobian_g1_mul_sanity_extra_curve_order_mul_sanity xoshiro512** seed: ", seed
#
# proc test(EC: typedesc, bits: static int, randZ: static bool) =
# for _ in 0 ..< ItersMul:
# when randZ:
# let a = rng.random_unsafe_with_randZ(EC)
# else:
# let a = rng.random_unsafe(EC)
#
# let exponent = F.C.getCurveOrder()
#
# var
# impl = a
# reference = a
#
# impl.scalarMulGeneric(exponent)
# reference.unsafe_ECmul_double_add(exponent)
#
# check:
# bool(impl.isInf())
# bool(reference.isInf())
#
# test(ECP_ShortW_Jac[Fp2[BN254_Snarks]], bits = BN254_Snarks.getCurveOrderBitwidth(), randZ = false)
# test(ECP_ShortW_Jac[Fp2[BN254_Snarks]], bits = BN254_Snarks.getCurveOrderBitwidth(), randZ = true)

View File

@ -0,0 +1,25 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_vs_ref_impl(
ec = ECP_ShortW_Jac[Fp2[BLS12_377]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g2_mul_vs_ref_" & $BLS12_377
)

View File

@ -0,0 +1,25 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_vs_ref_impl(
ec = ECP_ShortW_Jac[Fp2[BLS12_381]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g2_mul_vs_ref_" & $BLS12_381
)

View File

@ -0,0 +1,25 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Internals
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_jacobian,
../constantine/towers,
# Test utilities
./t_ec_template
const
Iters = 12
ItersMul = Iters div 4
run_EC_mul_vs_ref_impl(
ec = ECP_ShortW_Jac[Fp2[BN254_Snarks]],
ItersMul = ItersMul,
moduleName = "test_ec_shortweierstrass_jacobian_g2_mul_vs_ref_" & $BN254_Snarks
)

View File

@ -7,15 +7,10 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
../constantine/config/[type_fp, curves],
../constantine/elliptic/ec_shortweierstrass_projective,
# Test utilities
../helpers/prng_unsafe,
./t_ec_template
const

View File

@ -7,16 +7,10 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
../constantine/config/[type_fp, curves],
../constantine/elliptic/ec_shortweierstrass_projective,
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const

View File

@ -7,16 +7,10 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
../constantine/config/[type_fp, curves],
../constantine/elliptic/ec_shortweierstrass_projective,
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const

View File

@ -7,16 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
# Test utilities
../helpers/prng_unsafe,
./t_ec_template
const

View File

@ -7,16 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
# Test utilities
../helpers/prng_unsafe,
./t_ec_template
const

View File

@ -7,16 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
# Test utilities
../helpers/prng_unsafe,
./t_ec_template
const

View File

@ -7,17 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const

View File

@ -7,17 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const

View File

@ -7,17 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const

View File

@ -7,17 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const

View File

@ -7,17 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const

View File

@ -7,17 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const

View File

@ -7,17 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const

View File

@ -7,17 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const

View File

@ -7,17 +7,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard library
std/[unittest, times],
# Internals
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/config/curves,
../constantine/elliptic/ec_shortweierstrass_projective,
../constantine/towers,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult,
./t_ec_template
const

View File

@ -19,7 +19,12 @@ import
../constantine/config/[common, curves],
../constantine/arithmetic,
../constantine/towers,
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul],
../constantine/elliptic/[
ec_shortweierstrass_affine,
ec_shortweierstrass_jacobian,
ec_shortweierstrass_projective,
ec_scalar_mul],
../constantine/io/[io_bigints, io_fields],
# Test utilities
../helpers/prng_unsafe,
./support/ec_reference_scalar_mult
@ -215,7 +220,7 @@ proc run_EC_mul_sanity_tests*(
else:
const G1_or_G2 = "G2"
const testSuiteDesc = "Elliptic curve in Short Weierstrass form with projective coordinates"
const testSuiteDesc = "Elliptic curve in Short Weierstrass form"
suite testSuiteDesc & " - " & $ec & " - [" & $WordBitwidth & "-bit mode]":
test "EC " & G1_or_G2 & " mul [0]P == Inf":
@ -313,7 +318,7 @@ proc run_EC_mul_distributive_tests*(
else:
const G1_or_G2 = "G2"
const testSuiteDesc = "Elliptic curve in Short Weierstrass form with projective coordinates"
const testSuiteDesc = "Elliptic curve in Short Weierstrass form"
suite testSuiteDesc & " - " & $ec & " - [" & $WordBitwidth & "-bit mode]":
@ -383,7 +388,7 @@ proc run_EC_mul_vs_ref_impl*(
else:
const G1_or_G2 = "G2"
const testSuiteDesc = "Elliptic curve in Short Weierstrass form with projective coordinates"
const testSuiteDesc = "Elliptic curve in Short Weierstrass form"
suite testSuiteDesc & " - " & $ec & " - [" & $WordBitwidth & "-bit mode]":
test "EC " & G1_or_G2 & " mul constant-time is equivalent to a simple double-and-add algorithm":

View File

@ -0,0 +1,34 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import std/unittest,
../constantine/arithmetic,
../constantine/io/io_fields,
../constantine/config/[common, curves]
echo "\n------------------------------------------------------\n"
proc main() =
suite "Finite field conditional arithmetic":
test "Conditional substraction borrow bug":
let a = FP[BN254_Snarks].fromHex"0x14ae3e4392eb3238968c7624ee3d041590392e289e4f0bdfac4b6e56ac8cf768"
let b = FP[BN254_Snarks].fromHex"0x24e810017b4c0630a0b35b5c63a377097533928b31fa95d58d0e08d1f98b16c6"
let expected = FP[BN254_Snarks].fromHex"0x202a7cb4f8d0cc31ae29607f0c1ae569b287062ed4c640975b5df19b8b7edde9"
var normalsub: Fp[BN254_Snarks]
normalsub.diff(a, b)
var condsub = a
condsub.csub(b, CtTrue)
check:
bool(normalsub == expected)
bool(condsub == expected)
main()

View File

@ -121,12 +121,8 @@ proc main() =
exhaustiveCheck Fake103, 103
exhaustiveCheck Fake10007, 10007
exhaustiveCheck Fake65519, 65519
randomSqrtCheck Mersenne61
randomSqrtCheck Mersenne127
randomSqrtCheck BN254_Nogami
randomSqrtCheck BN254_Snarks
randomSqrtCheck P256
randomSqrtCheck Secp256k1
randomSqrtCheck BLS12_377 # p ≢ 3 (mod 4)
randomSqrtCheck BLS12_381