diff --git a/benchmarks/bench_ec_g1_scalar_mul.nim b/benchmarks/bench_ec_g1_scalar_mul.nim index e53888a34..41f21a7de 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 a17f0bb71..06dd93841 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 1b05fdec9..91f5fc46a 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 f9c776556..2c5b068bf 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 f05c3d9d8..da953b180 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 79b0d2b7f..48f83cf9f 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 4765e0bb2..0a86e293f 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 6200d3764..708002d69 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 faf4a36c8..13aca484a 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 fa414c4f1..69c3748a6 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 aeb4d93d7..cc10108ef 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) @@ -59,6 +59,9 @@ proc main() = gtExp_endo_wNAF_vartimeBench(Fp12[curve], window = 3, ExpIters) gtExp_endo_wNAF_vartimeBench(Fp12[curve], window = 4, ExpIters) separator() + gtExpEndo_constanttimeBench(Fp12[curve], ExpIters) + separator() + main() notes() diff --git a/benchmarks/bench_gt_template.nim b/benchmarks/bench_gt_template.nim index f27420a9b..4e41b5f1f 100644 --- a/benchmarks/bench_gt_template.nim +++ b/benchmarks/bench_gt_template.nim @@ -20,6 +20,7 @@ import constantine/math/pairings/[ pairings_generic, cyclotomic_subgroups, + gt_exponentiations, gt_exponentiations_vartime ], # Helpers @@ -145,23 +146,30 @@ 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) + +proc gtExpEndo_constanttimeBench*(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 (endomorphism, constant-time)", T, iters): + r.gtExpEndo(x, exponent) diff --git a/benchmarks/bench_summary_bls12_377.nim b/benchmarks/bench_summary_bls12_377.nim index ab42b71f3..917ef29e9 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 9f75ed405..b314696dd 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 45b0a561e..3d6efc679 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 c327deb69..d41c3f89e 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 c25e7d8df..048ff17da 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 978de6156..4c32ec808 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/benchmarks/zkalc.nim b/benchmarks/zkalc.nim index fb452d66b..7448f72a8 100644 --- a/benchmarks/zkalc.nim +++ b/benchmarks/zkalc.nim @@ -55,6 +55,7 @@ type hash_G2: ZkalcBenchDetails mul_Gt: ZkalcBenchDetails + exp_Gt: ZkalcBenchDetails multiexp_Gt: ZkalcBenchDetails pairing: ZkalcBenchDetails @@ -394,6 +395,57 @@ proc benchEcHashToCurve(rng: var RngState, EC: type): ZkalcBenchDetails = report(G & " Hash-to-Curve", curve, stats) stats.toZkalc() +# 𝔾ₜ benches +# ------------------------------------------------------------------------------------- + +func random_gt*(rng: var RngState, F: typedesc): F {.inline, noInit.} = + result = rng.random_unsafe(F) + result.finalExp() + +proc benchGtMul(rng: var RngState, curve: static Algebra): ZkalcBenchDetails = + when curve in {BN254_Snarks, BLS12_377, BLS12_381}: + type Gt = Fp12[curve] + else: + {.error: "𝔾ₜ multiplication is not configured for " & $curve.} + + var x = rng.random_gt(Gt) + let y = rng.random_gt(Gt) + + preventOptimAway(x) + preventOptimAway(y) + + let stats = bench(): + x *= y + + report("𝔾ₜ Multiplication", curve, stats) + stats.toZkalc() + +proc benchGtExp(rng: var RngState, curve: static Algebra, useVartime: bool): ZkalcBenchDetails = + when curve in {BN254_Snarks, BLS12_377, BLS12_381}: + type Gt = Fp12[curve] + else: + {.error: "𝔾ₜ exponentiation is not configured for " & $curve.} + + var r {.noInit.}: Gt + let a = rng.random_gt(Gt) + let k = rng.random_unsafe(Fr[curve].getBigInt()) + + preventOptimAway(r) + preventOptimAway(a) + + if useVartime: + let stats = bench(): + r.gtExp_vartime(a, k) + + report("𝔾ₜ exponentiation" & align("| vartime", 16), curve, stats) + stats.toZkalc() + else: + let stats = bench(): + r.gtExp(a, k) + + report("𝔾ₜ exponentiation" & align("| constant-time", 16), curve, stats) + stats.toZkalc() + # Pairing benches # ------------------------------------------------------------------------------------- @@ -405,7 +457,7 @@ func clearCofactor[F; G: static Subgroup]( t.clearCofactor() ec.affine(t) -func random_point*(rng: var RngState, EC: typedesc): EC {.noInit.} = +func random_point*(rng: var RngState, EC: typedesc): EC {.inline, noInit.} = result = rng.random_unsafe(EC) result.clearCofactor() @@ -514,6 +566,11 @@ proc runBenches(curve: static Algebra, useVartime: bool): ZkalcBenchResult = zkalc.multipairing = rng.benchMultiPairing(curve, maxNumInputs = 1024) separator() + # Target group 𝔾ₜ + # -------------------------------------------------------------------- + zkalc.mul_Gt = rng.benchGtMul(curve) + zkalc.exp_Gt = rng.benchGtExp(curve, useVartime) + return zkalc proc main() = diff --git a/constantine/boolean_hypercube/multilinear_extensions.nim b/constantine/boolean_hypercube/multilinear_extensions.nim index 147001dbe..34fc217e0 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 554550851..ad52bab95 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 abbcc2aae..19c53ff20 100644 --- a/constantine/lowlevel_pairing_curves.nim +++ b/constantine/lowlevel_pairing_curves.nim @@ -10,11 +10,13 @@ import ./platforms/abstractions, ./named/algebras, ./named/zoo_pairings, - ./math/isogenies/frobenius, + ./math/endomorphisms/frobenius, ./math/pairings/[ cyclotomic_subgroups, lines_eval, - pairings_generic] + pairings_generic, + gt_exponentiations, + gt_exponentiations_vartime] # ############################################################ # # Low-level named Pairing-Friendly Curve API @@ -64,3 +66,15 @@ export zoo_pairings.isInPairingSubgroup export pairings_generic.pairing export pairings_generic.millerLoop export pairings_generic.finalExp + +export gt_exponentiations.gtExp +export gt_exponentiations_vartime.gtExp_vartime + +# Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 +# +# They are intended for rapid prototyping, testing and debugging. +export gt_exponentiations.`^` +export gt_exponentiations_vartime.`~^` diff --git a/constantine/math/arithmetic/bigints.nim b/constantine/math/arithmetic/bigints.nim index 97bce194f..458559fd2 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 4084cd497..9a0f4adf4 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 cee871f40..51f9e9573 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 4dcbaea4e..be5a5c327 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 eaa57c6e7..76acedae5 100644 --- a/constantine/math/elliptic/ec_scalar_mul.nim +++ b/constantine/math/elliptic/ec_scalar_mul.nim @@ -9,16 +9,21 @@ 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 + +{.push raises: [].} # No exceptions allowed in core cryptographic operations +{.push checks: off.} # No defects due to array bound checking or signed integer overflow allowed # ############################################################ # # @@ -55,6 +60,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 +140,6 @@ func scalarMulDoubling[EC]( return (k, bits) - func scalarMulGeneric[EC]( P: var EC, scalar: openArray[byte], @@ -232,6 +239,195 @@ 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 + 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 table 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 + 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 7486d39fb..dbff3a478 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, @@ -27,6 +27,13 @@ import {.push raises: [].} # No exceptions allowed in core cryptographic operations {.push checks: off.} # No defects due to array bound checking or signed integer overflow allowed +# ############################################################ +# # +# Scalar Multiplication # +# variable-time # +# # +# ############################################################ + iterator unpackBE(scalarByte: byte): bool = for i in countdown(7, 0): yield bool((scalarByte shr i) and 1) @@ -148,14 +155,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) @@ -169,6 +179,9 @@ func scalarMul_minHammingWeight_vartime*[EC](P: var EC, scalar: BigInt) {.tags:[ elif bit == -1: P ~-= Paff +# Non-Adjacent Form (NAF) recoding +# ------------------------------------------------------------ + func initNAF[precompSize, NafMax: static int, EC, ECaff]( P: var EC, tab: array[precompSize, ECaff], @@ -199,7 +212,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 +249,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.} = @@ -317,12 +330,18 @@ func scalarMulEndo_minHammingWeight_windowed_vartime*[scalBits: static int; EC]( else: isInit = P.initNAF(tab[m], tabNaf[m], NafLen, i) +# ############################################################ +# +# Public API +# +# ############################################################ + func scalarMul_vartime*[scalBits; EC](P: var EC, scalar: BigInt[scalBits]) {.meter.} = ## Elliptic Curve Scalar Multiplication ## ## P <- [k] P ## - ## This select the best algorithm depending on heuristics + ## This selects the best algorithm depending on heuristics ## and the scalar being multiplied. ## The scalar MUST NOT be a secret as this does not use side-channel countermeasures ## @@ -345,21 +364,21 @@ 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) + P.scalarMul_jy00_vartime(scalar) else: P.scalarMul_addchain_4bit_vartime(scalar) 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 d4be13b56..db88af066 100644 --- a/constantine/math/elliptic/ec_endomorphism_accel.nim +++ b/constantine/math/endomorphisms/split_scalars.nim @@ -13,20 +13,14 @@ 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 + +{.push raises: [].} # No exceptions allowed in core cryptographic operations +{.push checks: off.} # No defects due to array bound checking or signed integer overflow allowed # ############################################################ # -# Endomorphism acceleration for -# Scalar Multiplication +# Splitting scalars for endomorphism acceleration # # ############################################################ # @@ -175,7 +169,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 +221,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 +258,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 +298,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]) - - # Step 2. Convert to affine coordinates to benefit from mixed-addition - lut.batchAffine(tab) + lut[u].groupLawAdd(lut[u.clearBit(msb)], endomorphisms[msb]) -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 +349,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]) = +template buildEndoLookupTable_m2w2*[Group]( + lut: var array[8, Group], + P0, P1: Group, + groupLawAdd, groupLawSub, groupLawDouble: untyped) = ## Build a lookup table 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-table 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 +398,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 +411,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 0a5b8806b..000000000 --- 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 63d4514c4..f04714c93 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.nim b/constantine/math/pairings/gt_exponentiations.nim new file mode 100644 index 000000000..3c1f9b2c0 --- /dev/null +++ b/constantine/math/pairings/gt_exponentiations.nim @@ -0,0 +1,178 @@ +# 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/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, + constantine/named/zoo_endomorphisms, + constantine/named/algebras, + ./cyclotomic_subgroups + +from constantine/math/elliptic/ec_shortweierstrass_affine import G2 + +{.push raises: [].} # No exceptions allowed in core cryptographic operations +{.push checks: off.} # No defects due to array bound checking or signed integer overflow allowed + +# ############################################################ +# # +# Exponentiation in 𝔾ₜ # +# # +# ############################################################ + +func cinv[Gt](r{.noalias.}: var Gt, a{.noalias.}: Gt, ctl: SecretBool) {.inline.} = + r.cyclotomic_inv(a) + r.ccopy(a, not ctl) + +func cinv[Gt](a: var Gt, ctl: SecretBool) {.inline.} = + var t{.noInit.}: Gt + t.cyclotomic_inv(a) + a.ccopy(t, ctl) + +func quot[Gt](r: var Gt, a{.noalias.}, b: Gt) {.inline.} = + r.cyclotomic_inv(b) + r *= a + +func gtExpEndo*[Gt: ExtensionField, scalBits: static int]( + r: var Gt, + a: Gt, + scalar: BigInt[scalBits]) {.meter.} = + ## Endomorphism accelerated **Variable-time** Exponentiation in 𝔾ₜ + ## + ## r <- aᵏ + ## + ## Requires: + ## - Cofactor to be cleared + ## - 0 <= scalar < curve order + static: doAssert scalBits <= Fr[Gt.Name].bits(), "Do not use endomorphism to multiply beyond the curve order" + + # 1. Compute endomorphisms + const M = when Gt is Fp6: 2 + elif Gt is Fp12: 4 + else: {.error: "Unconfigured".} + + var endos {.noInit.}: array[M-1, Gt] + endos.computeEndomorphisms(a) + + # 2. Decompose scalar into mini-scalars + const L = Fr[Gt.Name].bits().computeEndoRecodedLength(M) + var miniScalars {.noInit.}: array[M, BigInt[L]] + var negateElems {.noInit.}: array[M, SecretBool] + miniScalars.decomposeEndo(negateElems, scalar, Fr[Gt.Name].bits(), Gt.Name, G2) # 𝔾ₜ has same decomposition as 𝔾₂ + + # 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: + r.cinv(a, negateElems[0]) + staticFor i, 1, M: + endos[i-1].cinv(negateElems[i]) + + # 4. Precompute lookup table + var lut {.noInit.}: array[1 shl (M-1), Gt] + buildEndoLookupTable( + r, endos, lut, + groupLawAdd = prod, # 𝔾ₜ is a multiplicative subgroup + ) + + # 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.}, t {.noInit.}: Gt + Q.secretLookup(lut, recoded.getRecodedIndex(L-1)) + + for i in countdown(L-2, 0): + Q.cyclotomic_square() + t.secretLookup(lut, recoded.getRecodedIndex(i)) + t.cinv(SecretBool recoded.getRecodedNegate(i)) + Q *= t + + # Now we need to correct if the sign miniscalar was not odd + r.quot(Q, r) + r.ccopy(Q, k0isOdd) + +# ############################################################ +# +# Public API +# +# ############################################################ + + +func gtExp*[Gt](r: var Gt, a: Gt, scalar: BigInt) {.inline, meter.} = + ## Exponentiation in 𝔾ₜ + ## + ## r <- aᵏ + ## + ## This use endomorphism acceleration by default if available + ## Endomorphism acceleration requires: + ## - Cofactor to be cleared + ## - 0 <= scalar < curve order + ## Those will be assumed to maintain constant-time property + when Gt.Name.hasEndomorphismAcceleration() and + BigInt.bits >= EndomorphismThreshold: + when Gt is Fp6: + r.gtExpEndo(a, scalar) # TODO: window method + elif Gt is Fp12: + r.gtExpEndo(a, scalar) + else: # Curves defined on Fp^m with m > 2 + {.error: "Unconfigured".} + else: + {.error: "Unimplemented".} + +func gtExp*[EC](r: var EC, a: EC, scalar: Fr) {.inline.} = + ## Exponentiation in 𝔾ₜ + ## + ## r <- aᵏ + r.gtExp(a, scalar.toBig()) + +func gtExp*[EC](a: var EC, scalar: Fr or BigInt) {.inline.} = + ## Exponentiation in 𝔾ₜ + ## + ## r <- aᵏ + ## + ## This use endomorphism acceleration by default if available + ## Endomorphism acceleration requires: + ## - Cofactor to be cleared + ## - 0 <= scalar < curve order + ## Those will be assumed to maintain constant-time property + a.gtExp(a, scalar) + +# ############################################################ +# +# Out-of-Place functions +# +# ############################################################ +# +# Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 + +func `^`*[Gt: ExtensionField](a: Gt, scalar: Fr or BigInt): Gt {.noInit, inline.} = + ## Exponentiation in 𝔾ₜ + ## + ## r <- aᵏ + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.gtExp(a, scalar) diff --git a/constantine/math/pairings/gt_exponentiations_vartime.nim b/constantine/math/pairings/gt_exponentiations_vartime.nim index cbc9fb31f..29cad3318 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, @@ -23,6 +23,13 @@ from constantine/math/elliptic/ec_shortweierstrass_affine import G2 {.push raises: [].} # No exceptions allowed in core cryptographic operations {.push checks: off.} # No defects due to array bound checking or signed integer overflow allowed +# ############################################################ +# # +# Exponentiation in 𝔾ₜ # +# variable-time # +# # +# ############################################################ + iterator unpackBE(scalarByte: byte): bool = for i in countdown(7, 0): yield bool((scalarByte shr i) and 1) @@ -62,7 +69,7 @@ func gtExp_addchain_4bit_vartime[Gt: ExtensionField](r: var Gt, a: Gt, scalar: B case s of 0: - r.setNeutral() + r.setOne() of 1: discard of 2: @@ -146,14 +153,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 @@ -168,6 +178,9 @@ func gtExp_minHammingWeight_vartime*[Gt: ExtensionField](r: var Gt, a: Gt, scala elif bit == -1: r *= na +# Non-Adjacent Form (NAF) recoding +# ------------------------------------------------------------ + func initNAF[precompSize, NafMax: static int, Gt: ExtensionField]( acc: var Gt, tab: array[precompSize, Gt], @@ -199,7 +212,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 +246,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 𝔾ₜ ## @@ -258,7 +271,7 @@ func gtExpEndo_minHammingWeight_windowed_vartime*[Gt: ExtensionField, scalBits: endos.computeEndomorphisms(a) # 2. Decompose scalar into mini-scalars - const L = Fr[Gt.Name].bits().ceilDiv_vartime(M) + 1 + const L = Fr[Gt.Name].bits().computeEndoRecodedLength(M) var miniScalars {.noInit.}: array[M, BigInt[L]] var negateElems {.noInit.}: array[M, SecretBool] miniScalars.decomposeEndo(negateElems, scalar, Fr[Gt.Name].bits(), Gt.Name, G2) # 𝔾ₜ has same decomposition as 𝔾₂ @@ -310,3 +323,97 @@ func gtExpEndo_minHammingWeight_windowed_vartime*[Gt: ExtensionField, scalBits: r.accumNAF(tab[m], tabNaf[m], NafLen, i) else: isInit = r.initNAF(tab[m], tabNaf[m], NafLen, i) + +# ############################################################ +# +# Public API +# +# ############################################################ + +func gtExp_vartime*[Gt: ExtensionField, scalBits: static int]( + r: var Gt, a: Gt, scalar: BigInt[scalBits]) {.tags:[VarTime], meter.} = + ## Exponentiation in 𝔾ₜ + ## + ## r <- aᵏ + ## + ## This selects the best algorithm depending on heuristics + ## and the scalar being multiplied. + ## The scalar MUST NOT be a secret as this does not use side-channel countermeasures + ## + ## This may use endomorphism acceleration. + ## As endomorphism acceleration requires: + ## - Cofactor to be cleared + ## - 0 <= scalar < curve order + ## Those conditions will be assumed. + + let usedBits = scalar.limbs.getBits_LE_vartime() + + when Gt.Name.hasEndomorphismAcceleration(): + when scalBits >= EndomorphismThreshold: # Skip static: doAssert when multiplying by intentionally small scalars. + if usedBits >= EndomorphismThreshold: + when Gt is Fp6: + r.gtExpEndo_wNAF_vartime(a, scalar, window = 4) + elif Gt is Fp12: + r.gtExpEndo_wNAF_vartime(a, scalar, window = 3) + else: # Curves defined on Fp^m with m > 2 + {.error: "Unconfigured".} + return + + if 64 < usedBits: + # With a window of 4, we precompute 2^4 = 4 elements + r.gtExp_wNAF_vartime(a, scalar, window = 4) + elif 16 < usedBits: + # With a window of 3, we precompute 2^1 = 2 elements + r.gtExp_wNAF_vartime(a, scalar, window = 3) + elif 4 < usedBits: + r.gtExp_jy00_vartime(a, scalar) + else: + r.gtExp_addchain_4bit_vartime(a, scalar) + +func gtExp_vartime*[Gt](r: var Gt, a: Gt, scalar: Fr) {.inline.} = + ## Exponentiation in 𝔾ₜ + ## + ## r <- aᵏ + ## + ## This select the best algorithm depending on heuristics + ## and the scalar being multiplied. + ## The scalar MUST NOT be a secret as this does not use side-channel countermeasures + r.gtExp_vartime(a, scalar.toBig()) + +func gtExp_vartime*[Gt](a: var Gt, scalar: Fr or BigInt) {.inline.} = + ## Exponentiation in 𝔾ₜ + ## + ## r <- aᵏ + ## + ## This selects the best algorithm depending on heuristics + ## and the scalar being multiplied. + ## The scalar MUST NOT be a secret as this does not use side-channel countermeasures + ## + ## This may use endomorphism acceleration. + ## As endomorphism acceleration requires: + ## - Cofactor to be cleared + ## - 0 <= scalar < curve order + ## Those conditions will be assumed. + a.gtExp_vartime(a, scalar) + +# ############################################################ +# +# Out-of-Place functions +# +# ############################################################ +# +# Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 + +func `~^`*[Gt: ExtensionField](a: Gt, scalar: Fr or BigInt): Gt {.noInit, inline.} = + ## Elliptic Curve variable-time Scalar Multiplication + ## + ## r <- aᵏ + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.gtExp_vartime(a, scalar) diff --git a/constantine/math/pairings/miller_loops.nim b/constantine/math/pairings/miller_loops.nim index 0d31362fa..68c4c3461 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 d10264330..fa3168f9f 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 2c7f479eb..0fd85fdde 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 110f94781..7c03a9866 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 ccebc3cc4..dae61c93d 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 2eba310a1..827da8989 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 5e5ef5645..3f85cd9ec 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 9b07b8e1b..02baeeced 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 689538807..6b3d8fbab 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 7ce7fa63e..afbe0a665 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 14ec1a719..d38a1f954 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 bf8f954b0..a0dbc6b99 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 6c4da7ed7..d459c9dcb 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 30cb06966..62f122d4a 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 f49fd3656..72805b574 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 4d5ebc83f..99301a4d7 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 96caee89b..6450b4b95 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 c4f05e0d6..823263918 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 a17e0bd35..655a8a3d9 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 8971f33a1..9c310f9c0 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 09e2c9654..3a095b482 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 1d0217faa..7552e421a 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 d56c66c49..b893ea390 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 034084bca..9509369d2 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 2365a4f87..faf284e7d 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 1632d587c..b1a35c123 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 4753738f1..7a8f2a550 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 3e45eb7c0..7dd25289c 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 eaf44f27a..ea29dac2f 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 ba9485434..e617ca049 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 11b63c54a..2e003f3be 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 ba0b5ec69..470dc3b25 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 60ec57263..76b634b87 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 c3f6bed46..32942d786 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 2abcc25b3..570572985 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 fb3d3de79..0c7382478 100644 --- a/tests/math_pairings/t_pairing_template.nim +++ b/tests/math_pairings/t_pairing_template.nim @@ -16,7 +16,11 @@ import constantine/named/algebras, constantine/named/zoo_subgroups, constantine/math/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective], - constantine/math/pairings/[cyclotomic_subgroups, gt_exponentiations_vartime, pairings_generic], + constantine/math/pairings/[ + cyclotomic_subgroups, + gt_exponentiations, + gt_exponentiations_vartime, + pairings_generic], constantine/math/io/io_extfields, # Test utilities @@ -27,7 +31,8 @@ export ec_shortweierstrass_affine, ec_shortweierstrass_projective, arithmetic, extension_fields, io_extfields, - cyclotomic_subgroups, gt_exponentiations_vartime, + cyclotomic_subgroups, + gt_exponentiations, gt_exponentiations_vartime, abstractions, algebras type @@ -181,27 +186,32 @@ 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) + # Constant-time 𝔾ₜ exponentiation with endomorphism + var r_ctEndo {.noInit.}: GT + r_ctEndo.gtExpEndo(a, k) + doAssert bool(r_ref == r_ctEndo) + stdout.write '.' stdout.write '\n' 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 9dc1e6993..fe2604697 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 7fa2a09ab..5c307ecde 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