From 776e9069ea6536c2bb27c5681dfdbea5a8ce81dd Mon Sep 17 00:00:00 2001 From: Mamy Ratsimbazafy Date: Mon, 15 Jul 2024 14:08:05 +0200 Subject: [PATCH] =?UTF-8?q?feat(=F0=9D=94=BE=E2=82=9C=20constant-time=20ex?= =?UTF-8?q?ponentiation):=20generalize=20ec=5Fendomorphism=5Faccel=20to=20?= =?UTF-8?q?elliptic=20curve=20and=20=F0=9D=94=BE=E2=82=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- benchmarks/bench_ec_g1_scalar_mul.nim | 8 +- benchmarks/bench_ec_g2.nim | 5 +- benchmarks/bench_ec_g2_scalar_mul.nim | 8 +- benchmarks/bench_ec_msm_bandersnatch.nim | 2 +- benchmarks/bench_ec_msm_bls12_381_g1.nim | 4 +- benchmarks/bench_ec_msm_bls12_381_g2.nim | 4 +- benchmarks/bench_ec_msm_bn254_snarks_g1.nim | 4 +- benchmarks/bench_ec_msm_pasta.nim | 4 +- benchmarks/bench_elliptic_template.nim | 10 +- ...nch_eth_eip2537_subgroup_checks_impact.nim | 2 +- benchmarks/bench_gt.nim | 2 +- benchmarks/bench_gt_template.nim | 8 +- benchmarks/bench_summary_bls12_377.nim | 8 +- benchmarks/bench_summary_bls12_381.nim | 8 +- benchmarks/bench_summary_bn254_nogami.nim | 8 +- benchmarks/bench_summary_bn254_snarks.nim | 8 +- benchmarks/bench_summary_pasta.nim | 8 +- benchmarks/bench_summary_template.nim | 11 +- .../multilinear_extensions.nim | 4 +- constantine/lowlevel_extension_fields.nim | 2 +- constantine/lowlevel_pairing_curves.nim | 2 +- constantine/math/arithmetic/bigints.nim | 6 +- constantine/math/ec_shortweierstrass.nim | 2 + .../math/elliptic/ec_multi_scalar_mul.nim | 2 +- .../elliptic/ec_multi_scalar_mul_parallel.nim | 2 +- constantine/math/elliptic/ec_scalar_mul.nim | 200 ++++++++++++++- .../math/elliptic/ec_scalar_mul_vartime.nim | 23 +- .../frobenius.nim | 0 .../split_scalars.nim} | 238 ++++-------------- constantine/math/isogenies/README.md | 15 -- .../math/pairings/cyclotomic_subgroups.nim | 2 +- .../pairings/gt_exponentiations_vartime.nim | 15 +- constantine/math/pairings/miller_loops.nim | 2 +- constantine/math/pairings/pairings_bls12.nim | 2 +- constantine/math/pairings/pairings_bn.nim | 2 +- .../math/pairings/pairings_bw6_761.nim | 2 +- .../named/constants/bls12_377_pairings.nim | 2 +- .../named/constants/bls12_377_subgroups.nim | 2 +- .../named/constants/bls12_381_pairings.nim | 2 +- .../named/constants/bls12_381_subgroups.nim | 2 +- .../named/constants/bn254_nogami_pairings.nim | 2 +- .../constants/bn254_nogami_subgroups.nim | 2 +- .../named/constants/bn254_snarks_pairings.nim | 2 +- .../constants/bn254_snarks_subgroups.nim | 2 +- .../named/constants/bw6_761_pairings.nim | 2 +- .../named/constants/bw6_761_subgroups.nim | 2 +- constantine/named/zoo_endomorphisms.nim | 4 +- constantine/platforms/abstractions.nim | 9 + metering/eip2537.md | 8 +- research/endomorphisms/glv.nim | 4 +- tests/math_elliptic_curves/t_ec_frobenius.nim | 2 +- .../t_ec_sage_bls12_377.nim | 3 +- .../t_ec_sage_bls12_381.nim | 3 +- .../t_ec_sage_bn254_nogami.nim | 3 +- .../t_ec_sage_bn254_snarks.nim | 3 +- .../t_ec_sage_bw6_761_g1.nim | 3 +- .../t_ec_sage_bw6_761_g2.nim | 3 +- .../math_elliptic_curves/t_ec_sage_pallas.nim | 3 +- .../t_ec_sage_template.nim | 17 +- .../math_elliptic_curves/t_ec_sage_vesta.nim | 3 +- .../t_ec_shortw_jac_g1_msm.nim | 2 +- .../t_ec_shortw_prj_g1_msm.nim | 2 +- tests/math_elliptic_curves/t_ec_template.nim | 17 +- .../t_ec_twedw_prj_msm.nim | 2 +- ...wedwards_mul_endomorphism_bandersnatch.nim | 2 +- .../t_fp_tower_frobenius_template.nim | 2 +- .../t_pairing_cyclotomic_subgroup.nim | 2 +- tests/math_pairings/t_pairing_template.nim | 14 +- .../t_ec_shortw_jac_g1_msm_parallel.nim | 2 +- .../t_ec_shortw_prj_g1_msm_parallel.nim | 2 +- 70 files changed, 375 insertions(+), 393 deletions(-) rename constantine/math/{isogenies => endomorphisms}/frobenius.nim (100%) rename constantine/math/{elliptic/ec_endomorphism_accel.nim => endomorphisms/split_scalars.nim} (67%) delete mode 100644 constantine/math/isogenies/README.md diff --git a/benchmarks/bench_ec_g1_scalar_mul.nim b/benchmarks/bench_ec_g1_scalar_mul.nim index e53888a3..41f21a7d 100644 --- a/benchmarks/bench_ec_g1_scalar_mul.nim +++ b/benchmarks/bench_ec_g1_scalar_mul.nim @@ -8,11 +8,9 @@ import # Internals - constantine/named/algebras, + constantine/named/[algebras, zoo_endomorphisms], constantine/math/arithmetic, - constantine/math/elliptic/[ - ec_shortweierstrass_projective, - ec_shortweierstrass_jacobian], + constantine/math/ec_shortweierstrass, # Helpers ./bench_elliptic_template @@ -69,7 +67,7 @@ proc main() = scalarMulVartimeWNAFBench(EC_ShortW_Jac[Fp[curve], G1], bits, window = 4, MulIters) scalarMulVartimeWNAFBench(EC_ShortW_Jac[Fp[curve], G1], bits, window = 5, MulIters) separator() - when bits >= 196: # All endomorphisms constants are below this threshold + when bits >= EndomorphismThreshold: # All endomorphisms constants are below this threshold scalarMulVartimeEndoWNAFBench(EC_ShortW_Prj[Fp[curve], G1], bits, window = 2, MulIters) scalarMulVartimeEndoWNAFBench(EC_ShortW_Prj[Fp[curve], G1], bits, window = 3, MulIters) scalarMulVartimeEndoWNAFBench(EC_ShortW_Prj[Fp[curve], G1], bits, window = 4, MulIters) diff --git a/benchmarks/bench_ec_g2.nim b/benchmarks/bench_ec_g2.nim index a17f0bb7..06dd9384 100644 --- a/benchmarks/bench_ec_g2.nim +++ b/benchmarks/bench_ec_g2.nim @@ -11,10 +11,7 @@ import constantine/named/algebras, constantine/math/arithmetic, constantine/math/extension_fields, - constantine/math/elliptic/[ - ec_shortweierstrass_projective, - ec_shortweierstrass_jacobian, - ec_shortweierstrass_jacobian_extended], + constantine/math/ec_shortweierstrass, # Helpers ./bench_elliptic_template, # Standard library diff --git a/benchmarks/bench_ec_g2_scalar_mul.nim b/benchmarks/bench_ec_g2_scalar_mul.nim index 1b05fdec..91f5fc46 100644 --- a/benchmarks/bench_ec_g2_scalar_mul.nim +++ b/benchmarks/bench_ec_g2_scalar_mul.nim @@ -8,12 +8,10 @@ import # Internals - constantine/named/algebras, + constantine/named/[algebras, zoo_endomorphisms], constantine/math/arithmetic, constantine/math/extension_fields, - constantine/math/elliptic/[ - ec_shortweierstrass_projective, - ec_shortweierstrass_jacobian], + constantine/math/ec_shortweierstrass, # Helpers ./bench_elliptic_template @@ -68,7 +66,7 @@ proc main() = scalarMulVartimeWNAFBench(EC_ShortW_Jac[Fp2[curve], G2], bits, window = 4, MulIters) scalarMulVartimeWNAFBench(EC_ShortW_Jac[Fp2[curve], G2], bits, window = 5, MulIters) separator() - when bits >= 196: # All endomorphisms constants are below this threshold + when bits >= EndomorphismThreshold: # All endomorphisms constants are below this threshold scalarMulVartimeEndoWNAFBench(EC_ShortW_Prj[Fp2[curve], G2], bits, window = 2, MulIters) scalarMulVartimeEndoWNAFBench(EC_ShortW_Prj[Fp2[curve], G2], bits, window = 3, MulIters) scalarMulVartimeEndoWNAFBench(EC_ShortW_Prj[Fp2[curve], G2], bits, window = 4, MulIters) diff --git a/benchmarks/bench_ec_msm_bandersnatch.nim b/benchmarks/bench_ec_msm_bandersnatch.nim index f9c77655..2c5b068b 100644 --- a/benchmarks/bench_ec_msm_bandersnatch.nim +++ b/benchmarks/bench_ec_msm_bandersnatch.nim @@ -10,7 +10,7 @@ import # Internals constantine/named/algebras, constantine/math/arithmetic, - constantine/math/elliptic/ec_twistededwards_projective, + constantine/math/ec_twistededwards, # Helpers helpers/prng_unsafe, ./bench_elliptic_parallel_template diff --git a/benchmarks/bench_ec_msm_bls12_381_g1.nim b/benchmarks/bench_ec_msm_bls12_381_g1.nim index f05c3d9d..da953b18 100644 --- a/benchmarks/bench_ec_msm_bls12_381_g1.nim +++ b/benchmarks/bench_ec_msm_bls12_381_g1.nim @@ -10,9 +10,7 @@ import # Internals constantine/named/algebras, constantine/math/arithmetic, - constantine/math/elliptic/[ - ec_shortweierstrass_projective, - ec_shortweierstrass_jacobian], + constantine/math/ec_shortweierstrass, # Helpers helpers/prng_unsafe, ./bench_elliptic_parallel_template diff --git a/benchmarks/bench_ec_msm_bls12_381_g2.nim b/benchmarks/bench_ec_msm_bls12_381_g2.nim index 79b0d2b7..48f83cf9 100644 --- a/benchmarks/bench_ec_msm_bls12_381_g2.nim +++ b/benchmarks/bench_ec_msm_bls12_381_g2.nim @@ -10,9 +10,7 @@ import # Internals constantine/named/algebras, constantine/math/extension_fields, - constantine/math/elliptic/[ - ec_shortweierstrass_projective, - ec_shortweierstrass_jacobian], + constantine/math/ec_shortweierstrass, # Helpers helpers/prng_unsafe, ./bench_elliptic_parallel_template diff --git a/benchmarks/bench_ec_msm_bn254_snarks_g1.nim b/benchmarks/bench_ec_msm_bn254_snarks_g1.nim index 4765e0bb..0a86e293 100644 --- a/benchmarks/bench_ec_msm_bn254_snarks_g1.nim +++ b/benchmarks/bench_ec_msm_bn254_snarks_g1.nim @@ -10,9 +10,7 @@ import # Internals constantine/named/algebras, constantine/math/arithmetic, - constantine/math/elliptic/[ - ec_shortweierstrass_projective, - ec_shortweierstrass_jacobian], + constantine/math/ec_shortweierstrass, # Helpers ./bench_elliptic_parallel_template diff --git a/benchmarks/bench_ec_msm_pasta.nim b/benchmarks/bench_ec_msm_pasta.nim index 6200d376..708002d6 100644 --- a/benchmarks/bench_ec_msm_pasta.nim +++ b/benchmarks/bench_ec_msm_pasta.nim @@ -10,9 +10,7 @@ import # Internals constantine/named/algebras, constantine/math/arithmetic, - constantine/math/elliptic/[ - ec_shortweierstrass_projective, - ec_shortweierstrass_jacobian], + constantine/math/ec_shortweierstrass, # Helpers helpers/prng_unsafe, ./bench_elliptic_parallel_template diff --git a/benchmarks/bench_elliptic_template.nim b/benchmarks/bench_elliptic_template.nim index faf4a36c..13aca484 100644 --- a/benchmarks/bench_elliptic_template.nim +++ b/benchmarks/bench_elliptic_template.nim @@ -24,7 +24,7 @@ import ec_shortweierstrass_jacobian, ec_shortweierstrass_jacobian_extended, ec_shortweierstrass_batch_ops, - ec_scalar_mul, ec_endomorphism_accel], + ec_scalar_mul], constantine/named/zoo_subgroups, # Helpers helpers/prng_unsafe, @@ -210,7 +210,7 @@ proc scalarMulVartimeMinHammingWeightRecodingBench*(EC: typedesc, bits: static i bench("EC ScalarMul " & $bits & "-bit " & $EC.G & " (vartime min Hamming Weight recoding)", EC, iters): r = P - r.scalarMul_minHammingWeight_vartime(exponent) + r.scalarMul_jy00_vartime(exponent) proc scalarMulVartimeWNAFBench*(EC: typedesc, bits, window: static int, iters: int) = var r {.noInit.}: EC @@ -221,7 +221,7 @@ proc scalarMulVartimeWNAFBench*(EC: typedesc, bits, window: static int, iters: i bench("EC ScalarMul " & $bits & "-bit " & $EC.G & " (vartime wNAF-" & $window & ")", EC, iters): r = P - r.scalarMul_minHammingWeight_windowed_vartime(exponent, window) + r.scalarMul_wNAF_vartime(exponent, window) proc scalarMulVartimeEndoWNAFBench*(EC: typedesc, bits, window: static int, iters: int) = var r {.noInit.}: EC @@ -232,7 +232,7 @@ proc scalarMulVartimeEndoWNAFBench*(EC: typedesc, bits, window: static int, iter bench("EC ScalarMul " & $bits & "-bit " & $EC.G & " (vartime endomorphism + wNAF-" & $window & ")", EC, iters): r = P - r.scalarMulEndo_minHammingWeight_windowed_vartime(exponent, window) + r.scalarMulEndo_wNAF_vartime(exponent, window) proc subgroupCheckBench*(EC: typedesc, iters: int) = var P = rng.random_unsafe(EC) @@ -251,7 +251,7 @@ proc subgroupCheckScalarMulVartimeEndoWNAFBench*(EC: typedesc, bits, window: sta bench("EC subgroup check + ScalarMul " & $bits & "-bit " & $EC.G & " (vartime endo + wNAF-" & $window & ")", EC, iters): r = P discard r.isInSubgroup() - r.scalarMulEndo_minHammingWeight_windowed_vartime(exponent, window) + r.scalarMulEndo_wNAF_vartime(exponent, window) proc multiAddBench*(EC: typedesc, numPoints: int, useBatching: bool, iters: int) = var points = newSeq[EC_ShortW_Aff[EC.F, EC.G]](numPoints) diff --git a/benchmarks/bench_eth_eip2537_subgroup_checks_impact.nim b/benchmarks/bench_eth_eip2537_subgroup_checks_impact.nim index fa414c4f..69c3748a 100644 --- a/benchmarks/bench_eth_eip2537_subgroup_checks_impact.nim +++ b/benchmarks/bench_eth_eip2537_subgroup_checks_impact.nim @@ -11,7 +11,7 @@ import constantine/named/algebras, constantine/math/arithmetic, constantine/math/extension_fields, - constantine/math/elliptic/ec_shortweierstrass_jacobian, + constantine/math/ec_shortweierstrass, # Helpers ./bench_elliptic_template diff --git a/benchmarks/bench_gt.nim b/benchmarks/bench_gt.nim index aeb4d93d..aee22e1a 100644 --- a/benchmarks/bench_gt.nim +++ b/benchmarks/bench_gt.nim @@ -49,7 +49,7 @@ proc main() = powVartimeBench(Fp12[curve], window = 4, ExpIters) separator() gtExp_sqrmul_vartimeBench(Fp12[curve], ExpIters) - gtExp_minHammingWeight_vartimeBench(Fp12[curve], ExpIters) + gtExp_jy00_vartimeBench(Fp12[curve], ExpIters) separator() gtExp_wNAF_vartimeBench(Fp12[curve], window = 2, ExpIters) gtExp_wNAF_vartimeBench(Fp12[curve], window = 3, ExpIters) diff --git a/benchmarks/bench_gt_template.nim b/benchmarks/bench_gt_template.nim index f27420a9..78d3b13c 100644 --- a/benchmarks/bench_gt_template.nim +++ b/benchmarks/bench_gt_template.nim @@ -145,23 +145,23 @@ proc gtExp_sqrmul_vartimeBench*(T: typedesc, iters: int) = bench("𝔾ₜ Exponentiation " & $exponent.bits & "-bit (cyclotomic square-multiply, vartime)", T, iters): r.gtExp_sqrmul_vartime(x, exponent) -proc gtExp_minHammingWeight_vartimeBench*(T: typedesc, iters: int) = +proc gtExp_jy00_vartimeBench*(T: typedesc, iters: int) = let x = rng.random_gt(T) let exponent = rng.random_unsafe(BigInt[Fr[T.Name].bits()]) var r {.noInit.}: T bench("𝔾ₜ Exponentiation " & $exponent.bits & "-bit (signed recoding, vartime)", T, iters): - r.gtExp_minHammingWeight_vartime(x, exponent) + r.gtExp_jy00_vartime(x, exponent) proc gtExp_wNAF_vartimeBench*(T: typedesc, window: static int, iters: int) = let x = rng.random_gt(T) let exponent = rng.random_unsafe(BigInt[Fr[T.Name].bits()]) var r {.noInit.}: T bench("𝔾ₜ Exponentiation " & $exponent.bits & "-bit (wNAF-" & $window & ", vartime)", T, iters): - r.gtExp_minHammingWeight_windowed_vartime(x, exponent, window) + r.gtExp_wNAF_vartime(x, exponent, window) proc gtExp_endo_wNAF_vartimeBench*(T: typedesc, window: static int, iters: int) = let x = rng.random_gt(T) let exponent = rng.random_unsafe(BigInt[Fr[T.Name].bits()]) var r {.noInit.}: T bench("𝔾ₜ Exponentiation " & $exponent.bits & "-bit (endomorphism, wNAF-" & $window & ", vartime)", T, iters): - r.gtExpEndo_minHammingWeight_windowed_vartime(x, exponent, window) + r.gtExpEndo_wNAF_vartime(x, exponent, window) diff --git a/benchmarks/bench_summary_bls12_377.nim b/benchmarks/bench_summary_bls12_377.nim index ab42b71f..917ef29e 100644 --- a/benchmarks/bench_summary_bls12_377.nim +++ b/benchmarks/bench_summary_bls12_377.nim @@ -6,13 +6,7 @@ # * 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/named/algebras, - constantine/math/arithmetic, - constantine/math/extension_fields, - # Helpers - ./bench_summary_template +import ./bench_summary_template # ############################################################ # diff --git a/benchmarks/bench_summary_bls12_381.nim b/benchmarks/bench_summary_bls12_381.nim index 9f75ed40..b314696d 100644 --- a/benchmarks/bench_summary_bls12_381.nim +++ b/benchmarks/bench_summary_bls12_381.nim @@ -6,13 +6,7 @@ # * 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/named/algebras, - constantine/math/arithmetic, - constantine/math/extension_fields, - # Helpers - ./bench_summary_template +import ./bench_summary_template # ############################################################ # diff --git a/benchmarks/bench_summary_bn254_nogami.nim b/benchmarks/bench_summary_bn254_nogami.nim index 45b0a561..3d6efc67 100644 --- a/benchmarks/bench_summary_bn254_nogami.nim +++ b/benchmarks/bench_summary_bn254_nogami.nim @@ -6,13 +6,7 @@ # * 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/named/algebras, - constantine/math/arithmetic, - constantine/math/extension_fields, - # Helpers - ./bench_summary_template +import ./bench_summary_template # ############################################################ # diff --git a/benchmarks/bench_summary_bn254_snarks.nim b/benchmarks/bench_summary_bn254_snarks.nim index c327deb6..d41c3f89 100644 --- a/benchmarks/bench_summary_bn254_snarks.nim +++ b/benchmarks/bench_summary_bn254_snarks.nim @@ -6,13 +6,7 @@ # * 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/named/algebras, - constantine/math/arithmetic, - constantine/math/extension_fields, - # Helpers - ./bench_summary_template +import ./bench_summary_template # ############################################################ # diff --git a/benchmarks/bench_summary_pasta.nim b/benchmarks/bench_summary_pasta.nim index c25e7d8d..048ff17d 100644 --- a/benchmarks/bench_summary_pasta.nim +++ b/benchmarks/bench_summary_pasta.nim @@ -6,13 +6,7 @@ # * 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/named/algebras, - constantine/math/arithmetic, - constantine/math/extension_fields, - # Helpers - ./bench_summary_template +import ./bench_summary_template # ############################################################ # diff --git a/benchmarks/bench_summary_template.nim b/benchmarks/bench_summary_template.nim index 978de615..4c32ec80 100644 --- a/benchmarks/bench_summary_template.nim +++ b/benchmarks/bench_summary_template.nim @@ -17,11 +17,7 @@ import constantine/platforms/abstractions, constantine/named/algebras, constantine/math/[arithmetic, extension_fields], - constantine/math/elliptic/[ - ec_shortweierstrass_affine, - ec_shortweierstrass_projective, - ec_shortweierstrass_jacobian, - ec_scalar_mul, ec_scalar_mul_vartime, ec_endomorphism_accel], + constantine/math/ec_shortweierstrass, constantine/named/zoo_subgroups, constantine/math/pairings/[ cyclotomic_subgroups, @@ -36,8 +32,9 @@ import ./bench_blueprint export - ec_shortweierstrass_projective, - ec_shortweierstrass_jacobian + algebras, + arithmetic, extension_fields, + ec_shortweierstrass export abstractions # generic sandwich on SecretBool and SecretBool in Jacobian sum export zoo_pairings # generic sandwich https://github.com/nim-lang/Nim/issues/11225 diff --git a/constantine/boolean_hypercube/multilinear_extensions.nim b/constantine/boolean_hypercube/multilinear_extensions.nim index 147001db..34fc217e 100644 --- a/constantine/boolean_hypercube/multilinear_extensions.nim +++ b/constantine/boolean_hypercube/multilinear_extensions.nim @@ -120,7 +120,7 @@ func evalMultilinearExtensionAt_BE[F]( # e ∈ {0,1}ˢ hence each factor is either: # (1-xᵢ) or xᵢ # - # See the algorithm in ec_endomorphism_accel to build + # See the algorithm in split_scalars to build # a binary lookup table for O(n) evaluations # # Algorithm: @@ -231,7 +231,7 @@ func evalMultilinearExtensionAt_LE[F]( # e ∈ {0,1}ˢ hence each factor is either: # (1-xᵢ) or xᵢ # - # See the algorithm in ec_endomorphism_accel to build + # See the algorithm in split_scalars to build # a binary lookup table for O(n) evaluations # # Algorithm: diff --git a/constantine/lowlevel_extension_fields.nim b/constantine/lowlevel_extension_fields.nim index 55455085..ad52bab9 100644 --- a/constantine/lowlevel_extension_fields.nim +++ b/constantine/lowlevel_extension_fields.nim @@ -9,7 +9,7 @@ import ./platforms/abstractions, ./named/algebras, - ./math/isogenies/frobenius, + ./math/endomorphisms/frobenius, ./math/extension_fields, ./math/io/io_extfields diff --git a/constantine/lowlevel_pairing_curves.nim b/constantine/lowlevel_pairing_curves.nim index abbcc2aa..f9273066 100644 --- a/constantine/lowlevel_pairing_curves.nim +++ b/constantine/lowlevel_pairing_curves.nim @@ -10,7 +10,7 @@ import ./platforms/abstractions, ./named/algebras, ./named/zoo_pairings, - ./math/isogenies/frobenius, + ./math/endomorphisms/frobenius, ./math/pairings/[ cyclotomic_subgroups, lines_eval, diff --git a/constantine/math/arithmetic/bigints.nim b/constantine/math/arithmetic/bigints.nim index 97bce194..458559fd 100644 --- a/constantine/math/arithmetic/bigints.nim +++ b/constantine/math/arithmetic/bigints.nim @@ -602,6 +602,10 @@ iterator recoding_l2r_signed_vartime*[bits: static int](a: BigInt[bits]): int8 = ## ## ⚠️ While the recoding is constant-time, ## usage of this recoding is intended vartime + ## + ## - Optimal Left-to-Right Binary Signed-Digit Recoding + ## Joye, Yen, 2000 + ## https://marcjoye.github.io/papers/JY00sd2r.pdf # As the caller is copy-pasted at each yield # we rework the algorithm so that we have a single yield point @@ -610,7 +614,7 @@ iterator recoding_l2r_signed_vartime*[bits: static int](a: BigInt[bits]): int8 = var bi, bi1, ri, ri1, ri2: int8 var i = bits - while true: # JY00 outputs at mots bits+1 digits + while true: # JY00 outputs at most bits+1 digits if i == bits: # We rely on compiler to hoist this branch out of the loop. ri = 0 ri1 = int8 a.bit(bits-1) diff --git a/constantine/math/ec_shortweierstrass.nim b/constantine/math/ec_shortweierstrass.nim index 4084cd49..9a0f4adf 100644 --- a/constantine/math/ec_shortweierstrass.nim +++ b/constantine/math/ec_shortweierstrass.nim @@ -17,6 +17,7 @@ import elliptic/[ ec_shortweierstrass_affine, ec_shortweierstrass_jacobian, + ec_shortweierstrass_jacobian_extended, ec_shortweierstrass_projective, ec_shortweierstrass_batch_ops, ec_scalar_mul, ec_scalar_mul_vartime, @@ -25,6 +26,7 @@ import ../named/zoo_generators export ec_shortweierstrass_affine, ec_shortweierstrass_jacobian, ec_shortweierstrass_projective, + ec_shortweierstrass_jacobian_extended, ec_shortweierstrass_batch_ops, ec_scalar_mul, ec_scalar_mul_vartime, ec_multi_scalar_mul diff --git a/constantine/math/elliptic/ec_multi_scalar_mul.nim b/constantine/math/elliptic/ec_multi_scalar_mul.nim index cee871f4..51f9e957 100644 --- a/constantine/math/elliptic/ec_multi_scalar_mul.nim +++ b/constantine/math/elliptic/ec_multi_scalar_mul.nim @@ -8,7 +8,7 @@ import constantine/named/algebras, ./ec_multi_scalar_mul_scheduler, - ./ec_endomorphism_accel, + constantine/math/endomorphisms/split_scalars, constantine/math/extension_fields, constantine/named/zoo_endomorphisms, constantine/platforms/abstractions diff --git a/constantine/math/elliptic/ec_multi_scalar_mul_parallel.nim b/constantine/math/elliptic/ec_multi_scalar_mul_parallel.nim index 4dcbaea4..be5a5c32 100644 --- a/constantine/math/elliptic/ec_multi_scalar_mul_parallel.nim +++ b/constantine/math/elliptic/ec_multi_scalar_mul_parallel.nim @@ -9,7 +9,7 @@ import constantine/named/algebras, ./ec_multi_scalar_mul_scheduler, ./ec_multi_scalar_mul, - ./ec_endomorphism_accel, + constantine/math/endomorphisms/split_scalars, constantine/math/extension_fields, constantine/named/zoo_endomorphisms, ../../threadpool/[threadpool, partitioners] diff --git a/constantine/math/elliptic/ec_scalar_mul.nim b/constantine/math/elliptic/ec_scalar_mul.nim index eaa57c6e..5619a532 100644 --- a/constantine/math/elliptic/ec_scalar_mul.nim +++ b/constantine/math/elliptic/ec_scalar_mul.nim @@ -9,16 +9,18 @@ import constantine/platforms/abstractions, constantine/named/algebras, + constantine/named/zoo_endomorphisms, constantine/math/arithmetic, constantine/math/extension_fields, constantine/math/io/io_bigints, - constantine/named/zoo_endomorphisms, - ./ec_endomorphism_accel, + constantine/math/endomorphisms/split_scalars, ./ec_shortweierstrass_affine, ./ec_shortweierstrass_projective, ./ec_shortweierstrass_jacobian, ./ec_twistededwards_affine, - ./ec_twistededwards_projective + ./ec_twistededwards_projective, + ./ec_shortweierstrass_batch_ops, + ./ec_twistededwards_batch_ops # ############################################################ # # @@ -55,6 +57,9 @@ import # Junfeng Fan,XuGuo, Elke De Mulder, Patrick Schaumont, Bart Preneel and Ingrid Verbauwhede, 2010 # https://www.esat.kuleuven.be/cosic/publications/article-1461.pdf +# Generic implementation +# -------------------------------------------------------------------------------------- + template checkScalarMulScratchspaceLen(len: int) = ## CHeck that there is a minimum of scratchspace to hold the temporaries debug: @@ -132,7 +137,6 @@ func scalarMulDoubling[EC]( return (k, bits) - func scalarMulGeneric[EC]( P: var EC, scalar: openArray[byte], @@ -232,6 +236,194 @@ func scalarMulGeneric*[EC](P: var EC, scalar: BigInt, window: static int = 5) = scalarCanonicalBE.marshal(scalar, bigEndian) # Export is constant-time P.scalarMulGeneric(scalarCanonicalBE, scratchSpace) +# Endomorphism accelerated +# -------------------------------------------------------------------------------------- + +func buildEndoLookupTable[M: static int, EC, ECaff]( + P: EC, + endomorphisms: array[M-1, EC], + lut: var array[1 shl (M-1), ECaff]) = + ## Build the lookup table from the base point P + ## and the curve endomorphism + ## + ## Note: + ## The destination parameter is last so that the compiler can infer the value of M + ## It fails with 1 shl (M-1) + + # Step 1. Create the lookup-table in alternative coordinates + var tab {.noInit.}: array[1 shl (M-1), EC] + buildEndoLookupTable( + P, endomorphisms, + tab, + groupLawAdd = sum + ) + + # Step 2. Convert to affine coordinates to benefit from mixed-addition + lut.batchAffine(tab) + +func scalarMulEndo*[scalBits; EC]( + P: var EC, + scalar: BigInt[scalBits]) {.meter.} = + ## Elliptic Curve Scalar Multiplication + ## + ## P <- [k] P + ## + ## This is a scalar multiplication accelerated by an endomorphism + ## - via the GLV (Gallant-lambert-Vanstone) decomposition on G1 + ## - via the GLS (Galbraith-Lin-Scott) decomposition on G2 + ## + ## Requires: + ## - Cofactor to be cleared + ## - 0 <= scalar < curve order + const C = P.F.Name # curve + static: doAssert scalBits <= EC.getScalarField().bits(), "Do not use endomorphism to multiply beyond the curve order" + + # 1. Compute endomorphisms + const M = when P.F is Fp: 2 + elif P.F is Fp2: 4 + else: {.error: "Unconfigured".} + const G = when EC isnot EC_ShortW_Aff|EC_ShortW_Jac|EC_ShortW_Prj: G1 + else: EC.G + + var endos {.noInit.}: array[M-1, EC] + endos.computeEndomorphisms(P) + + # 2. Decompose scalar into mini-scalars + const L = EC.getScalarField().bits().computeEndoRecodedLength(M) + var miniScalars {.noInit.}: array[M, BigInt[L]] + var negatePoints {.noInit.}: array[M, SecretBool] + miniScalars.decomposeEndo(negatePoints, scalar, EC.getScalarField().bits(), EC.getName(), G) + + # 3. Handle negative mini-scalars + # A scalar decomposition might lead to negative miniscalar. + # For proper handling it requires either: + # 1. Negating it and then negating the corresponding curve point P + # 2. Adding an extra bit to L for the recoding, which will do the right thing™ + block: + P.cneg(negatePoints[0]) + staticFor i, 1, M: + endos[i-1].cneg(negatePoints[i]) + + # 4. Precompute lookup table + var lut {.noInit.}: array[1 shl (M-1), affine(EC)] + buildEndoLookupTable(P, endos, lut) + + # 5. Recode the miniscalars + # we need the base miniscalar (that encodes the sign) + # to be odd, and this in constant-time to protect the secret least-significant bit. + let k0isOdd = miniScalars[0].isOdd() + discard miniScalars[0].cadd(One, not k0isOdd) + + var recoded: GLV_SAC[M, L] # zero-init required + recoded.nDimMultiScalarRecoding(miniScalars) + + # 6. Proceed to GLV accelerated scalar multiplication + var Q {.noInit.}: EC + var tmp {.noInit.}: affine(EC) + tmp.secretLookup(lut, recoded.getRecodedIndex(L-1)) + Q.fromAffine(tmp) + + for i in countdown(L-2, 0): + Q.double() + tmp.secretLookup(lut, recoded.getRecodedIndex(i)) + tmp.cneg(SecretBool recoded.getRecodedNegate(i)) + Q += tmp + + # Now we need to correct if the sign miniscalar was not odd + P.diff(Q, P) + P.ccopy(Q, k0isOdd) + +# Endomorphism accelerated with window of size 2 +# -------------------------------------------------------------------------------------- + +func buildEndoLookupTable_m2w2[EC, ECaff]( + lut: var array[8, ECaff], + P0, P1: EC) = + ## Build a lookup lutle for GLV with 2-dimensional decomposition + ## and window of size 2 + # Step 1. Create the lookup-table in alternative coordinates + var tab {.noInit.}: array[8, EC] + tab.buildEndoLookupTable_m2w2( + P0, P1, + groupLawAdd = sum, + groupLawSub = diff, + groupLawDouble = double, + ) + + # Step 2. Convert to affine coordinates to benefit from mixed-addition + lut.batchAffine(tab) + +func scalarMulGLV_m2w2*[scalBits; EC](P0: var EC, scalar: BigInt[scalBits]) {.meter.} = + ## Elliptic Curve Scalar Multiplication + ## + ## P <- [k] P + ## + ## This is a scalar multiplication accelerated by an endomorphism + ## via the GLV (Gallant-lambert-Vanstone) decomposition. + ## + ## For 2-dimensional decomposition with window 2 + ## + ## Requires: + ## - Cofactor to be cleared + ## - 0 <= scalar < curve order + const C = P0.F.Name # curve + static: doAssert: scalBits <= EC.getScalarField().bits() + const G = when EC isnot EC_ShortW_Aff|EC_ShortW_Jac|EC_ShortW_Prj: G1 + else: EC.G + + # 1. Compute endomorphisms + var P1 {.noInit.}: EC + P1.computeEndomorphism(P0) + + # 2. Decompose scalar into mini-scalars + const L = computeEndoWindowRecodedLength(EC.getScalarField().bits(), window = 2) + var miniScalars {.noInit.}: array[2, BigInt[L]] + var negatePoints {.noInit.}: array[2, SecretBool] + miniScalars.decomposeEndo(negatePoints, scalar, EC.getScalarField().bits(), EC.getName(), G) + + # 3. Handle negative mini-scalars + # Either negate the associated base and the scalar (in the `endomorphisms` array) + # Or use Algorithm 3 from Faz et al which can encode the sign + # in the GLV representation at the low low price of 1 bit + block: + P0.cneg(negatePoints[0]) + P1.cneg(negatePoints[1]) + + # 4. Precompute lookup table + var lut {.noInit.}: array[8, affine(EC)] + lut.buildEndoLookupTable_m2w2(P0, P1) + + # 5. Recode the miniscalars + # we need the base miniscalar (that encodes the sign) + # to be odd, and this in constant-time to protect the secret least-significant bit. + let k0isOdd = miniScalars[0].isOdd() + discard miniScalars[0].cadd(One, not k0isOdd) + + var recoded: GLV_SAC[2, L] # zero-init required + recoded.nDimMultiScalarRecoding(miniScalars) + + # 6. Proceed to GLV accelerated scalar multiplication + var Q {.noInit.}: EC + var tmp {.noInit.}: affine(EC) + var isNeg: SecretBool + + tmp.secretLookup(lut, recoded.getRecodedIndexW2((L div 2) - 1, isNeg)) + Q.fromAffine(tmp) + + for i in countdown((L div 2) - 2, 0): + Q.double() + Q.double() + tmp.secretLookup(lut, recoded.getRecodedIndexW2(i, isNeg)) + tmp.cneg(isNeg) + Q += tmp + + # Now we need to correct if the sign miniscalar was not odd + P0.diff(Q, P0) + P0.ccopy(Q, k0isOdd) + +# Public API +# -------------------------------------------------------------------------------------- + func scalarMul*[EC](P: var EC, scalar: BigInt) {.inline, meter.} = ## Elliptic Curve Scalar Multiplication ## diff --git a/constantine/math/elliptic/ec_scalar_mul_vartime.nim b/constantine/math/elliptic/ec_scalar_mul_vartime.nim index 7486d39f..84e94cbf 100644 --- a/constantine/math/elliptic/ec_scalar_mul_vartime.nim +++ b/constantine/math/elliptic/ec_scalar_mul_vartime.nim @@ -13,11 +13,11 @@ import ./ec_shortweierstrass_projective, ./ec_twistededwards_affine, ./ec_twistededwards_projective, - ./ec_endomorphism_accel, ./ec_shortweierstrass_batch_ops, ./ec_twistededwards_batch_ops, constantine/math/arithmetic, constantine/math/extension_fields, + constantine/math/endomorphisms/split_scalars, constantine/math/io/io_bigints, constantine/platforms/abstractions, constantine/math_arbitrary_precision/arithmetic/limbs_views, @@ -148,14 +148,17 @@ func scalarMul_addchain_4bit_vartime[EC](P: var EC, scalar: BigInt) {.tags:[VarT else: unreachable() -func scalarMul_minHammingWeight_vartime*[EC](P: var EC, scalar: BigInt) {.tags:[VarTime].} = +func scalarMul_jy00_vartime*[EC](P: var EC, scalar: BigInt) {.tags:[VarTime].} = ## **Variable-time** Elliptic Curve Scalar Multiplication ## ## P <- [k] P ## ## This uses an online recoding with minimum Hamming Weight - ## (which is not NAF, NAF is least-significant bit to most) - ## This MUST NOT be used with secret data. + ## bassed on Joye, Yen, 2000 recoding. + ## + ## ⚠️ While the recoding is constant-time, + ## usage of this recoding is intended vartime + ## This MUST NOT be used with secret data. ## ## This is highly VULNERABLE to timing attacks and power analysis attacks var Paff {.noinit.}: affine(EC) @@ -199,7 +202,7 @@ func accumNAF[precompSize, NafMax: static int, EC, ECaff]( elif digit < 0: P ~-= tab[-digit shr 1] -func scalarMul_minHammingWeight_windowed_vartime*[EC](P: var EC, scalar: BigInt, window: static int) {.tags:[VarTime, Alloca], meter.} = +func scalarMul_wNAF_vartime*[EC](P: var EC, scalar: BigInt, window: static int) {.tags:[VarTime, Alloca], meter.} = ## **Variable-time** Elliptic Curve Scalar Multiplication ## ## P <- [k] P @@ -236,7 +239,7 @@ func scalarMul_minHammingWeight_windowed_vartime*[EC](P: var EC, scalar: BigInt, else: isInit = P.initNAF(tab, naf, nafLen, i) -func scalarMulEndo_minHammingWeight_windowed_vartime*[scalBits: static int; EC]( +func scalarMulEndo_wNAF_vartime*[scalBits: static int; EC]( P: var EC, scalar: BigInt[scalBits], window: static int) {.tags:[VarTime, Alloca], meter.} = @@ -345,19 +348,19 @@ func scalarMul_vartime*[scalBits; EC](P: var EC, scalar: BigInt[scalBits]) {.met when scalBits >= EndomorphismThreshold: # Skip static: doAssert when multiplying by intentionally small scalars. if usedBits >= EndomorphismThreshold: when EC.F is Fp: - P.scalarMulEndo_minHammingWeight_windowed_vartime(scalar, window = 4) + P.scalarMulEndo_wNAF_vartime(scalar, window = 4) elif EC.F is Fp2: - P.scalarMulEndo_minHammingWeight_windowed_vartime(scalar, window = 3) + P.scalarMulEndo_wNAF_vartime(scalar, window = 3) else: # Curves defined on Fp^m with m > 2 {.error: "Unreachable".} return if 64 < usedBits: # With a window of 4, we precompute 2^4 = 4 points - P.scalarMul_minHammingWeight_windowed_vartime(scalar, window = 4) + P.scalarMul_wNAF_vartime(scalar, window = 4) elif 16 < usedBits: # With a window of 3, we precompute 2^1 = 2 points - P.scalarMul_minHammingWeight_windowed_vartime(scalar, window = 3) + P.scalarMul_wNAF_vartime(scalar, window = 3) elif 4 < usedBits: P.scalarMul_doubleAdd_vartime(scalar) else: diff --git a/constantine/math/isogenies/frobenius.nim b/constantine/math/endomorphisms/frobenius.nim similarity index 100% rename from constantine/math/isogenies/frobenius.nim rename to constantine/math/endomorphisms/frobenius.nim diff --git a/constantine/math/elliptic/ec_endomorphism_accel.nim b/constantine/math/endomorphisms/split_scalars.nim similarity index 67% rename from constantine/math/elliptic/ec_endomorphism_accel.nim rename to constantine/math/endomorphisms/split_scalars.nim index d4be13b5..1394da7a 100644 --- a/constantine/math/elliptic/ec_endomorphism_accel.nim +++ b/constantine/math/endomorphisms/split_scalars.nim @@ -13,15 +13,7 @@ import constantine/platforms/abstractions, constantine/named/algebras, constantine/named/zoo_endomorphisms, - constantine/math/arithmetic, - constantine/math/extension_fields, - ./ec_shortweierstrass_affine, - ./ec_shortweierstrass_projective, - ./ec_shortweierstrass_jacobian, - ./ec_twistededwards_affine, - ./ec_twistededwards_projective, - ./ec_shortweierstrass_batch_ops, - ./ec_twistededwards_batch_ops + constantine/math/arithmetic/bigints # ############################################################ # @@ -175,7 +167,7 @@ func decomposeEndo*[M, scalBits, L: static int]( type Recoded[LengthInDigits: static int] = distinct array[LengthInDigits.ceilDiv_vartime(8), byte] - GLV_SAC[M, LengthInDigits: static int] = array[M, Recoded[LengthInDigits]] + GLV_SAC*[M, LengthInDigits: static int] = array[M, Recoded[LengthInDigits]] ## GLV-Based Sign-Aligned-Column representation ## see Faz-Hernandez, 2013 ## @@ -227,7 +219,7 @@ proc `[]=`(recoding: var Recoded, let shifted = byte((value and DigitMask) shl (BitSize*(digitIdx and WordMask))) slot[] = slot[] or shifted -func nDimMultiScalarRecoding[M, L: static int]( +func nDimMultiScalarRecoding*[M, L: static int]( dst: var GLV_SAC[M, L], src: MultiScalar[M, L]) = ## This recodes N scalar for GLV multi-scalar multiplication @@ -264,12 +256,19 @@ func nDimMultiScalarRecoding[M, L: static int]( k[j].div2() k[j] += SecretWord (bji and b[0][i]) -func buildLookupTable[M: static int, EC, ECaff]( - P: EC, - endomorphisms: array[M-1, EC], - lut: var array[1 shl (M-1), ECaff]) = - ## Build the lookup table from the base point P - ## and the curve endomorphism +template buildEndoLookupTable*[M: static int, Group]( + P: Group, + endomorphisms: array[M-1, Group], + lut: var array[1 shl (M-1), Group], + groupLawAdd: untyped) = + ## Build the lookup table from the base element P + ## and the group endomorphism + ## + ## Note: + ## The destination parameter is last so that the compiler can infer the value of M + ## It fails with 1 shl (M-1) + # + # Assuming elliptic curves # # Algorithm # Compute P[u] = P0 + u0 P1 +...+ um−2 Pm−1 for all 0≤u<2^m−1, where @@ -297,103 +296,24 @@ func buildLookupTable[M: static int, EC, ECaff]( # This scheme ensures 1 addition per table entry instead of a number # of addition dependent on `u` Hamming Weight - # Step 1. Create the lookup-table in alternative coordinates - var tab {.noInit.}: array[1 shl (M-1), EC] - tab[0] = P + # Create the lookup-table in alternative coordinates + lut[0] = P for u in 1'u32 ..< 1 shl (M-1): # The recoding allows usage of 2^(n-1) table instead of the usual 2^n with NAF let msb = u.log2_vartime() # No undefined, u != 0 - tab[u].sum(tab[u.clearBit(msb)], endomorphisms[msb]) + lut[u].groupLawAdd(lut[u.clearBit(msb)], endomorphisms[msb]) - # Step 2. Convert to affine coordinates to benefit from mixed-addition - lut.batchAffine(tab) - -func tableIndex(glv: GLV_SAC, bit: int): SecretWord = +func getRecodedIndex*(glv: GLV_SAC, bit: int): SecretWord {.inline.} = ## Compose the secret table index from ## the GLV-SAC representation and the "bit" accessed staticFor i, 1, GLV_SAC.M: result = result or SecretWord((glv[i][bit] and 1) shl (i-1)) -func secretLookup[T](dst: var T, table: openArray[T], index: SecretWord) = - ## Load a table[index] into `dst` - ## This is constant-time, whatever the `index`, its value is not leaked - ## This is also protected against cache-timing attack by always scanning the whole table - for i in 0 ..< table.len: - let selector = SecretWord(i) == index - dst.ccopy(table[i], selector) - -func scalarMulEndo*[scalBits; EC]( - P: var EC, - scalar: BigInt[scalBits]) {.meter.} = - ## Elliptic Curve Scalar Multiplication - ## - ## P <- [k] P - ## - ## This is a scalar multiplication accelerated by an endomorphism - ## - via the GLV (Gallant-lambert-Vanstone) decomposition on G1 - ## - via the GLS (Galbraith-Lin-Scott) decomposition on G2 - ## - ## Requires: - ## - Cofactor to be cleared - ## - 0 <= scalar < curve order - mixin affine - const C = P.F.Name # curve - static: doAssert scalBits <= EC.getScalarField().bits(), "Do not use endomorphism to multiply beyond the curve order" - - # 1. Compute endomorphisms - const M = when P.F is Fp: 2 - elif P.F is Fp2: 4 - else: {.error: "Unconfigured".} - const G = when EC isnot EC_ShortW_Aff|EC_ShortW_Jac|EC_ShortW_Prj: G1 - else: EC.G - - var endos {.noInit.}: array[M-1, EC] - endos.computeEndomorphisms(P) - - # 2. Decompose scalar into mini-scalars - const L = EC.getScalarField().bits().ceilDiv_vartime(M) + 1 - var miniScalars {.noInit.}: array[M, BigInt[L]] - var negatePoints {.noInit.}: array[M, SecretBool] - miniScalars.decomposeEndo(negatePoints, scalar, EC.getScalarField().bits(), EC.getName(), G) - - # 3. Handle negative mini-scalars - # A scalar decomposition might lead to negative miniscalar. - # For proper handling it requires either: - # 1. Negating it and then negating the corresponding curve point P - # 2. Adding an extra bit to L for the recoding, which will do the right thing™ - block: - P.cneg(negatePoints[0]) - staticFor i, 1, M: - endos[i-1].cneg(negatePoints[i]) - - # 4. Precompute lookup table - var lut {.noInit.}: array[1 shl (M-1), affine(EC)] - buildLookupTable(P, endos, lut) - - # 5. Recode the miniscalars - # we need the base miniscalar (that encodes the sign) - # to be odd, and this in constant-time to protect the secret least-significant bit. - let k0isOdd = miniScalars[0].isOdd() - discard miniScalars[0].cadd(One, not k0isOdd) - - var recoded: GLV_SAC[M, L] # zero-init required - recoded.nDimMultiScalarRecoding(miniScalars) - - # 6. Proceed to GLV accelerated scalar multiplication - var Q {.noInit.}: EC - var tmp {.noInit.}: affine(EC) - tmp.secretLookup(lut, recoded.tableIndex(L-1)) - Q.fromAffine(tmp) - - for i in countdown(L-2, 0): - Q.double() - tmp.secretLookup(lut, recoded.tableIndex(i)) - tmp.cneg(SecretBool recoded[0][i]) - Q += tmp - - # Now we need to correct if the sign miniscalar was not odd - P.diff(Q, P) - P.ccopy(Q, k0isOdd) +func getRecodedNegate*(glv: GLV_SAC, bit: int): SecretBool {.inline.} = + SecretBool glv[0][bit] + +func computeEndoRecodedLength*(bits, decomposition_dimension: int): int = + bits.ceilDiv_vartime(decomposition_dimension) + 1 # Windowed GLV # ---------------------------------------------------------------- @@ -427,39 +347,34 @@ func scalarMulEndo*[scalBits; EC]( # - 0t10 -> 0b10 is 2 # - 0t11 -> 0b11 is 3 -func buildLookupTable_m2w2[EC, Ecaff]( - P0: EC, - P1: EC, - lut: var array[8, Ecaff]) = - ## Build a lookup table for GLV with 2-dimensional decomposition +template buildEndoLookupTable_m2w2*[Group]( + lut: var array[8, Group], + P0, P1: Group, + groupLawAdd, groupLawSub, groupLawDouble: untyped) = + ## Build a lookup lutle for GLV with 2-dimensional decomposition ## and window of size 2 - # Step 1. Create the lookup-table in alternative coordinates - var tab {.noInit.}: array[8, EC] - + # Create the lookup-lutle in alternative coordinates # with [k0, k1] the mini-scalars with digits of size 2-bit # # 4 = 0b100 - encodes [0b01, 0b00] ≡ P0 - tab[4] = P0 + lut[4] = P0 # 5 = 0b101 - encodes [0b01, 0b01] ≡ P0 - P1 - tab[5].diff(tab[4], P1) + lut[5].groupLawSub(lut[4], P1) # 7 = 0b111 - encodes [0b01, 0b11] ≡ P0 + P1 - tab[7].sum(tab[4], P1) + lut[7].groupLawAdd(lut[4], P1) # 6 = 0b110 - encodes [0b01, 0b10] ≡ P0 + 2P1 - tab[6].sum(tab[7], P1) + lut[6].groupLawAdd(lut[7], P1) # 0 = 0b000 - encodes [0b00, 0b00] ≡ 3P0 - tab[0].double(tab[4]) - tab[0] += tab[4] + lut[0].groupLawDouble(lut[4]) + lut[0].groupLawAdd(lut[0], lut[4]) # 1 = 0b001 - encodes [0b00, 0b01] ≡ 3P0 + P1 - tab[1].sum(tab[0], P1) + lut[1].groupLawAdd(lut[0], P1) # 2 = 0b010 - encodes [0b00, 0b10] ≡ 3P0 + 2P1 - tab[2].sum(tab[1], P1) + lut[2].groupLawAdd(lut[1], P1) # 3 = 0b011 - encodes [0b00, 0b11] ≡ 3P0 + 3P1 - tab[3].sum(tab[2], P1) - - # Step 2. Convert to affine coordinates to benefit from mixed-addition - lut.batchAffine(tab) + lut[3].groupLawAdd(lut[2], P1) func w2Get(recoding: Recoded, digitIdx: int): uint8 {.inline.}= @@ -481,7 +396,7 @@ func w2Get(recoding: Recoded, let recoded = slot shr (wBitSize*(digitIdx and wWordMask)) and wDigitMask return recoded -func w2TableIndex(glv: GLV_SAC, bit2: int, isNeg: var SecretBool): SecretWord {.inline.} = +func getRecodedIndexW2*(glv: GLV_SAC, bit2: int, isNeg: var SecretBool): SecretWord {.inline.} = ## Compose the secret table index from ## the windowed of size 2 GLV-SAC representation and the "bit" accessed @@ -494,78 +409,9 @@ func w2TableIndex(glv: GLV_SAC, bit2: int, isNeg: var SecretBool): SecretWord {. let parity = (k0 shr 1) xor (k0 and 1) result = SecretWord((parity shl 2) or k1) -func computeRecodedLength(bitWidth, window: int): int = +func computeEndoWindowRecodedLength*(bitWidth, window: int): int = # Strangely in the paper this doesn't depend # "m", the GLV decomposition dimension. # lw = ⌈log2 r/w⌉+1 (optionally a second "+1" to handle negative mini scalars) let lw = bitWidth.ceilDiv_vartime(window) + 1 result = (lw mod window) + lw - -func scalarMulGLV_m2w2*[scalBits; EC](P0: var EC, scalar: BigInt[scalBits]) {.meter.} = - ## Elliptic Curve Scalar Multiplication - ## - ## P <- [k] P - ## - ## This is a scalar multiplication accelerated by an endomorphism - ## via the GLV (Gallant-lambert-Vanstone) decomposition. - ## - ## For 2-dimensional decomposition with window 2 - ## - ## Requires: - ## - Cofactor to be cleared - ## - 0 <= scalar < curve order - mixin affine - const C = P0.F.Name # curve - static: doAssert: scalBits <= EC.getScalarField().bits() - const G = when EC isnot EC_ShortW_Aff|EC_ShortW_Jac|EC_ShortW_Prj: G1 - else: EC.G - - # 1. Compute endomorphisms - var P1 {.noInit.}: EC - P1.computeEndomorphism(P0) - - # 2. Decompose scalar into mini-scalars - const L = computeRecodedLength(EC.getScalarField().bits(), 2) - var miniScalars {.noInit.}: array[2, BigInt[L]] - var negatePoints {.noInit.}: array[2, SecretBool] - miniScalars.decomposeEndo(negatePoints, scalar, EC.getScalarField().bits(), EC.getName(), G) - - # 3. Handle negative mini-scalars - # Either negate the associated base and the scalar (in the `endomorphisms` array) - # Or use Algorithm 3 from Faz et al which can encode the sign - # in the GLV representation at the low low price of 1 bit - block: - P0.cneg(negatePoints[0]) - P1.cneg(negatePoints[1]) - - # 4. Precompute lookup table - var lut {.noInit.}: array[8, affine(EC)] - buildLookupTable_m2w2(P0, P1, lut) - - # 5. Recode the miniscalars - # we need the base miniscalar (that encodes the sign) - # to be odd, and this in constant-time to protect the secret least-significant bit. - let k0isOdd = miniScalars[0].isOdd() - discard miniScalars[0].cadd(One, not k0isOdd) - - var recoded: GLV_SAC[2, L] # zero-init required - recoded.nDimMultiScalarRecoding(miniScalars) - - # 6. Proceed to GLV accelerated scalar multiplication - var Q {.noInit.}: EC - var tmp {.noInit.}: affine(EC) - var isNeg: SecretBool - - tmp.secretLookup(lut, recoded.w2TableIndex((L div 2) - 1, isNeg)) - Q.fromAffine(tmp) - - for i in countdown((L div 2) - 2, 0): - Q.double() - Q.double() - tmp.secretLookup(lut, recoded.w2TableIndex(i, isNeg)) - tmp.cneg(isNeg) - Q += tmp - - # Now we need to correct if the sign miniscalar was not odd - P0.diff(Q, P0) - P0.ccopy(Q, k0isOdd) diff --git a/constantine/math/isogenies/README.md b/constantine/math/isogenies/README.md deleted file mode 100644 index 0a5b8806..00000000 --- a/constantine/math/isogenies/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Isogeny-based Cryptography - -This folder will hold the implementations of isogeny-based cryptography. - -The initial focus will be the isogeny maps necessary to implement -hashing to elliptic curve - -## References - -### Normative references - -- Hashing to Elliptic Curve\ - (Draft, expires May 5, 2020)\ - https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-05 \ - https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve diff --git a/constantine/math/pairings/cyclotomic_subgroups.nim b/constantine/math/pairings/cyclotomic_subgroups.nim index 63d4514c..f04714c9 100644 --- a/constantine/math/pairings/cyclotomic_subgroups.nim +++ b/constantine/math/pairings/cyclotomic_subgroups.nim @@ -11,7 +11,7 @@ import constantine/named/algebras, constantine/math/arithmetic, constantine/math/extension_fields, - constantine/math/isogenies/frobenius + constantine/math/endomorphisms/frobenius # No exceptions allowed {.push raises: [].} diff --git a/constantine/math/pairings/gt_exponentiations_vartime.nim b/constantine/math/pairings/gt_exponentiations_vartime.nim index cbc9fb31..3775b797 100644 --- a/constantine/math/pairings/gt_exponentiations_vartime.nim +++ b/constantine/math/pairings/gt_exponentiations_vartime.nim @@ -8,9 +8,9 @@ import # Internals - constantine/math/elliptic/ec_endomorphism_accel, constantine/math/arithmetic, constantine/math/extension_fields, + constantine/math/endomorphisms/split_scalars, constantine/math/io/io_bigints, constantine/platforms/abstractions, constantine/math_arbitrary_precision/arithmetic/limbs_views, @@ -146,14 +146,17 @@ func gtExp_addchain_4bit_vartime[Gt: ExtensionField](r: var Gt, a: Gt, scalar: B else: unreachable() -func gtExp_minHammingWeight_vartime*[Gt: ExtensionField](r: var Gt, a: Gt, scalar: BigInt) {.tags:[VarTime].} = +func gtExp_jy00_vartime*[Gt: ExtensionField](r: var Gt, a: Gt, scalar: BigInt) {.tags:[VarTime].} = ## **Variable-time** Exponentiation in 𝔾ₜ ## ## r <- aᵏ ## ## This uses an online recoding with minimum Hamming Weight - ## (which is not NAF, NAF is least-significant bit to most) - ## This MUST NOT be used with secret data. + ## bassed on Joye, Yen, 2000 recoding. + ## + ## ⚠️ While the recoding is constant-time, + ## usage of this recoding is intended vartime + ## This MUST NOT be used with secret data. ## ## This is highly VULNERABLE to timing attacks and power analysis attacks let a {.noInit.} = a # Avoid aliasing issues @@ -199,7 +202,7 @@ func accumNAF[precompSize, NafMax: static int, Gt: ExtensionField]( neg.cyclotomic_inv(tab[-digit shr 1]) acc *= neg -func gtExp_minHammingWeight_windowed_vartime*[Gt: ExtensionField]( +func gtExp_wNAF_vartime*[Gt: ExtensionField]( r: var Gt, a: Gt, scalar: BigInt, window: static int) {.tags:[VarTime], meter.} = ## **Variable-time** Exponentiation in 𝔾ₜ ## @@ -233,7 +236,7 @@ func gtExp_minHammingWeight_windowed_vartime*[Gt: ExtensionField]( else: isInit = r.initNAF(tab, naf, nafLen, i) -func gtExpEndo_minHammingWeight_windowed_vartime*[Gt: ExtensionField, scalBits: static int]( +func gtExpEndo_wNAF_vartime*[Gt: ExtensionField, scalBits: static int]( r: var Gt, a: Gt, scalar: BigInt[scalBits], window: static int) {.tags:[VarTime], meter.} = ## Endomorphism accelerated **Variable-time** Exponentiation in 𝔾ₜ ## diff --git a/constantine/math/pairings/miller_loops.nim b/constantine/math/pairings/miller_loops.nim index 0d31362f..68c4c346 100644 --- a/constantine/math/pairings/miller_loops.nim +++ b/constantine/math/pairings/miller_loops.nim @@ -14,7 +14,7 @@ import ec_shortweierstrass_projective ], constantine/math/arithmetic, - constantine/math/isogenies/frobenius, + constantine/math/endomorphisms/frobenius, ./lines_eval # No exceptions allowed diff --git a/constantine/math/pairings/pairings_bls12.nim b/constantine/math/pairings/pairings_bls12.nim index d1026433..fa3168f9 100644 --- a/constantine/math/pairings/pairings_bls12.nim +++ b/constantine/math/pairings/pairings_bls12.nim @@ -14,7 +14,7 @@ import ec_shortweierstrass_affine, ec_shortweierstrass_projective ], - constantine/math/isogenies/frobenius, + constantine/math/endomorphisms/frobenius, constantine/named/zoo_pairings, constantine/math/arithmetic, ./cyclotomic_subgroups, diff --git a/constantine/math/pairings/pairings_bn.nim b/constantine/math/pairings/pairings_bn.nim index 2c7f479e..0fd85fdd 100644 --- a/constantine/math/pairings/pairings_bn.nim +++ b/constantine/math/pairings/pairings_bn.nim @@ -14,7 +14,7 @@ import ec_shortweierstrass_affine, ec_shortweierstrass_projective ], - constantine/math/isogenies/frobenius, + constantine/math/endomorphisms/frobenius, constantine/named/zoo_pairings, ./cyclotomic_subgroups, ./miller_loops diff --git a/constantine/math/pairings/pairings_bw6_761.nim b/constantine/math/pairings/pairings_bw6_761.nim index 110f9478..7c03a986 100644 --- a/constantine/math/pairings/pairings_bw6_761.nim +++ b/constantine/math/pairings/pairings_bw6_761.nim @@ -14,7 +14,7 @@ import ec_shortweierstrass_affine, ec_shortweierstrass_projective ], - constantine/math/isogenies/frobenius, + constantine/math/endomorphisms/frobenius, constantine/named/zoo_pairings, ./lines_eval, ./miller_loops diff --git a/constantine/named/constants/bls12_377_pairings.nim b/constantine/named/constants/bls12_377_pairings.nim index ccebc3cc..dae61c93 100644 --- a/constantine/named/constants/bls12_377_pairings.nim +++ b/constantine/named/constants/bls12_377_pairings.nim @@ -13,7 +13,7 @@ import constantine/math/extension_fields, constantine/math/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective], constantine/math/pairings/[cyclotomic_subgroups, miller_loops], - constantine/math/isogenies/frobenius + constantine/math/endomorphisms/frobenius # Slow generic implementation # ------------------------------------------------------------ diff --git a/constantine/named/constants/bls12_377_subgroups.nim b/constantine/named/constants/bls12_377_subgroups.nim index 2eba310a..827da898 100644 --- a/constantine/named/constants/bls12_377_subgroups.nim +++ b/constantine/named/constants/bls12_377_subgroups.nim @@ -15,7 +15,7 @@ import constantine/math/ec_shortweierstrass, constantine/math/elliptic/ec_scalar_mul, constantine/math/io/io_bigints, - constantine/math/isogenies/frobenius, + constantine/math/endomorphisms/frobenius, constantine/named/zoo_endomorphisms func pow_bls12_377_abs_x[ECP: EC_ShortW[Fp[BLS12_377], G1] or diff --git a/constantine/named/constants/bls12_381_pairings.nim b/constantine/named/constants/bls12_381_pairings.nim index 5e5ef564..3f85cd9e 100644 --- a/constantine/named/constants/bls12_381_pairings.nim +++ b/constantine/named/constants/bls12_381_pairings.nim @@ -13,7 +13,7 @@ import constantine/math/extension_fields, constantine/math/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective], constantine/math/pairings/[cyclotomic_subgroups, miller_loops], - constantine/math/isogenies/frobenius + constantine/math/endomorphisms/frobenius # Slow generic implementation # ------------------------------------------------------------ diff --git a/constantine/named/constants/bls12_381_subgroups.nim b/constantine/named/constants/bls12_381_subgroups.nim index 9b07b8e1..02baeece 100644 --- a/constantine/named/constants/bls12_381_subgroups.nim +++ b/constantine/named/constants/bls12_381_subgroups.nim @@ -15,7 +15,7 @@ import constantine/math/ec_shortweierstrass, constantine/math/elliptic/ec_scalar_mul, constantine/math/io/io_bigints, - constantine/math/isogenies/frobenius, + constantine/math/endomorphisms/frobenius, constantine/named/zoo_endomorphisms func pow_bls12_381_abs_x[ECP: EC_ShortW[Fp[BLS12_381], G1] or diff --git a/constantine/named/constants/bn254_nogami_pairings.nim b/constantine/named/constants/bn254_nogami_pairings.nim index 68953880..6b3d8fba 100644 --- a/constantine/named/constants/bn254_nogami_pairings.nim +++ b/constantine/named/constants/bn254_nogami_pairings.nim @@ -13,7 +13,7 @@ import constantine/math/extension_fields, constantine/math/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective], constantine/math/pairings/[cyclotomic_subgroups, miller_loops], - constantine/math/isogenies/frobenius + constantine/math/endomorphisms/frobenius # Slow generic implementation # ------------------------------------------------------------ diff --git a/constantine/named/constants/bn254_nogami_subgroups.nim b/constantine/named/constants/bn254_nogami_subgroups.nim index 7ce7fa63..afbe0a66 100644 --- a/constantine/named/constants/bn254_nogami_subgroups.nim +++ b/constantine/named/constants/bn254_nogami_subgroups.nim @@ -15,7 +15,7 @@ import constantine/math/ec_shortweierstrass, constantine/math/elliptic/ec_scalar_mul, constantine/math/io/io_bigints, - constantine/math/isogenies/frobenius + constantine/math/endomorphisms/frobenius func pow_BN254_Nogami_abs_u*[ECP: EC_ShortW[Fp[BN254_Nogami], G1] or EC_ShortW[Fp2[BN254_Nogami], G2]]( diff --git a/constantine/named/constants/bn254_snarks_pairings.nim b/constantine/named/constants/bn254_snarks_pairings.nim index 14ec1a71..d38a1f95 100644 --- a/constantine/named/constants/bn254_snarks_pairings.nim +++ b/constantine/named/constants/bn254_snarks_pairings.nim @@ -12,7 +12,7 @@ import constantine/math/io/io_bigints, constantine/math/extension_fields, constantine/math/pairings/cyclotomic_subgroups, - constantine/math/isogenies/frobenius + constantine/math/endomorphisms/frobenius # Slow generic implementation # ------------------------------------------------------------ diff --git a/constantine/named/constants/bn254_snarks_subgroups.nim b/constantine/named/constants/bn254_snarks_subgroups.nim index bf8f954b..a0dbc6b9 100644 --- a/constantine/named/constants/bn254_snarks_subgroups.nim +++ b/constantine/named/constants/bn254_snarks_subgroups.nim @@ -15,7 +15,7 @@ import constantine/math/ec_shortweierstrass, constantine/math/elliptic/ec_scalar_mul, constantine/math/io/io_bigints, - constantine/math/isogenies/frobenius + constantine/math/endomorphisms/frobenius func pow_bn254_snarks_abs_u*[ECP: EC_ShortW[Fp[BN254_Snarks], G1] or EC_ShortW[Fp2[BN254_Snarks], G2]]( diff --git a/constantine/named/constants/bw6_761_pairings.nim b/constantine/named/constants/bw6_761_pairings.nim index 6c4da7ed..d459c9dc 100644 --- a/constantine/named/constants/bw6_761_pairings.nim +++ b/constantine/named/constants/bw6_761_pairings.nim @@ -12,7 +12,7 @@ import constantine/math/io/io_bigints, constantine/math/extension_fields, constantine/math/pairings/cyclotomic_subgroups, - constantine/math/isogenies/frobenius + constantine/math/endomorphisms/frobenius # Slow generic implementation # ------------------------------------------------------------ diff --git a/constantine/named/constants/bw6_761_subgroups.nim b/constantine/named/constants/bw6_761_subgroups.nim index 30cb0696..62f122d4 100644 --- a/constantine/named/constants/bw6_761_subgroups.nim +++ b/constantine/named/constants/bw6_761_subgroups.nim @@ -15,7 +15,7 @@ import constantine/math/ec_shortweierstrass, constantine/math/elliptic/ec_scalar_mul, constantine/math/io/io_bigints - # constantine/math/isogenies/frobenius + # constantine/math/endomorphisms/frobenius # ############################################################ # diff --git a/constantine/named/zoo_endomorphisms.nim b/constantine/named/zoo_endomorphisms.nim index f49fd365..72805b57 100644 --- a/constantine/named/zoo_endomorphisms.nim +++ b/constantine/named/zoo_endomorphisms.nim @@ -10,7 +10,7 @@ import std/macros, constantine/platforms/abstractions, constantine/math/extension_fields, - constantine/math/isogenies/frobenius, + constantine/math/endomorphisms/frobenius, constantine/math/elliptic/[ ec_shortweierstrass_affine, ec_shortweierstrass_projective, @@ -30,6 +30,8 @@ import ./constants/bandersnatch_endomorphisms, ./constants/banderwagon_endomorphisms +export Subgroup + {.experimental: "dynamicBindSym".} macro dispatch(Name: static Algebra, tag: static string, G: static string): untyped = diff --git a/constantine/platforms/abstractions.nim b/constantine/platforms/abstractions.nim index 4d5ebc83..99301a4d 100644 --- a/constantine/platforms/abstractions.nim +++ b/constantine/platforms/abstractions.nim @@ -95,6 +95,15 @@ func setOne*(a: var openArray[SecretWord]){.inline.} = for i in 1 ..< a.len: a[i] = Zero +func secretLookup*[T](dst: var T, table: openArray[T], index: SecretWord) = + ## Load a table[index] into `dst` + ## This is constant-time, whatever the `index`, its value is not leaked + ## This is also protected against cache-timing attack by always scanning the whole table + mixin ccopy + for i in 0 ..< table.len: + let selector = SecretWord(i) == index + dst.ccopy(table[i], selector) + debug: # Don't allow printing secret words by default func toHex*(a: SecretWord): string = const hexChars = "0123456789abcdef" diff --git a/metering/eip2537.md b/metering/eip2537.md index 96caee89..6450b4b9 100644 --- a/metering/eip2537.md +++ b/metering/eip2537.md @@ -196,7 +196,7 @@ The CPU Cycle Count is indicative only. It cannot be used to compare across syst | sum_vartime*(r: var ECP_ShortW_Jac[F, G]; p, q: ECP_Shor ... | 6 | 418205.897 | 14.347 | 2.391 | 46.728 | 7.788 | | mixedSum_vartime*(r: var ECP_ShortW_Jac[F, G]; p: ECP_ShortW ... | 49 | 558188.280 | 87.784 | 1.792 | 284.097 | 5.798 | | batchAffine*(affs: ptr UncheckedArray[ECP_ShortW_Aff[F, ... | 1 | 154750.851 | 6.462 | 6.462 | 21.186 | 21.186 | -| scalarMulEndo_minHammingWeight_windowed_vartime*(P: var ... | 1 | 2937.910 | 340.378 | 340.378 | 1121.010 | 1121.010 | +| scalarMulEndo_wNAF_vartime*(P: var ... | 1 | 2937.910 | 340.378 | 340.378 | 1121.010 | 1121.010 | | scalarMul_vartime*(P: var EC; scalar: BigInt[scalBits]) | 1 | 2937.220 | 340.458 | 340.458 | 1121.274 | 1121.274 | @@ -223,7 +223,7 @@ The CPU Cycle Count is indicative only. It cannot be used to compare across syst | sum_vartime*(r: var ECP_ShortW_Prj[F, G]; p, q: ECP_Shor ... | 6 | 472255.018 | 12.705 | 2.118 | 41.217 | 6.869 | | mixedSum_vartime*(r: var ECP_ShortW_Prj[F, G]; p: ECP_ShortW ... | 47 | 553990.500 | 84.839 | 1.805 | 274.428 | 5.839 | | batchAffine*(affs: ptr UncheckedArray[ECP_ShortW_Aff[F, ... | 1 | 196078.431 | 5.100 | 5.100 | 16.698 | 16.698 | -| scalarMulEndo_minHammingWeight_windowed_vartime*(P: var ... | 1 | 3072.385 | 325.480 | 325.480 | 1071.939 | 1071.939 | +| scalarMulEndo_wNAF_vartime*(P: var ... | 1 | 3072.385 | 325.480 | 325.480 | 1071.939 | 1071.939 | | scalarMul_vartime*(P: var EC; scalar: BigInt[scalBits]) | 1 | 3071.630 | 325.560 | 325.560 | 1072.203 | 1072.203 | @@ -350,7 +350,7 @@ The CPU Cycle Count is indicative only. It cannot be used to compare across syst | sum_vartime*(r: var ECP_ShortW_Jac[F, G]; p, q: ECP_Shor ... | 4 | 220337.116 | 18.154 | 4.538 | 59.367 | 14.842 | | mixedSum_vartime*(r: var ECP_ShortW_Jac[F, G]; p: ECP_ShortW ... | 69 | 296900.616 | 232.401 | 3.368 | 758.835 | 10.998 | | batchAffine*(affs: ptr UncheckedArray[ECP_ShortW_Aff[F, ... | 1 | 73389.109 | 13.626 | 13.626 | 44.748 | 44.748 | -| scalarMulEndo_minHammingWeight_windowed_vartime*(P: var ... | 1 | 1933.436 | 517.214 | 517.214 | 1703.460 | 1703.460 | +| scalarMulEndo_wNAF_vartime*(P: var ... | 1 | 1933.436 | 517.214 | 517.214 | 1703.460 | 1703.460 | | scalarMul_vartime*(P: var EC; scalar: BigInt[scalBits]) | 1 | 1933.137 | 517.294 | 517.294 | 1703.691 | 1703.691 | @@ -377,7 +377,7 @@ The CPU Cycle Count is indicative only. It cannot be used to compare across syst | sum_vartime*(r: var ECP_ShortW_Prj[F, G]; p, q: ECP_Shor ... | 4 | 247662.683 | 16.151 | 4.038 | 52.734 | 13.184 | | mixedSum_vartime*(r: var ECP_ShortW_Prj[F, G]; p: ECP_ShortW ... | 62 | 300657.081 | 206.215 | 3.326 | 672.903 | 10.853 | | batchAffine*(affs: ptr UncheckedArray[ECP_ShortW_Aff[F, ... | 1 | 99611.515 | 10.039 | 10.039 | 32.967 | 32.967 | -| scalarMulEndo_minHammingWeight_windowed_vartime*(P: var ... | 1 | 1918.421 | 521.262 | 521.262 | 1716.825 | 1716.825 | +| scalarMulEndo_wNAF_vartime*(P: var ... | 1 | 1918.421 | 521.262 | 521.262 | 1716.825 | 1716.825 | | scalarMul_vartime*(P: var EC; scalar: BigInt[scalBits]) | 1 | 1918.127 | 521.342 | 521.342 | 1717.056 | 1717.056 | diff --git a/research/endomorphisms/glv.nim b/research/endomorphisms/glv.nim index c4f05e0d..82326391 100644 --- a/research/endomorphisms/glv.nim +++ b/research/endomorphisms/glv.nim @@ -6,7 +6,7 @@ # Armando Faz-Hernández, Patrick Longa, Ana H. Sánchez, 2013 # https://eprint.iacr.org/2013/158.pdf -import constantine/math/elliptic/ec_endomorphism_accel {.all.}, +import constantine/math/endomorphisms/split_scalars {.all.}, constantine/platforms/abstractions, constantine/math/io/io_bigints, constantine/math/arithmetic @@ -218,7 +218,7 @@ proc mainFullMulWindowed() = const M = 2 # GLS-2 decomposition const miniBitwidth = 8 # Bitwidth of the miniscalars resulting from scalar decomposition const W = 2 # Window - const L = computeRecodedLength(miniBitwidth, W) + const L = computeEndoWindowRecodedLength(miniBitwidth, W) var k: MultiScalar[M, L] var kRecoded: GLV_SAC[M, L] diff --git a/tests/math_elliptic_curves/t_ec_frobenius.nim b/tests/math_elliptic_curves/t_ec_frobenius.nim index a17e0bd3..655a8a3d 100644 --- a/tests/math_elliptic_curves/t_ec_frobenius.nim +++ b/tests/math_elliptic_curves/t_ec_frobenius.nim @@ -16,7 +16,7 @@ import constantine/math/[arithmetic, extension_fields], constantine/math/io/[io_bigints, io_ec], constantine/math/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective, ec_scalar_mul], - constantine/math/isogenies/frobenius, + constantine/math/endomorphisms/frobenius, # Tests helpers/prng_unsafe, ./t_ec_template diff --git a/tests/math_elliptic_curves/t_ec_sage_bls12_377.nim b/tests/math_elliptic_curves/t_ec_sage_bls12_377.nim index 8971f33a..9c310f9c 100644 --- a/tests/math_elliptic_curves/t_ec_sage_bls12_377.nim +++ b/tests/math_elliptic_curves/t_ec_sage_bls12_377.nim @@ -10,8 +10,7 @@ import # Internals constantine/named/algebras, constantine/math/extension_fields, - constantine/math/elliptic/ec_shortweierstrass_jacobian, - constantine/math/elliptic/ec_shortweierstrass_projective, + constantine/math/ec_shortweierstrass, # Test utilities ./t_ec_sage_template diff --git a/tests/math_elliptic_curves/t_ec_sage_bls12_381.nim b/tests/math_elliptic_curves/t_ec_sage_bls12_381.nim index 09e2c965..3a095b48 100644 --- a/tests/math_elliptic_curves/t_ec_sage_bls12_381.nim +++ b/tests/math_elliptic_curves/t_ec_sage_bls12_381.nim @@ -10,8 +10,7 @@ import # Internals constantine/named/algebras, constantine/math/extension_fields, - constantine/math/elliptic/ec_shortweierstrass_jacobian, - constantine/math/elliptic/ec_shortweierstrass_projective, + constantine/math/ec_shortweierstrass, # Test utilities ./t_ec_sage_template diff --git a/tests/math_elliptic_curves/t_ec_sage_bn254_nogami.nim b/tests/math_elliptic_curves/t_ec_sage_bn254_nogami.nim index 1d0217fa..7552e421 100644 --- a/tests/math_elliptic_curves/t_ec_sage_bn254_nogami.nim +++ b/tests/math_elliptic_curves/t_ec_sage_bn254_nogami.nim @@ -10,8 +10,7 @@ import # Internals constantine/named/algebras, constantine/math/extension_fields, - constantine/math/elliptic/ec_shortweierstrass_jacobian, - constantine/math/elliptic/ec_shortweierstrass_projective, + constantine/math/ec_shortweierstrass, # Test utilities ./t_ec_sage_template diff --git a/tests/math_elliptic_curves/t_ec_sage_bn254_snarks.nim b/tests/math_elliptic_curves/t_ec_sage_bn254_snarks.nim index d56c66c4..b893ea39 100644 --- a/tests/math_elliptic_curves/t_ec_sage_bn254_snarks.nim +++ b/tests/math_elliptic_curves/t_ec_sage_bn254_snarks.nim @@ -10,8 +10,7 @@ import # Internals constantine/named/algebras, constantine/math/extension_fields, - constantine/math/elliptic/ec_shortweierstrass_jacobian, - constantine/math/elliptic/ec_shortweierstrass_projective, + constantine/math/ec_shortweierstrass, # Test utilities ./t_ec_sage_template diff --git a/tests/math_elliptic_curves/t_ec_sage_bw6_761_g1.nim b/tests/math_elliptic_curves/t_ec_sage_bw6_761_g1.nim index 034084bc..9509369d 100644 --- a/tests/math_elliptic_curves/t_ec_sage_bw6_761_g1.nim +++ b/tests/math_elliptic_curves/t_ec_sage_bw6_761_g1.nim @@ -9,8 +9,7 @@ import # Internals constantine/named/algebras, - constantine/math/elliptic/ec_shortweierstrass_jacobian, - constantine/math/elliptic/ec_shortweierstrass_projective, + constantine/math/ec_shortweierstrass, # Test utilities ./t_ec_sage_template diff --git a/tests/math_elliptic_curves/t_ec_sage_bw6_761_g2.nim b/tests/math_elliptic_curves/t_ec_sage_bw6_761_g2.nim index 2365a4f8..faf284e7 100644 --- a/tests/math_elliptic_curves/t_ec_sage_bw6_761_g2.nim +++ b/tests/math_elliptic_curves/t_ec_sage_bw6_761_g2.nim @@ -9,8 +9,7 @@ import # Internals constantine/named/algebras, - constantine/math/elliptic/ec_shortweierstrass_jacobian, - constantine/math/elliptic/ec_shortweierstrass_projective, + constantine/math/ec_shortweierstrass, # Test utilities ./t_ec_sage_template diff --git a/tests/math_elliptic_curves/t_ec_sage_pallas.nim b/tests/math_elliptic_curves/t_ec_sage_pallas.nim index 1632d587..b1a35c12 100644 --- a/tests/math_elliptic_curves/t_ec_sage_pallas.nim +++ b/tests/math_elliptic_curves/t_ec_sage_pallas.nim @@ -10,8 +10,7 @@ import # Internals constantine/named/algebras, constantine/math/extension_fields, - constantine/math/elliptic/ec_shortweierstrass_jacobian, - constantine/math/elliptic/ec_shortweierstrass_projective, + constantine/math/ec_shortweierstrass, # Test utilities ./t_ec_sage_template diff --git a/tests/math_elliptic_curves/t_ec_sage_template.nim b/tests/math_elliptic_curves/t_ec_sage_template.nim index 4753738f..7a8f2a55 100644 --- a/tests/math_elliptic_curves/t_ec_sage_template.nim +++ b/tests/math_elliptic_curves/t_ec_sage_template.nim @@ -15,15 +15,8 @@ import constantine/platforms/abstractions, constantine/math/[arithmetic, extension_fields], constantine/math/io/[io_bigints, io_ec], - constantine/math/elliptic/[ - ec_shortweierstrass_affine, - ec_shortweierstrass_projective, - ec_shortweierstrass_jacobian, - ec_scalar_mul, - ec_endomorphism_accel], - constantine/named/zoo_endomorphisms, - # Test utilities - constantine/math/elliptic/ec_scalar_mul_vartime + constantine/math/ec_shortweierstrass, + constantine/named/zoo_endomorphisms export unittest, abstractions, arithmetic # Generic sandwich @@ -166,7 +159,7 @@ proc run_scalar_mul_test_vs_sage*( impl.scalarMulGeneric(vec.vectors[i].scalar) reference.scalarMul_doubleAdd_vartime(vec.vectors[i].scalar) - refMinWeight.scalarMul_minHammingWeight_vartime(vec.vectors[i].scalar) + refMinWeight.scalarMul_jy00_vartime(vec.vectors[i].scalar) doAssert: bool(Q == reference) doAssert: bool(Q == impl) @@ -174,7 +167,7 @@ proc run_scalar_mul_test_vs_sage*( staticFor w, 2, 5: var refWNAF = P - refWNAF.scalarMul_minHammingWeight_windowed_vartime(vec.vectors[i].scalar, window = w) + refWNAF.scalarMul_wNAF_vartime(vec.vectors[i].scalar, window = w) check: bool(impl == refWNAF) when bits >= EndomorphismThreshold: # All endomorphisms constants are below this threshold @@ -189,5 +182,5 @@ proc run_scalar_mul_test_vs_sage*( staticFor w, 2, 5: var endoWNAF = P - endoWNAF.scalarMulEndo_minHammingWeight_windowed_vartime(vec.vectors[i].scalar, window = w) + endoWNAF.scalarMulEndo_wNAF_vartime(vec.vectors[i].scalar, window = w) check: bool(impl == endoWNAF) diff --git a/tests/math_elliptic_curves/t_ec_sage_vesta.nim b/tests/math_elliptic_curves/t_ec_sage_vesta.nim index 3e45eb7c..7dd25289 100644 --- a/tests/math_elliptic_curves/t_ec_sage_vesta.nim +++ b/tests/math_elliptic_curves/t_ec_sage_vesta.nim @@ -10,8 +10,7 @@ import # Internals constantine/named/algebras, constantine/math/extension_fields, - constantine/math/elliptic/ec_shortweierstrass_jacobian, - constantine/math/elliptic/ec_shortweierstrass_projective, + constantine/math/ec_shortweierstrass, # Test utilities ./t_ec_sage_template diff --git a/tests/math_elliptic_curves/t_ec_shortw_jac_g1_msm.nim b/tests/math_elliptic_curves/t_ec_shortw_jac_g1_msm.nim index eaf44f27..ea29dac2 100644 --- a/tests/math_elliptic_curves/t_ec_shortw_jac_g1_msm.nim +++ b/tests/math_elliptic_curves/t_ec_shortw_jac_g1_msm.nim @@ -9,7 +9,7 @@ import # Internals constantine/named/algebras, - constantine/math/elliptic/ec_shortweierstrass_jacobian, + constantine/math/ec_shortweierstrass, constantine/math/arithmetic, # Test utilities ./t_ec_template diff --git a/tests/math_elliptic_curves/t_ec_shortw_prj_g1_msm.nim b/tests/math_elliptic_curves/t_ec_shortw_prj_g1_msm.nim index ba948543..e617ca04 100644 --- a/tests/math_elliptic_curves/t_ec_shortw_prj_g1_msm.nim +++ b/tests/math_elliptic_curves/t_ec_shortw_prj_g1_msm.nim @@ -9,7 +9,7 @@ import # Internals constantine/named/algebras, - constantine/math/elliptic/ec_shortweierstrass_projective, + constantine/math/ec_shortweierstrass, constantine/math/arithmetic, # Test utilities ./t_ec_template diff --git a/tests/math_elliptic_curves/t_ec_template.nim b/tests/math_elliptic_curves/t_ec_template.nim index 11b63c54..2e003f3b 100644 --- a/tests/math_elliptic_curves/t_ec_template.nim +++ b/tests/math_elliptic_curves/t_ec_template.nim @@ -28,8 +28,7 @@ import ec_twistededwards_affine, ec_twistededwards_projective, ec_scalar_mul, - ec_multi_scalar_mul, - ec_endomorphism_accel], + ec_multi_scalar_mul], constantine/math/io/[io_bigints, io_fields, io_ec], constantine/named/[zoo_subgroups, zoo_endomorphisms], # Test utilities @@ -494,7 +493,7 @@ proc run_EC_mul_sanity_tests*( impl.scalarMulGeneric(BigInt[bits]()) reference.scalarMul_doubleAdd_vartime(BigInt[bits]()) - refMinWeight.scalarMul_minHammingWeight_vartime(BigInt[bits]()) + refMinWeight.scalarMul_jy00_vartime(BigInt[bits]()) check: bool(impl.isNeutral()) @@ -503,7 +502,7 @@ proc run_EC_mul_sanity_tests*( proc refWNaf(bits, w: static int) = # workaround staticFor symbol visibility var refWNAF = a - refWNAF.scalarMul_minHammingWeight_windowed_vartime(BigInt[bits](), window = w) + refWNAF.scalarMul_wNAF_vartime(BigInt[bits](), window = w) check: bool(refWNAF.isNeutral()) refWNaf(bits, w = 2) @@ -665,7 +664,7 @@ proc run_EC_mul_vs_ref_impl*( impl.scalarMulGeneric(scalar) reference.scalarMul_doubleAdd_vartime(scalar) - refMinWeight.scalarMul_minHammingWeight_vartime(scalar) + refMinWeight.scalarMul_jy00_vartime(scalar) check: bool(impl == reference) @@ -673,7 +672,7 @@ proc run_EC_mul_vs_ref_impl*( proc refWNaf(w: static int) = # workaround staticFor symbol visibility var refWNAF = P - refWNAF.scalarMul_minHammingWeight_windowed_vartime(scalar, window = w) + refWNAF.scalarMul_wNAF_vartime(scalar, window = w) check: bool(impl == refWNAF) refWNaf(2) @@ -757,7 +756,7 @@ proc run_EC_mul_endomorphism_impl*( impl.scalarMulGeneric(scalar) reference.scalarMul_doubleAdd_vartime(scalar) - refMinWeight.scalarMul_minHammingWeight_vartime(scalar) + refMinWeight.scalarMul_jy00_vartime(scalar) check: bool(impl == reference) @@ -765,7 +764,7 @@ proc run_EC_mul_endomorphism_impl*( proc refWNaf(w: static int) = # workaround staticFor symbol visibility var refWNAF = P - refWNAF.scalarMul_minHammingWeight_windowed_vartime(scalar, window = w) + refWNAF.scalarMul_wNAF_vartime(scalar, window = w) check: bool(impl == refWNAF) refWNaf(2) @@ -784,7 +783,7 @@ proc run_EC_mul_endomorphism_impl*( staticFor w, 2, 5: var endoWNAF = P - endoWNAF.scalarMulEndo_minHammingWeight_windowed_vartime(scalar, window = w) + endoWNAF.scalarMulEndo_wNAF_vartime(scalar, window = w) doAssert bool(impl == endoWNAF), diagnostic(impl, endoWNAF) test(ec, bits = ec.getScalarField().bits(), randZ = false, gen = Uniform) diff --git a/tests/math_elliptic_curves/t_ec_twedw_prj_msm.nim b/tests/math_elliptic_curves/t_ec_twedw_prj_msm.nim index ba0b5ec6..470dc3b2 100644 --- a/tests/math_elliptic_curves/t_ec_twedw_prj_msm.nim +++ b/tests/math_elliptic_curves/t_ec_twedw_prj_msm.nim @@ -9,7 +9,7 @@ import # Internals constantine/named/algebras, - constantine/math/elliptic/ec_twistededwards_projective, + constantine/math/ec_twistededwards, constantine/math/arithmetic, # Test utilities ./t_ec_template diff --git a/tests/math_elliptic_curves/t_ec_twedwards_mul_endomorphism_bandersnatch.nim b/tests/math_elliptic_curves/t_ec_twedwards_mul_endomorphism_bandersnatch.nim index 60ec5726..76b634b8 100644 --- a/tests/math_elliptic_curves/t_ec_twedwards_mul_endomorphism_bandersnatch.nim +++ b/tests/math_elliptic_curves/t_ec_twedwards_mul_endomorphism_bandersnatch.nim @@ -9,7 +9,7 @@ import # Internals constantine/named/algebras, - constantine/math/elliptic/ec_twistededwards_projective, + constantine/math/ec_twistededwards, # Test utilities ./t_ec_template diff --git a/tests/math_extension_fields/t_fp_tower_frobenius_template.nim b/tests/math_extension_fields/t_fp_tower_frobenius_template.nim index c3f6bed4..32942d78 100644 --- a/tests/math_extension_fields/t_fp_tower_frobenius_template.nim +++ b/tests/math_extension_fields/t_fp_tower_frobenius_template.nim @@ -21,7 +21,7 @@ import constantine/math/extension_fields, constantine/named/algebras, constantine/math/arithmetic, - constantine/math/isogenies/frobenius, + constantine/math/endomorphisms/frobenius, # Test utilities helpers/prng_unsafe diff --git a/tests/math_pairings/t_pairing_cyclotomic_subgroup.nim b/tests/math_pairings/t_pairing_cyclotomic_subgroup.nim index 2abcc25b..57057298 100644 --- a/tests/math_pairings/t_pairing_cyclotomic_subgroup.nim +++ b/tests/math_pairings/t_pairing_cyclotomic_subgroup.nim @@ -16,7 +16,7 @@ import constantine/named/algebras, constantine/math/io/[io_bigints, io_extfields], constantine/math/pairings/cyclotomic_subgroups, - constantine/math/isogenies/frobenius, + constantine/math/endomorphisms/frobenius, # Test utilities helpers/prng_unsafe diff --git a/tests/math_pairings/t_pairing_template.nim b/tests/math_pairings/t_pairing_template.nim index fb3d3de7..3490f2da 100644 --- a/tests/math_pairings/t_pairing_template.nim +++ b/tests/math_pairings/t_pairing_template.nim @@ -181,25 +181,25 @@ template runGTexponentiationTests*(Iters: static int, GT: typedesc): untyped {.d # MSB->LSB min Hamming Weight signed recoding var r_l2r_recoding {.noInit.}: GT - r_l2r_recoding.gtExp_minHammingWeight_vartime(a, k) + r_l2r_recoding.gtExp_jy00_vartime(a, k) doAssert bool(r_ref == r_l2r_recoding) # Windowed NAF var r_wNAF {.noInit.}: GT - r_wNAF.gtExp_minHammingWeight_windowed_vartime(a, k, window = 2) + r_wNAF.gtExp_wNAF_vartime(a, k, window = 2) doAssert bool(r_ref == r_wNAF) - r_wNAF.gtExp_minHammingWeight_windowed_vartime(a, k, window = 3) + r_wNAF.gtExp_wNAF_vartime(a, k, window = 3) doAssert bool(r_ref == r_wNAF) - r_wNAF.gtExp_minHammingWeight_windowed_vartime(a, k, window = 4) + r_wNAF.gtExp_wNAF_vartime(a, k, window = 4) doAssert bool(r_ref == r_wNAF) # Windowed NAF + endomorphism acceleration var r_endoWNAF {.noInit.}: GT - r_endoWNAF.gtExpEndo_minHammingWeight_windowed_vartime(a, k, window = 2) + r_endoWNAF.gtExpEndo_wNAF_vartime(a, k, window = 2) doAssert bool(r_ref == r_endoWNAF) - r_endoWNAF.gtExpEndo_minHammingWeight_windowed_vartime(a, k, window = 3) + r_endoWNAF.gtExpEndo_wNAF_vartime(a, k, window = 3) doAssert bool(r_ref == r_endoWNAF) - r_endoWNAF.gtExpEndo_minHammingWeight_windowed_vartime(a, k, window = 4) + r_endoWNAF.gtExpEndo_wNAF_vartime(a, k, window = 4) doAssert bool(r_ref == r_endoWNAF) stdout.write '.' diff --git a/tests/parallel/t_ec_shortw_jac_g1_msm_parallel.nim b/tests/parallel/t_ec_shortw_jac_g1_msm_parallel.nim index 9dc1e699..fe260469 100644 --- a/tests/parallel/t_ec_shortw_jac_g1_msm_parallel.nim +++ b/tests/parallel/t_ec_shortw_jac_g1_msm_parallel.nim @@ -9,7 +9,7 @@ import # Internals constantine/named/algebras, - constantine/math/elliptic/ec_shortweierstrass_jacobian, + constantine/math/ec_shortweierstrass, constantine/math/arithmetic, # Test utilities ./t_ec_template_parallel diff --git a/tests/parallel/t_ec_shortw_prj_g1_msm_parallel.nim b/tests/parallel/t_ec_shortw_prj_g1_msm_parallel.nim index 7fa2a09a..5c307ecd 100644 --- a/tests/parallel/t_ec_shortw_prj_g1_msm_parallel.nim +++ b/tests/parallel/t_ec_shortw_prj_g1_msm_parallel.nim @@ -9,7 +9,7 @@ import # Internals constantine/named/algebras, - constantine/math/elliptic/ec_shortweierstrass_projective, + constantine/math/ec_shortweierstrass, constantine/math/arithmetic, # Test utilities ./t_ec_template_parallel