diff --git a/benchmarks/bench_ec_g1.nim b/benchmarks/bench_ec_g1.nim index a3b11dd..a7307f4 100644 --- a/benchmarks/bench_ec_g1.nim +++ b/benchmarks/bench_ec_g1.nim @@ -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() diff --git a/benchmarks/bench_ec_g2.nim b/benchmarks/bench_ec_g2.nim index 087a486..30e2ad6 100644 --- a/benchmarks/bench_ec_g2.nim +++ b/benchmarks/bench_ec_g2.nim @@ -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() diff --git a/benchmarks/bench_elliptic_template.nim b/benchmarks/bench_elliptic_template.nim index 258f709..f0c91a6 100644 --- a/benchmarks/bench_elliptic_template.nim +++ b/benchmarks/bench_elliptic_template.nim @@ -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" diff --git a/benchmarks/bench_fields_template.nim b/benchmarks/bench_fields_template.nim index da7c6fa..f4821f7 100644 --- a/benchmarks/bench_fields_template.nim +++ b/benchmarks/bench_fields_template.nim @@ -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) diff --git a/benchmarks/bench_fp.nim b/benchmarks/bench_fp.nim index 08a1dd8..c76c3f6 100644 --- a/benchmarks/bench_fp.nim +++ b/benchmarks/bench_fp.nim @@ -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) diff --git a/benchmarks/bench_fp2.nim b/benchmarks/bench_fp2.nim index a128bd2..267a8f0 100644 --- a/benchmarks/bench_fp2.nim +++ b/benchmarks/bench_fp2.nim @@ -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) diff --git a/benchmarks/bench_fp4.nim b/benchmarks/bench_fp4.nim new file mode 100644 index 0000000..a056cf0 --- /dev/null +++ b/benchmarks/bench_fp4.nim @@ -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() diff --git a/constantine.nimble b/constantine.nimble index 3f4d3e4..005d2f3 100644 --- a/constantine.nimble +++ b/constantine.nimble @@ -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") diff --git a/constantine/arithmetic/finite_fields.nim b/constantine/arithmetic/finite_fields.nim index 7d4a9fb..630f978 100644 --- a/constantine/arithmetic/finite_fields.nim +++ b/constantine/arithmetic/finite_fields.nim @@ -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 diff --git a/constantine/arithmetic/limbs.nim b/constantine/arithmetic/limbs.nim index 6364d05..4229b99 100644 --- a/constantine/arithmetic/limbs.nim +++ b/constantine/arithmetic/limbs.nim @@ -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 diff --git a/constantine/elliptic/README.md b/constantine/elliptic/README.md index a0d5021..ba7e7d7 100644 --- a/constantine/elliptic/README.md +++ b/constantine/elliptic/README.md @@ -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 diff --git a/constantine/elliptic/ec_endomorphism_accel.nim b/constantine/elliptic/ec_endomorphism_accel.nim index 3b874f0..b21fa10 100644 --- a/constantine/elliptic/ec_endomorphism_accel.nim +++ b/constantine/elliptic/ec_endomorphism_accel.nim @@ -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 diff --git a/constantine/elliptic/ec_scalar_mul.nim b/constantine/elliptic/ec_scalar_mul.nim index 123a3be..624784d 100644 --- a/constantine/elliptic/ec_scalar_mul.nim +++ b/constantine/elliptic/ec_scalar_mul.nim @@ -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".} diff --git a/constantine/elliptic/ec_shortweierstrass_affine.nim b/constantine/elliptic/ec_shortweierstrass_affine.nim index 2de80f5..850c203 100644 --- a/constantine/elliptic/ec_shortweierstrass_affine.nim +++ b/constantine/elliptic/ec_shortweierstrass_affine.nim @@ -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) diff --git a/constantine/elliptic/ec_shortweierstrass_jacobian.nim b/constantine/elliptic/ec_shortweierstrass_jacobian.nim new file mode 100644 index 0000000..f339d47 --- /dev/null +++ b/constantine/elliptic/ec_shortweierstrass_jacobian.nim @@ -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 | | | +# ``` diff --git a/constantine/elliptic/ec_shortweierstrass_projective.nim b/constantine/elliptic/ec_shortweierstrass_projective.nim index 83caefe..418a2f0 100644 --- a/constantine/elliptic/ec_shortweierstrass_projective.nim +++ b/constantine/elliptic/ec_shortweierstrass_projective.nim @@ -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 ## diff --git a/constantine/io/io_ec.nim b/constantine/io/io_ec.nim index f6cc771..f4bd626 100644 --- a/constantine/io/io_ec.nim +++ b/constantine/io/io_ec.nim @@ -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 diff --git a/constantine/tower_field_extensions/tower_common.nim b/constantine/tower_field_extensions/tower_common.nim index 50fed56..f548f80 100644 --- a/constantine/tower_field_extensions/tower_common.nim +++ b/constantine/tower_field_extensions/tower_common.nim @@ -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 # ------------------------------------------------------------------- diff --git a/helpers/prng_unsafe.nim b/helpers/prng_unsafe.nim index 1d291e6..23aaf08 100644 --- a/helpers/prng_unsafe.nim +++ b/helpers/prng_unsafe.nim @@ -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) diff --git a/tests/support/ec_reference_scalar_mult.nim b/tests/support/ec_reference_scalar_mult.nim index ac01473..f530ca2 100644 --- a/tests/support/ec_reference_scalar_mult.nim +++ b/tests/support/ec_reference_scalar_mult.nim @@ -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 diff --git a/tests/t_ec_sage_bls12_377.nim b/tests/t_ec_sage_bls12_377.nim index 49a6fc5..ba5e9e9 100644 --- a/tests/t_ec_sage_bls12_377.nim +++ b/tests/t_ec_sage_bls12_377.nim @@ -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" + ) diff --git a/tests/t_ec_sage_bls12_381.nim b/tests/t_ec_sage_bls12_381.nim index 1f37073..fd93ce7 100644 --- a/tests/t_ec_sage_bls12_381.nim +++ b/tests/t_ec_sage_bls12_381.nim @@ -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" + ) diff --git a/tests/t_ec_sage_bn254.nim b/tests/t_ec_sage_bn254.nim index eb5d5f6..353af95 100644 --- a/tests/t_ec_sage_bn254.nim +++ b/tests/t_ec_sage_bn254.nim @@ -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" + ) diff --git a/tests/t_ec_shortw_jac_g1_add_double.nim b/tests/t_ec_shortw_jac_g1_add_double.nim new file mode 100644 index 0000000..1165734 --- /dev/null +++ b/tests/t_ec_shortw_jac_g1_add_double.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g1_mul_distri.nim b/tests/t_ec_shortw_jac_g1_mul_distri.nim new file mode 100644 index 0000000..6b24b63 --- /dev/null +++ b/tests/t_ec_shortw_jac_g1_mul_distri.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g1_mul_sanity.nim b/tests/t_ec_shortw_jac_g1_mul_sanity.nim new file mode 100644 index 0000000..cdd711e --- /dev/null +++ b/tests/t_ec_shortw_jac_g1_mul_sanity.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g1_mul_vs_ref.nim b/tests/t_ec_shortw_jac_g1_mul_vs_ref.nim new file mode 100644 index 0000000..56bb7fe --- /dev/null +++ b/tests/t_ec_shortw_jac_g1_mul_vs_ref.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_add_double_bls12_377.nim b/tests/t_ec_shortw_jac_g2_add_double_bls12_377.nim new file mode 100644 index 0000000..420dee7 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_add_double_bls12_377.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_add_double_bls12_381.nim b/tests/t_ec_shortw_jac_g2_add_double_bls12_381.nim new file mode 100644 index 0000000..6426df6 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_add_double_bls12_381.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_add_double_bn254_snarks.nim b/tests/t_ec_shortw_jac_g2_add_double_bn254_snarks.nim new file mode 100644 index 0000000..1555871 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_add_double_bn254_snarks.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_mixed_add_bls12_377.nim b/tests/t_ec_shortw_jac_g2_mixed_add_bls12_377.nim new file mode 100644 index 0000000..766c192 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mixed_add_bls12_377.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_mixed_add_bls12_381.nim b/tests/t_ec_shortw_jac_g2_mixed_add_bls12_381.nim new file mode 100644 index 0000000..c8fcef6 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mixed_add_bls12_381.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_mixed_add_bn254_snarks.nim b/tests/t_ec_shortw_jac_g2_mixed_add_bn254_snarks.nim new file mode 100644 index 0000000..48ca35c --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mixed_add_bn254_snarks.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_mul_distri_bls12_377.nim b/tests/t_ec_shortw_jac_g2_mul_distri_bls12_377.nim new file mode 100644 index 0000000..2179bd8 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mul_distri_bls12_377.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_mul_distri_bls12_381.nim b/tests/t_ec_shortw_jac_g2_mul_distri_bls12_381.nim new file mode 100644 index 0000000..3336e4e --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mul_distri_bls12_381.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_mul_distri_bn254_snarks.nim b/tests/t_ec_shortw_jac_g2_mul_distri_bn254_snarks.nim new file mode 100644 index 0000000..7291990 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mul_distri_bn254_snarks.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_mul_sanity_bls12_377.nim b/tests/t_ec_shortw_jac_g2_mul_sanity_bls12_377.nim new file mode 100644 index 0000000..5e5d827 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mul_sanity_bls12_377.nim @@ -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) diff --git a/tests/t_ec_shortw_jac_g2_mul_sanity_bls12_381.nim b/tests/t_ec_shortw_jac_g2_mul_sanity_bls12_381.nim new file mode 100644 index 0000000..afe41e9 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mul_sanity_bls12_381.nim @@ -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) diff --git a/tests/t_ec_shortw_jac_g2_mul_sanity_bn254_snarks.nim b/tests/t_ec_shortw_jac_g2_mul_sanity_bn254_snarks.nim new file mode 100644 index 0000000..7f3d568 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mul_sanity_bn254_snarks.nim @@ -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∗(2p−r) 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) diff --git a/tests/t_ec_shortw_jac_g2_mul_vs_ref_bls12_377.nim b/tests/t_ec_shortw_jac_g2_mul_vs_ref_bls12_377.nim new file mode 100644 index 0000000..10afeda --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mul_vs_ref_bls12_377.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_mul_vs_ref_bls12_381.nim b/tests/t_ec_shortw_jac_g2_mul_vs_ref_bls12_381.nim new file mode 100644 index 0000000..2780311 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mul_vs_ref_bls12_381.nim @@ -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 + ) diff --git a/tests/t_ec_shortw_jac_g2_mul_vs_ref_bn254_snarks.nim b/tests/t_ec_shortw_jac_g2_mul_vs_ref_bn254_snarks.nim new file mode 100644 index 0000000..9fb80a8 --- /dev/null +++ b/tests/t_ec_shortw_jac_g2_mul_vs_ref_bn254_snarks.nim @@ -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 + ) diff --git a/tests/t_ec_wstrass_prj_edge_cases.nim b/tests/t_ec_shortw_prj_edge_cases.nim similarity index 100% rename from tests/t_ec_wstrass_prj_edge_cases.nim rename to tests/t_ec_shortw_prj_edge_cases.nim diff --git a/tests/t_ec_wstrass_prj_g1_add_double.nim b/tests/t_ec_shortw_prj_g1_add_double.nim similarity index 80% rename from tests/t_ec_wstrass_prj_g1_add_double.nim rename to tests/t_ec_shortw_prj_g1_add_double.nim index 69f241a..98e6cce 100644 --- a/tests/t_ec_wstrass_prj_g1_add_double.nim +++ b/tests/t_ec_shortw_prj_g1_add_double.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g1_mixed_add.nim b/tests/t_ec_shortw_prj_g1_mixed_add.nim similarity index 100% rename from tests/t_ec_wstrass_prj_g1_mixed_add.nim rename to tests/t_ec_shortw_prj_g1_mixed_add.nim diff --git a/tests/t_ec_wstrass_prj_g1_mul_distri.nim b/tests/t_ec_shortw_prj_g1_mul_distri.nim similarity index 78% rename from tests/t_ec_wstrass_prj_g1_mul_distri.nim rename to tests/t_ec_shortw_prj_g1_mul_distri.nim index aaa4d6e..64f46f3 100644 --- a/tests/t_ec_wstrass_prj_g1_mul_distri.nim +++ b/tests/t_ec_shortw_prj_g1_mul_distri.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g1_mul_sanity.nim b/tests/t_ec_shortw_prj_g1_mul_sanity.nim similarity index 100% rename from tests/t_ec_wstrass_prj_g1_mul_sanity.nim rename to tests/t_ec_shortw_prj_g1_mul_sanity.nim diff --git a/tests/t_ec_wstrass_prj_g1_mul_vs_ref.nim b/tests/t_ec_shortw_prj_g1_mul_vs_ref.nim similarity index 78% rename from tests/t_ec_wstrass_prj_g1_mul_vs_ref.nim rename to tests/t_ec_shortw_prj_g1_mul_vs_ref.nim index 288eaf5..a416716 100644 --- a/tests/t_ec_wstrass_prj_g1_mul_vs_ref.nim +++ b/tests/t_ec_shortw_prj_g1_mul_vs_ref.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_add_double_bls12_377.nim b/tests/t_ec_shortw_prj_g2_add_double_bls12_377.nim similarity index 74% rename from tests/t_ec_wstrass_prj_g2_add_double_bls12_377.nim rename to tests/t_ec_shortw_prj_g2_add_double_bls12_377.nim index c26d131..d8d50d9 100644 --- a/tests/t_ec_wstrass_prj_g2_add_double_bls12_377.nim +++ b/tests/t_ec_shortw_prj_g2_add_double_bls12_377.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_add_double_bls12_381.nim b/tests/t_ec_shortw_prj_g2_add_double_bls12_381.nim similarity index 74% rename from tests/t_ec_wstrass_prj_g2_add_double_bls12_381.nim rename to tests/t_ec_shortw_prj_g2_add_double_bls12_381.nim index 0bbbee6..bb13c84 100644 --- a/tests/t_ec_wstrass_prj_g2_add_double_bls12_381.nim +++ b/tests/t_ec_shortw_prj_g2_add_double_bls12_381.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_add_double_bn254_snarks.nim b/tests/t_ec_shortw_prj_g2_add_double_bn254_snarks.nim similarity index 74% rename from tests/t_ec_wstrass_prj_g2_add_double_bn254_snarks.nim rename to tests/t_ec_shortw_prj_g2_add_double_bn254_snarks.nim index 5e493af..b4fbb75 100644 --- a/tests/t_ec_wstrass_prj_g2_add_double_bn254_snarks.nim +++ b/tests/t_ec_shortw_prj_g2_add_double_bn254_snarks.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_mixed_add_bls12_377.nim b/tests/t_ec_shortw_prj_g2_mixed_add_bls12_377.nim similarity index 100% rename from tests/t_ec_wstrass_prj_g2_mixed_add_bls12_377.nim rename to tests/t_ec_shortw_prj_g2_mixed_add_bls12_377.nim diff --git a/tests/t_ec_wstrass_prj_g2_mixed_add_bls12_381.nim b/tests/t_ec_shortw_prj_g2_mixed_add_bls12_381.nim similarity index 100% rename from tests/t_ec_wstrass_prj_g2_mixed_add_bls12_381.nim rename to tests/t_ec_shortw_prj_g2_mixed_add_bls12_381.nim diff --git a/tests/t_ec_wstrass_prj_g2_mixed_add_bn254_snarks.nim b/tests/t_ec_shortw_prj_g2_mixed_add_bn254_snarks.nim similarity index 100% rename from tests/t_ec_wstrass_prj_g2_mixed_add_bn254_snarks.nim rename to tests/t_ec_shortw_prj_g2_mixed_add_bn254_snarks.nim diff --git a/tests/t_ec_wstrass_prj_g2_mul_distri_bls12_377.nim b/tests/t_ec_shortw_prj_g2_mul_distri_bls12_377.nim similarity index 71% rename from tests/t_ec_wstrass_prj_g2_mul_distri_bls12_377.nim rename to tests/t_ec_shortw_prj_g2_mul_distri_bls12_377.nim index edb5a02..23de880 100644 --- a/tests/t_ec_wstrass_prj_g2_mul_distri_bls12_377.nim +++ b/tests/t_ec_shortw_prj_g2_mul_distri_bls12_377.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_mul_distri_bls12_381.nim b/tests/t_ec_shortw_prj_g2_mul_distri_bls12_381.nim similarity index 71% rename from tests/t_ec_wstrass_prj_g2_mul_distri_bls12_381.nim rename to tests/t_ec_shortw_prj_g2_mul_distri_bls12_381.nim index cc8b52d..cdc4f6d 100644 --- a/tests/t_ec_wstrass_prj_g2_mul_distri_bls12_381.nim +++ b/tests/t_ec_shortw_prj_g2_mul_distri_bls12_381.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_mul_distri_bn254_snarks.nim b/tests/t_ec_shortw_prj_g2_mul_distri_bn254_snarks.nim similarity index 72% rename from tests/t_ec_wstrass_prj_g2_mul_distri_bn254_snarks.nim rename to tests/t_ec_shortw_prj_g2_mul_distri_bn254_snarks.nim index b7c1baf..0efb832 100644 --- a/tests/t_ec_wstrass_prj_g2_mul_distri_bn254_snarks.nim +++ b/tests/t_ec_shortw_prj_g2_mul_distri_bn254_snarks.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_mul_sanity_bls12_377.nim b/tests/t_ec_shortw_prj_g2_mul_sanity_bls12_377.nim similarity index 85% rename from tests/t_ec_wstrass_prj_g2_mul_sanity_bls12_377.nim rename to tests/t_ec_shortw_prj_g2_mul_sanity_bls12_377.nim index b1750e3..d97c130 100644 --- a/tests/t_ec_wstrass_prj_g2_mul_sanity_bls12_377.nim +++ b/tests/t_ec_shortw_prj_g2_mul_sanity_bls12_377.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_mul_sanity_bls12_381.nim b/tests/t_ec_shortw_prj_g2_mul_sanity_bls12_381.nim similarity index 85% rename from tests/t_ec_wstrass_prj_g2_mul_sanity_bls12_381.nim rename to tests/t_ec_shortw_prj_g2_mul_sanity_bls12_381.nim index f01617a..a41f719 100644 --- a/tests/t_ec_wstrass_prj_g2_mul_sanity_bls12_381.nim +++ b/tests/t_ec_shortw_prj_g2_mul_sanity_bls12_381.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_mul_sanity_bn254_snarks.nim b/tests/t_ec_shortw_prj_g2_mul_sanity_bn254_snarks.nim similarity index 85% rename from tests/t_ec_wstrass_prj_g2_mul_sanity_bn254_snarks.nim rename to tests/t_ec_shortw_prj_g2_mul_sanity_bn254_snarks.nim index 465dd9c..9101f4b 100644 --- a/tests/t_ec_wstrass_prj_g2_mul_sanity_bn254_snarks.nim +++ b/tests/t_ec_shortw_prj_g2_mul_sanity_bn254_snarks.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_mul_vs_ref_bls12_377.nim b/tests/t_ec_shortw_prj_g2_mul_vs_ref_bls12_377.nim similarity index 71% rename from tests/t_ec_wstrass_prj_g2_mul_vs_ref_bls12_377.nim rename to tests/t_ec_shortw_prj_g2_mul_vs_ref_bls12_377.nim index 4530f33..d7e238c 100644 --- a/tests/t_ec_wstrass_prj_g2_mul_vs_ref_bls12_377.nim +++ b/tests/t_ec_shortw_prj_g2_mul_vs_ref_bls12_377.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_mul_vs_ref_bls12_381.nim b/tests/t_ec_shortw_prj_g2_mul_vs_ref_bls12_381.nim similarity index 71% rename from tests/t_ec_wstrass_prj_g2_mul_vs_ref_bls12_381.nim rename to tests/t_ec_shortw_prj_g2_mul_vs_ref_bls12_381.nim index 2c3dd53..979dd7c 100644 --- a/tests/t_ec_wstrass_prj_g2_mul_vs_ref_bls12_381.nim +++ b/tests/t_ec_shortw_prj_g2_mul_vs_ref_bls12_381.nim @@ -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 diff --git a/tests/t_ec_wstrass_prj_g2_mul_vs_ref_bn254_snarks.nim b/tests/t_ec_shortw_prj_g2_mul_vs_ref_bn254_snarks.nim similarity index 71% rename from tests/t_ec_wstrass_prj_g2_mul_vs_ref_bn254_snarks.nim rename to tests/t_ec_shortw_prj_g2_mul_vs_ref_bn254_snarks.nim index a9f1501..dc33401 100644 --- a/tests/t_ec_wstrass_prj_g2_mul_vs_ref_bn254_snarks.nim +++ b/tests/t_ec_shortw_prj_g2_mul_vs_ref_bn254_snarks.nim @@ -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 diff --git a/tests/t_ec_template.nim b/tests/t_ec_template.nim index db72f7d..9288d66 100644 --- a/tests/t_ec_template.nim +++ b/tests/t_ec_template.nim @@ -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": diff --git a/tests/t_finite_fields_conditional_arithmetic.nim b/tests/t_finite_fields_conditional_arithmetic.nim new file mode 100644 index 0000000..4612723 --- /dev/null +++ b/tests/t_finite_fields_conditional_arithmetic.nim @@ -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() diff --git a/tests/t_finite_fields_sqrt.nim b/tests/t_finite_fields_sqrt.nim index 93436e3..5e8db64 100644 --- a/tests/t_finite_fields_sqrt.nim +++ b/tests/t_finite_fields_sqrt.nim @@ -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