diff --git a/README.md b/README.md index 9a7c4fb..90efd2a 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,20 @@ This library provides constant-time implementation of elliptic curve cryptography. -> Warning ⚠️: The library is in development state and cannot be used at the moment -> except as a showcase or to start a discussion on modular big integers internals. +The implementation is accompanied with SAGE code used as reference implementation and test vectors generators before high speed implementation. + +> The library is in development state and high-level wrappers or example protocols are not available yet. + +## Target audience + +The library aims to be a portable, compact and hardened library for elliptic curve cryptography needs, in particular for blockchain protocols and zero-knowledge proofs system. + +The library focuses on following properties: +- constant-time (not leaking secret data via side-channels) +- performance +- generated code size, datatype size and stack usage + +in this order ## Installation @@ -31,17 +43,6 @@ This can be deactivated with `"-d:ConstantineASM=false"`: - at misssed opportunity on recent CPUs that support MULX/ADCX/ADOX instructions (~60% faster than Clang). - There is a 2.4x perf ratio between using plain GCC vs GCC with inline assembly. -## Target audience - -The library aims to be a portable, compact and hardened library for elliptic curve cryptography needs, in particular for blockchain protocols and zero-knowledge proofs system. - -The library focuses on following properties: -- constant-time (not leaking secret data via side-channels) -- performance -- generated code size, datatype size and stack usage - -in this order - ## Curves supported At the moment the following curves are supported, adding a new curve only requires adding the prime modulus @@ -49,11 +50,9 @@ and its bitsize in [constantine/config/curves.nim](constantine/config/curves_dec The following curves are configured: -> Note: At the moment, finite field arithmetic is fully supported -> but elliptic curve arithmetic is work-in-progress. - -### ECDH / ECDSA curves +### ECDH / ECDSA / EdDSA curves +WIP: - NIST P-224 - Curve25519 - NIST P-256 / Secp256r1 @@ -61,20 +60,22 @@ The following curves are configured: ### Pairing-Friendly curves +Supports: +- [x] Field arithmetics +- [x] Curve arithmetic +- [x] Pairing +- [ ] Multi-Pairing +- [ ] Hash-To-Curve + Families: -- BN: Barreto-Naerig +- BN: Barreto-Naehrig - BLS: Barreto-Lynn-Scott -- FKM: Fotiadis-Konstantinou-Martindale Curves: - BN254_Nogami - BN254_Snarks (Zero-Knowledge Proofs, Snarks, Starks, Zcash, Ethereum 1) - BLS12-377 (Zexe) - BLS12-381 (Algorand, Chia Networks, Dfinity, Ethereum 2, Filecoin, Zcash Sapling) -- BN446 -- FKM12-447 -- BLS12-461 -- BN462 ## Security @@ -141,73 +142,72 @@ The previous implementation was 15x slower and one of the key optimizations was changing the elliptic curve cryptography backend. It had a direct implication on hardware cost and/or cloud computing resources required. -## Measuring performance +### Measuring performance To measure the performance of Constantine ```bash git clone https://github.com/mratsim/constantine -nimble bench_fp # Using Assembly (+ GCC) -nimble bench_fp_clang # Using Clang only -nimble bench_fp_gcc # Using Clang only (very slow) +nimble bench_fp # Using default compiler + Assembly +nimble bench_fp_clang # Using Clang + Assembly (recommended) +nimble bench_fp_gcc # Using GCC + Assembly (very slow) +nimble bench_fp_clang_noasm # Using Clang only +nimble bench_fp_gcc # Using GCC only (slowest) nimble bench_fp2 # ... nimble bench_ec_g1 nimble bench_ec_g2 +nimble bench_pairing_bn254_nogami +nimble bench_pairing_bn254_snarks +nimble bench_pairing_bls12_377 +nimble bench_pairing_bls12_381 ``` +"Unsafe" lines uses a non-constant-time algorithm. + As mentioned in the [Compiler caveats](#compiler-caveats) section, GCC is up to 2x slower than Clang due to mishandling of carries and register usage. -On my machine, for selected benchmarks on the prime field for popular pairing-friendly curves. +On my machine i9-9980XE, for selected benchmarks with Clang + Assembly ``` -Compiled with GCC -Optimization level => - no optimization: false - release: true - danger: true - inline assembly: true -Using Constantine with 64-bit limbs -Running on Intel(R) Core(TM) i9-9980XE CPU @ 3.00GHz - -⚠️ Cycles measurements are approximate and use the CPU nominal clock: Turbo-Boost and overclocking will skew them. -i.e. a 20% overclock will be about 20% off (assuming no dynamic frequency scaling) - -================================================================================================================= - -------------------------------------------------------------------------------------------------------------------------------------------------- -Addition Fp[BN254_Snarks] 333333333.333 ops/s 3 ns/op 9 CPU cycles (approx) -Substraction Fp[BN254_Snarks] 500000000.000 ops/s 2 ns/op 8 CPU cycles (approx) -Negation Fp[BN254_Snarks] 1000000000.000 ops/s 1 ns/op 3 CPU cycles (approx) -Multiplication Fp[BN254_Snarks] 71428571.429 ops/s 14 ns/op 44 CPU cycles (approx) -Squaring Fp[BN254_Snarks] 71428571.429 ops/s 14 ns/op 44 CPU cycles (approx) -Inversion (constant-time Euclid) Fp[BN254_Snarks] 122579.063 ops/s 8158 ns/op 24474 CPU cycles (approx) -Inversion via exponentiation p-2 (Little Fermat) Fp[BN254_Snarks] 153822.489 ops/s 6501 ns/op 19504 CPU cycles (approx) -Square Root + square check (constant-time) Fp[BN254_Snarks] 153491.942 ops/s 6515 ns/op 19545 CPU cycles (approx) -Exp curve order (constant-time) - 254-bit Fp[BN254_Snarks] 104580.632 ops/s 9562 ns/op 28687 CPU cycles (approx) -Exp curve order (Leak exponent bits) - 254-bit Fp[BN254_Snarks] 153798.831 ops/s 6502 ns/op 19506 CPU cycles (approx) -------------------------------------------------------------------------------------------------------------------------------------------------- -Addition Fp[BLS12_381] 250000000.000 ops/s 4 ns/op 14 CPU cycles (approx) -Substraction Fp[BLS12_381] 250000000.000 ops/s 4 ns/op 13 CPU cycles (approx) -Negation Fp[BLS12_381] 1000000000.000 ops/s 1 ns/op 4 CPU cycles (approx) -Multiplication Fp[BLS12_381] 35714285.714 ops/s 28 ns/op 84 CPU cycles (approx) -Squaring Fp[BLS12_381] 35714285.714 ops/s 28 ns/op 85 CPU cycles (approx) -Inversion (constant-time Euclid) Fp[BLS12_381] 43763.676 ops/s 22850 ns/op 68552 CPU cycles (approx) -Inversion via exponentiation p-2 (Little Fermat) Fp[BLS12_381] 63983.620 ops/s 15629 ns/op 46889 CPU cycles (approx) -Square Root + square check (constant-time) Fp[BLS12_381] 63856.960 ops/s 15660 ns/op 46982 CPU cycles (approx) -Exp curve order (constant-time) - 255-bit Fp[BLS12_381] 68535.399 ops/s 14591 ns/op 43775 CPU cycles (approx) -Exp curve order (Leak exponent bits) - 255-bit Fp[BLS12_381] 93222.709 ops/s 10727 ns/op 32181 CPU cycles (approx) -------------------------------------------------------------------------------------------------------------------------------------------------- -Notes: - - Compilers: - Compilers are severely limited on multiprecision arithmetic. - Inline Assembly is used by default (nimble bench_fp). - Bench without assembly can use "nimble bench_fp_gcc" or "nimble bench_fp_clang". - GCC is significantly slower than Clang on multiprecision arithmetic due to catastrophic handling of carries. - - The simplest operations might be optimized away by the compiler. - - Fast Squaring and Fast Multiplication are possible if there are spare bits in the prime representation (i.e. the prime uses 254 bits out of 256 bits) +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Line double BLS12_381 649350.649 ops/s 1540 ns/op 4617 CPU cycles (approx) +Line add BLS12_381 482858.522 ops/s 2071 ns/op 6211 CPU cycles (approx) +Mul 𝔽p12 by line xy000z BLS12_381 543478.261 ops/s 1840 ns/op 5518 CPU cycles (approx) +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Final Exponentiation Easy BLS12_381 39411.973 ops/s 25373 ns/op 76119 CPU cycles (approx) +Final Exponentiation Hard BLS12 BLS12_381 2141.603 ops/s 466940 ns/op 1400833 CPU cycles (approx) +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Miller Loop BLS12 BLS12_381 2731.576 ops/s 366089 ns/op 1098278 CPU cycles (approx) +Final Exponentiation BLS12 BLS12_381 2033.045 ops/s 491873 ns/op 1475634 CPU cycles (approx) +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Pairing BLS12 BLS12_381 1131.391 ops/s 883868 ns/op 2651631 CPU cycles (approx) +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ``` +``` +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EC Add G1 ECP_SWei_Proj[Fp[BLS12_381]] 2118644.068 ops/s 472 ns/op 1416 CPU cycles (approx) +EC Mixed Addition G1 ECP_SWei_Proj[Fp[BLS12_381]] 2439024.390 ops/s 410 ns/op 1232 CPU cycles (approx) +EC Double G1 ECP_SWei_Proj[Fp[BLS12_381]] 3448275.862 ops/s 290 ns/op 871 CPU cycles (approx) +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EC ScalarMul G1 (unsafe reference DoubleAdd) ECP_SWei_Proj[Fp[BLS12_381]] 7147.094 ops/s 139917 ns/op 419756 CPU cycles (approx) +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EC ScalarMul Generic G1 (window = 2, scratchsize = 4) ECP_SWei_Proj[Fp[BLS12_381]] 5048.975 ops/s 198060 ns/op 594188 CPU cycles (approx) +EC ScalarMul Generic G1 (window = 3, scratchsize = 8) ECP_SWei_Proj[Fp[BLS12_381]] 7148.269 ops/s 139894 ns/op 419685 CPU cycles (approx) +EC ScalarMul Generic G1 (window = 4, scratchsize = 16) ECP_SWei_Proj[Fp[BLS12_381]] 8112.735 ops/s 123263 ns/op 369791 CPU cycles (approx) +EC ScalarMul Generic G1 (window = 5, scratchsize = 32) ECP_SWei_Proj[Fp[BLS12_381]] 8464.534 ops/s 118140 ns/op 354424 CPU cycles (approx) +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +EC ScalarMul G1 (endomorphism accelerated) ECP_SWei_Proj[Fp[BLS12_381]] 9679.418 ops/s 103312 ns/op 309939 CPU cycles (approx) +EC ScalarMul Window-2 G1 (endomorphism accelerated) ECP_SWei_Proj[Fp[BLS12_381]] 13089.348 ops/s 76398 ns/op 229195 CPU cycles (approx) +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +``` + + + + ### Compiler caveats Unfortunately compilers and in particular GCC are not very good at optimizing big integers and/or cryptographic code even when using intrinsics like `addcarry_u64`. diff --git a/benchmarks/bench_ec_g1.nim b/benchmarks/bench_ec_g1.nim index 6376d1a..6f090cc 100644 --- a/benchmarks/bench_ec_g1.nim +++ b/benchmarks/bench_ec_g1.nim @@ -37,10 +37,6 @@ const AvailableCurves = [ # Secp256k1, BLS12_377, BLS12_381, - # BN446, - # FKM12_447, - # BLS12_461, - # BN462 ] proc main() = diff --git a/benchmarks/bench_ec_g2.nim b/benchmarks/bench_ec_g2.nim index 3054107..dee5bd5 100644 --- a/benchmarks/bench_ec_g2.nim +++ b/benchmarks/bench_ec_g2.nim @@ -38,10 +38,6 @@ const AvailableCurves = [ # Secp256k1, BLS12_377, BLS12_381, - # BN446, - # FKM12_447, - # BLS12_461, - # BN462 ] proc main() = diff --git a/benchmarks/bench_fp.nim b/benchmarks/bench_fp.nim index 2da3501..08a1dd8 100644 --- a/benchmarks/bench_fp.nim +++ b/benchmarks/bench_fp.nim @@ -35,10 +35,6 @@ const AvailableCurves = [ # Secp256k1, BLS12_377, BLS12_381, - # BN446, - # FKM12_447, - # BLS12_461, - # BN462 ] proc main() = diff --git a/benchmarks/bench_fp12.nim b/benchmarks/bench_fp12.nim index 0d0b7da..2a35eed 100644 --- a/benchmarks/bench_fp12.nim +++ b/benchmarks/bench_fp12.nim @@ -31,10 +31,6 @@ const AvailableCurves = [ BN254_Snarks, BLS12_377, BLS12_381 - # BN446, - # FKM12_447, - # BLS12_461, - # BN462 ] proc main() = diff --git a/benchmarks/bench_fp2.nim b/benchmarks/bench_fp2.nim index cce0550..a128bd2 100644 --- a/benchmarks/bench_fp2.nim +++ b/benchmarks/bench_fp2.nim @@ -31,10 +31,6 @@ const AvailableCurves = [ BN254_Snarks, BLS12_377, BLS12_381 - # BN446, - # FKM12_447, - # BLS12_461, - # BN462 ] proc main() = diff --git a/benchmarks/bench_fp6.nim b/benchmarks/bench_fp6.nim index 715c90e..6693860 100644 --- a/benchmarks/bench_fp6.nim +++ b/benchmarks/bench_fp6.nim @@ -30,11 +30,7 @@ const AvailableCurves = [ BN254_Nogami, BN254_Snarks, BLS12_377, - BLS12_381 - # BN446, - # FKM12_447, - # BLS12_461, - # BN462 + BLS12_381, ] proc main() = diff --git a/constantine.nimble b/constantine.nimble index cda47e9..3f4d3e4 100644 --- a/constantine.nimble +++ b/constantine.nimble @@ -33,8 +33,7 @@ const testDesc: seq[tuple[path: string, useGMP: bool]] = @[ ("tests/t_finite_fields_sqrt.nim", false), ("tests/t_finite_fields_powinv.nim", false), ("tests/t_finite_fields_vs_gmp.nim", true), - # Precompute - ("tests/t_precomputed", false), + ("tests/t_fp_cubic_root.nim", false), # Double-width finite fields ("tests/t_finite_fields_double_width.nim", false), # Towers of extension fields diff --git a/constantine/arithmetic/limbs_asm_modular_dbl_width_x86.nim b/constantine/arithmetic/assembly/limbs_asm_modular_dbl_width_x86.nim similarity index 98% rename from constantine/arithmetic/limbs_asm_modular_dbl_width_x86.nim rename to constantine/arithmetic/assembly/limbs_asm_modular_dbl_width_x86.nim index 96ee717..ed49566 100644 --- a/constantine/arithmetic/limbs_asm_modular_dbl_width_x86.nim +++ b/constantine/arithmetic/assembly/limbs_asm_modular_dbl_width_x86.nim @@ -10,8 +10,8 @@ import # Standard library std/macros, # Internal - ../config/common, - ../primitives + ../../config/common, + ../../primitives # ############################################################ # diff --git a/constantine/arithmetic/limbs_asm_modular_x86.nim b/constantine/arithmetic/assembly/limbs_asm_modular_x86.nim similarity index 99% rename from constantine/arithmetic/limbs_asm_modular_x86.nim rename to constantine/arithmetic/assembly/limbs_asm_modular_x86.nim index 05c0aff..d0cf94e 100644 --- a/constantine/arithmetic/limbs_asm_modular_x86.nim +++ b/constantine/arithmetic/assembly/limbs_asm_modular_x86.nim @@ -10,9 +10,9 @@ import # Standard library std/macros, # Internal - ../config/common, - ../primitives, - ./limbs + ../../config/common, + ../../primitives, + ../limbs # ############################################################ # diff --git a/constantine/arithmetic/limbs_asm_montmul_x86.nim b/constantine/arithmetic/assembly/limbs_asm_montmul_x86.nim similarity index 99% rename from constantine/arithmetic/limbs_asm_montmul_x86.nim rename to constantine/arithmetic/assembly/limbs_asm_montmul_x86.nim index 8a50584..6301526 100644 --- a/constantine/arithmetic/limbs_asm_montmul_x86.nim +++ b/constantine/arithmetic/assembly/limbs_asm_montmul_x86.nim @@ -10,9 +10,9 @@ import # Standard library std/macros, # Internal - ../config/common, - ../primitives, - ./limbs, + ../../config/common, + ../../primitives, + ../limbs, ./limbs_asm_montred_x86 # ############################################################ diff --git a/constantine/arithmetic/limbs_asm_montmul_x86_adx_bmi2.nim b/constantine/arithmetic/assembly/limbs_asm_montmul_x86_adx_bmi2.nim similarity index 99% rename from constantine/arithmetic/limbs_asm_montmul_x86_adx_bmi2.nim rename to constantine/arithmetic/assembly/limbs_asm_montmul_x86_adx_bmi2.nim index db6b85a..88c8ce3 100644 --- a/constantine/arithmetic/limbs_asm_montmul_x86_adx_bmi2.nim +++ b/constantine/arithmetic/assembly/limbs_asm_montmul_x86_adx_bmi2.nim @@ -10,9 +10,9 @@ import # Standard library std/macros, # Internal - ../config/common, - ../primitives, - ./limbs, + ../../config/common, + ../../primitives, + ../limbs, ./limbs_asm_montred_x86 # ############################################################ diff --git a/constantine/arithmetic/limbs_asm_montred_x86.nim b/constantine/arithmetic/assembly/limbs_asm_montred_x86.nim similarity index 99% rename from constantine/arithmetic/limbs_asm_montred_x86.nim rename to constantine/arithmetic/assembly/limbs_asm_montred_x86.nim index a696812..a0887c0 100644 --- a/constantine/arithmetic/limbs_asm_montred_x86.nim +++ b/constantine/arithmetic/assembly/limbs_asm_montred_x86.nim @@ -10,9 +10,9 @@ import # Standard library std/macros, # Internal - ../config/common, - ../primitives, - ./limbs + ../../config/common, + ../../primitives, + ../limbs # ############################################################ # diff --git a/constantine/arithmetic/limbs_asm_montred_x86_adx_bmi2.nim b/constantine/arithmetic/assembly/limbs_asm_montred_x86_adx_bmi2.nim similarity index 98% rename from constantine/arithmetic/limbs_asm_montred_x86_adx_bmi2.nim rename to constantine/arithmetic/assembly/limbs_asm_montred_x86_adx_bmi2.nim index 442cd34..6771785 100644 --- a/constantine/arithmetic/limbs_asm_montred_x86_adx_bmi2.nim +++ b/constantine/arithmetic/assembly/limbs_asm_montred_x86_adx_bmi2.nim @@ -10,9 +10,9 @@ import # Standard library std/macros, # Internal - ../config/common, - ../primitives, - ./limbs, + ../../config/common, + ../../primitives, + ../limbs, ./limbs_asm_montred_x86 # ############################################################ diff --git a/constantine/arithmetic/limbs_asm_mul_x86.nim b/constantine/arithmetic/assembly/limbs_asm_mul_x86.nim similarity index 98% rename from constantine/arithmetic/limbs_asm_mul_x86.nim rename to constantine/arithmetic/assembly/limbs_asm_mul_x86.nim index 64a12e3..72ff595 100644 --- a/constantine/arithmetic/limbs_asm_mul_x86.nim +++ b/constantine/arithmetic/assembly/limbs_asm_mul_x86.nim @@ -10,8 +10,8 @@ import # Standard library std/macros, # Internal - ../config/common, - ../primitives + ../../config/common, + ../../primitives # ############################################################ # diff --git a/constantine/arithmetic/limbs_asm_mul_x86_adx_bmi2.nim b/constantine/arithmetic/assembly/limbs_asm_mul_x86_adx_bmi2.nim similarity index 99% rename from constantine/arithmetic/limbs_asm_mul_x86_adx_bmi2.nim rename to constantine/arithmetic/assembly/limbs_asm_mul_x86_adx_bmi2.nim index dcc9042..c5c2aa7 100644 --- a/constantine/arithmetic/limbs_asm_mul_x86_adx_bmi2.nim +++ b/constantine/arithmetic/assembly/limbs_asm_mul_x86_adx_bmi2.nim @@ -10,8 +10,8 @@ import # Standard library std/macros, # Internal - ../config/common, - ../primitives + ../../config/common, + ../../primitives # ############################################################ # diff --git a/constantine/arithmetic/limbs_asm_x86.nim b/constantine/arithmetic/assembly/limbs_asm_x86.nim similarity index 99% rename from constantine/arithmetic/limbs_asm_x86.nim rename to constantine/arithmetic/assembly/limbs_asm_x86.nim index 79bf47f..8a73176 100644 --- a/constantine/arithmetic/limbs_asm_x86.nim +++ b/constantine/arithmetic/assembly/limbs_asm_x86.nim @@ -10,8 +10,8 @@ import # Standard library std/macros, # Internal - ../config/common, - ../primitives + ../../config/common, + ../../primitives # ############################################################ # diff --git a/constantine/arithmetic/bigints.nim b/constantine/arithmetic/bigints.nim index 6c38c60..53ec303 100644 --- a/constantine/arithmetic/bigints.nim +++ b/constantine/arithmetic/bigints.nim @@ -10,7 +10,7 @@ import ../config/[common, type_bigint], ../primitives, ./limbs, - ./limbs_generic_modular, + ./limbs_modular, ./limbs_montgomery export BigInt diff --git a/constantine/arithmetic/finite_fields.nim b/constantine/arithmetic/finite_fields.nim index 44084a1..7d4a9fb 100644 --- a/constantine/arithmetic/finite_fields.nim +++ b/constantine/arithmetic/finite_fields.nim @@ -31,7 +31,7 @@ import ./bigints, ./limbs_montgomery when UseASM_X86_64: - import ./limbs_asm_modular_x86 + import ./assembly/limbs_asm_modular_x86 when nimvm: from ../config/precompute import montyResidue_precompute @@ -340,10 +340,15 @@ func `*=`*(a: var Fp, b: Fp) {.inline.} = ## Multiplication modulo p a.prod(a, b) -func square*(a: var Fp) {.inline.}= +func square*(a: var Fp) {.inline.} = ## Squaring modulo p a.mres.montySquare(a.mres, Fp.C.Mod, Fp.C.getNegInvModWord(), Fp.C.canUseNoCarryMontySquare()) +func square_repeated*(r: var Fp, num: int) {.inline.} = + ## Repeated squarings + for _ in 0 ..< num: + r.square() + func `*=`*(a: var Fp, b: static int) {.inline.} = ## Multiplication by a small integer known at compile-time # Implementation: diff --git a/constantine/arithmetic/finite_fields_double_width.nim b/constantine/arithmetic/finite_fields_double_width.nim index 523c744..3efaaba 100644 --- a/constantine/arithmetic/finite_fields_double_width.nim +++ b/constantine/arithmetic/finite_fields_double_width.nim @@ -15,7 +15,7 @@ import ./limbs_double_width when UseASM_X86_64: - import limbs_asm_modular_dbl_width_x86 + import assembly/limbs_asm_modular_dbl_width_x86 type FpDbl*[C: static Curve] = object ## Double-width Fp element diff --git a/constantine/arithmetic/finite_fields_inversion.nim b/constantine/arithmetic/finite_fields_inversion.nim index e64373d..cbaeae5 100644 --- a/constantine/arithmetic/finite_fields_inversion.nim +++ b/constantine/arithmetic/finite_fields_inversion.nim @@ -7,506 +7,25 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import - ../config/[common, curves], + ../config/[common, curves, type_fp], ./bigints, - ./finite_fields + ../curves/zoo_inversions + +export zoo_inversions # ############################################################ # -# Specialized inversions +# Finite field inversion # # ############################################################ -# Field-specific inversion routines -func square_repeated(r: var Fp, num: int) = - ## Repeated squarings - for _ in 0 ..< num: - r.square() - -# Secp256k1 -# ------------------------------------------------------------ -func inv_addchain(r: var Fp[Secp256k1], a: Fp[Secp256k1]) {.used.}= - ## We invert via Little Fermat's theorem - ## a^(-1) ≡ a^(p-2) (mod p) - ## with p = "0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F" - ## We take advantage of the prime special form to hardcode - ## the sequence of squarings and multiplications for the modular exponentiation - ## - ## See libsecp256k1 - ## - ## The binary representation of (p - 2) has 5 blocks of 1s, with lengths in - ## { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: - ## [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] - - var - x2{.noInit.}: Fp[Secp256k1] - x3{.noInit.}: Fp[Secp256k1] - x6{.noInit.}: Fp[Secp256k1] - x9{.noInit.}: Fp[Secp256k1] - x11{.noInit.}: Fp[Secp256k1] - x22{.noInit.}: Fp[Secp256k1] - x44{.noInit.}: Fp[Secp256k1] - x88{.noInit.}: Fp[Secp256k1] - x176{.noInit.}: Fp[Secp256k1] - x220{.noInit.}: Fp[Secp256k1] - x223{.noInit.}: Fp[Secp256k1] - - x2.square(a) - x2 *= a - - x3.square(x2) - x3 *= a - - x6 = x3 - x6.square_repeated(3) - x6 *= x3 - - x9 = x6 - x9.square_repeated(3) - x9 *= x3 - - x11 = x9 - x11.square_repeated(2) - x11 *= x2 - - x22 = x11 - x22.square_repeated(11) - x22 *= x11 - - x44 = x22 - x44.square_repeated(22) - x44 *= x22 - - x88 = x44 - x88.square_repeated(44) - x88 *= x44 - - x176 = x88 - x88.square_repeated(88) - x176 *= x88 - - x220 = x176 - x220.square_repeated(44) - x220 *= x44 - - x223 = x220 - x223.square_repeated(3) - x223 *= x3 - - # The final result is then assembled using a sliding window over the blocks - r = x223 - r.square_repeated(23) - r *= x22 - r.square_repeated(5) - r *= a - r.square_repeated(3) - r *= x2 - r.square_repeated(2) - r *= a - -# BLS12-381 -# ------------------------------------------------------------ -func inv_addchain*(r: var Fp[BLS12_381], a: Fp[BLS12_381]) = - var - x10 {.noinit.}: Fp[BLS12_381] - x100 {.noinit.}: Fp[BLS12_381] - x1000 {.noinit.}: Fp[BLS12_381] - x1001 {.noinit.}: Fp[BLS12_381] - x1011 {.noinit.}: Fp[BLS12_381] - x1101 {.noinit.}: Fp[BLS12_381] - x10001 {.noinit.}: Fp[BLS12_381] - x10100 {.noinit.}: Fp[BLS12_381] - x11001 {.noinit.}: Fp[BLS12_381] - x11010 {.noinit.}: Fp[BLS12_381] - x110100 {.noinit.}: Fp[BLS12_381] - x110110 {.noinit.}: Fp[BLS12_381] - x110111 {.noinit.}: Fp[BLS12_381] - x1001101 {.noinit.}: Fp[BLS12_381] - x1001111 {.noinit.}: Fp[BLS12_381] - x1010101 {.noinit.}: Fp[BLS12_381] - x1011101 {.noinit.}: Fp[BLS12_381] - x1100111 {.noinit.}: Fp[BLS12_381] - x1101001 {.noinit.}: Fp[BLS12_381] - x1110111 {.noinit.}: Fp[BLS12_381] - x1111011 {.noinit.}: Fp[BLS12_381] - x10001001 {.noinit.}: Fp[BLS12_381] - x10010101 {.noinit.}: Fp[BLS12_381] - x10010111 {.noinit.}: Fp[BLS12_381] - x10101001 {.noinit.}: Fp[BLS12_381] - x10110001 {.noinit.}: Fp[BLS12_381] - x10111111 {.noinit.}: Fp[BLS12_381] - x11000011 {.noinit.}: Fp[BLS12_381] - x11010000 {.noinit.}: Fp[BLS12_381] - x11010111 {.noinit.}: Fp[BLS12_381] - x11100001 {.noinit.}: Fp[BLS12_381] - x11100101 {.noinit.}: Fp[BLS12_381] - x11101011 {.noinit.}: Fp[BLS12_381] - x11110101 {.noinit.}: Fp[BLS12_381] - x11111111 {.noinit.}: Fp[BLS12_381] - - x10 .square(a) - x100 .square(x10) - x1000 .square(x100) - x1001 .prod(a, x1000) - x1011 .prod(x10, x1001) - x1101 .prod(x10, x1011) - x10001 .prod(x100, x1101) - x10100 .prod(x1001, x1011) - x11001 .prod(x1000, x10001) - x11010 .prod(a, x11001) - x110100 .square(x11010) - x110110 .prod(x10, x110100) - x110111 .prod(a, x110110) - x1001101 .prod(x11001, x110100) - x1001111 .prod(x10, x1001101) - x1010101 .prod(x1000, x1001101) - x1011101 .prod(x1000, x1010101) - x1100111 .prod(x11010, x1001101) - x1101001 .prod(x10, x1100111) - x1110111 .prod(x11010, x1011101) - x1111011 .prod(x100, x1110111) - x10001001 .prod(x110100, x1010101) - x10010101 .prod(x11010, x1111011) - x10010111 .prod(x10, x10010101) - x10101001 .prod(x10100, x10010101) - x10110001 .prod(x1000, x10101001) - x10111111 .prod(x110110, x10001001) - x11000011 .prod(x100, x10111111) - x11010000 .prod(x1101, x11000011) - x11010111 .prod(x10100, x11000011) - x11100001 .prod(x10001, x11010000) - x11100101 .prod(x100, x11100001) - x11101011 .prod(x10100, x11010111) - x11110101 .prod(x10100, x11100001) - x11111111 .prod(x10100, x11101011) # 35 operations - - # TODO: we can accumulate in a partially reduced - # doubled-size `r` to avoid the final substractions. - # and only reduce at the end. - # This requires the number of op to be less than log2(p) == 381 - - # 35 + 22 = 57 operations - r.prod(x10111111, x11100001) - r.square_repeated(8) - r *= x10001 - r.square_repeated(11) - r *= x11110101 - - # 57 + 28 = 85 operations - r.square_repeated(11) - r *= x11100101 - r.square_repeated(8) - r *= x11111111 - r.square_repeated(7) - - # 88 + 22 = 107 operations - r *= x1001101 - r.square_repeated(9) - r *= x1101001 - r.square_repeated(10) - r *= x10110001 - - # 107+24 = 131 operations - r.square_repeated(7) - r *= x1011101 - r.square_repeated(9) - r *= x1111011 - r.square_repeated(6) - - # 131+23 = 154 operations - r *= x11001 - r.square_repeated(11) - r *= x1101001 - r.square_repeated(9) - r *= x11101011 - - # 154+28 = 182 operations - r.square_repeated(10) - r *= x11010111 - r.square_repeated(6) - r *= x11001 - r.square_repeated(10) - - # 182+23 = 205 operations - r *= x1110111 - r.square_repeated(9) - r *= x10010111 - r.square_repeated(11) - r *= x1001111 - - # 205+30 = 235 operations - r.square_repeated(10) - r *= x11100001 - r.square_repeated(9) - r *= x10001001 - r.square_repeated(9) - - # 235+21 = 256 operations - r *= x10111111 - r.square_repeated(8) - r *= x1100111 - r.square_repeated(10) - r *= x11000011 - - # 256+28 = 284 operations - r.square_repeated(9) - r *= x10010101 - r.square_repeated(12) - r *= x1111011 - r.square_repeated(5) - - # 284 + 21 = 305 operations - r *= x1011 - r.square_repeated(11) - r *= x1111011 - r.square_repeated(7) - r *= x1001 - - # 305+32 = 337 operations - r.square_repeated(13) - r *= x11110101 - r.square_repeated(9) - r *= x10111111 - r.square_repeated(8) - - # 337+22 = 359 operations - r *= x11111111 - r.square_repeated(8) - r *= x11101011 - r.square_repeated(11) - r *= x10101001 - - # 359+24 = 383 operations - r.square_repeated(8) - r *= x11111111 - r.square_repeated(8) - r *= x11111111 - r.square_repeated(6) - - # 383+22 = 405 operations - r *= x110111 - r.square_repeated(10) - r *= x11111111 - r.square_repeated(9) - r *= x11111111 - - # 405+26 = 431 operations - r.square_repeated(8) - r *= x11111111 - r.square_repeated(8) - r *= x11111111 - r.square_repeated(8) - - # 431+19 = 450 operations - r *= x11111111 - r.square_repeated(7) - r *= x1010101 - r.square_repeated(9) - r *= x10101001 - - # Total 450 operations: - # - 74 multiplications - # - 376 squarings - -# BN Curves -# ------------------------------------------------------------ -# Efficient Pairings and ECC for Embedded Systems -# Thomas Unterluggauer and Erich Wenger -# https://eprint.iacr.org/2014/800.pdf -# -# BN curve field modulus are of the form: -# p = 36u^4 + 36u^3 + 24u^2 + 6u + 1 -# -# We construct the following multiplication-squaring chain -# a^-1 mod p = a^(p-2) mod p (Little Fermat Theorem) -# = a^(36 u^4 + 36 u^3 + 24 u^2 + 6u + 1 - 2) mod p -# = a^(36 u^4) . a^(36 u^3) . a^(24 u^2) . a^(6u-1) mod p -# -# Note: it only works for u positive, in particular BN254_Nogami doesn't work :/ -# Is there a way to only use a^-u or even powers? - -func inv_addchain_bn[C](r: var Fp[C], a: Fp[C]) {.used.}= - ## Inversion on BN prime fields with positive base parameter `u` - ## via Little Fermat theorem and leveraging the prime low Hamming weight - ## - ## Requires a `bn` curve with a positive parameter `u` - # TODO: debug for input "0x0d2007d8aaface1b8501bfbe792974166e8f9ad6106e5b563604f0aea9ab06f6" - # on BN254_Snarks see test suite (but works in Sage so aliasing issue?) - # - # For BN254_Snarks `u` and `6u-1` exponentiation are not fast enough - # (even with dedicated addchains) - # compared to an addchain on the full prime modulus - static: doAssert C.canUse_BN_AddchainInversion() - - var v0 {.noInit.}, v1 {.noInit.}: Fp[C] - - v0 = a - v0.powUnsafeExponent(C.getBN_param_6u_minus_1_BE()) # v0 <- a^(6u-1) - v1.prod(v0, a) # v1 <- a^(6u) - v1.powUnsafeExponent(C.getBN_param_u_BE()) # v1 <- a^(6u²) - r.square(v1) # r <- a^(12u²) - v1.square(r) # v1 <- a^(24u²) - v0 *= v1 # v0 <- a^(24u²) a^(6u-1) - v1 *= r # v1 <- a^(24u²) a^(12u²) = a^(36u²) - v1.powUnsafeExponent(C.getBN_param_u_BE()) # v1 <- a^(36u³) - r.prod(v0, v1) # r <- a^(36u³) a^(24u²) a^(6u-1) - v1.powUnsafeExponent(C.getBN_param_u_BE()) # v1 <- a^(36u⁴) - r *= v1 # r <- a^(36u⁴) a^(36u³) a^(24u²) a^(6u-1) = a^(p-2) = a^(-1) - -func inv_addchain*(r: var Fp[BN254_Snarks], a: Fp[BN254_Snarks]) = - var - x10 {.noInit.}: Fp[BN254_Snarks] - x11 {.noInit.}: Fp[BN254_Snarks] - x101 {.noInit.}: Fp[BN254_Snarks] - x110 {.noInit.}: Fp[BN254_Snarks] - x1000 {.noInit.}: Fp[BN254_Snarks] - x1101 {.noInit.}: Fp[BN254_Snarks] - x10010 {.noInit.}: Fp[BN254_Snarks] - x10011 {.noInit.}: Fp[BN254_Snarks] - x10100 {.noInit.}: Fp[BN254_Snarks] - x10111 {.noInit.}: Fp[BN254_Snarks] - x11100 {.noInit.}: Fp[BN254_Snarks] - x100000 {.noInit.}: Fp[BN254_Snarks] - x100011 {.noInit.}: Fp[BN254_Snarks] - x101011 {.noInit.}: Fp[BN254_Snarks] - x101111 {.noInit.}: Fp[BN254_Snarks] - x1000001 {.noInit.}: Fp[BN254_Snarks] - x1010011 {.noInit.}: Fp[BN254_Snarks] - x1011011 {.noInit.}: Fp[BN254_Snarks] - x1100001 {.noInit.}: Fp[BN254_Snarks] - x1110101 {.noInit.}: Fp[BN254_Snarks] - x10010001 {.noInit.}: Fp[BN254_Snarks] - x10010101 {.noInit.}: Fp[BN254_Snarks] - x10110101 {.noInit.}: Fp[BN254_Snarks] - x10111011 {.noInit.}: Fp[BN254_Snarks] - x11000001 {.noInit.}: Fp[BN254_Snarks] - x11000011 {.noInit.}: Fp[BN254_Snarks] - x11010011 {.noInit.}: Fp[BN254_Snarks] - x11100001 {.noInit.}: Fp[BN254_Snarks] - x11100011 {.noInit.}: Fp[BN254_Snarks] - x11100111 {.noInit.}: Fp[BN254_Snarks] - - x10 .square(a) - x11 .prod(x10, a) - x101 .prod(x10, x11) - x110 .prod(x101, a) - x1000 .prod(x10, x110) - x1101 .prod(x101, x1000) - x10010 .prod(x101, x1101) - x10011 .prod(x10010, a) - x10100 .prod(x10011, a) - x10111 .prod(x11, x10100) - x11100 .prod(x101, x10111) - x100000 .prod(x1101, x10011) - x100011 .prod(x11, x100000) - x101011 .prod(x1000, x100011) - x101111 .prod(x10011, x11100) - x1000001 .prod(x10010, x101111) - x1010011 .prod(x10010, x1000001) - x1011011 .prod(x1000, x1010011) - x1100001 .prod(x110, x1011011) - x1110101 .prod(x10100, x1100001) - x10010001 .prod(x11100, x1110101) - x10010101 .prod(x100000, x1110101) - x10110101 .prod(x100000, x10010101) - x10111011 .prod(x110, x10110101) - x11000001 .prod(x110, x10111011) - x11000011 .prod(x10, x11000001) - x11010011 .prod(x10010, x11000001) - x11100001 .prod(x100000, x11000001) - x11100011 .prod(x10, x11100001) - x11100111 .prod(x110, x11100001) # 30 operations - - # 30 + 27 = 57 operations - r.square(x11000001) - r.square_repeated(7) - r *= x10010001 - r.square_repeated(10) - r *= x11100111 - r.square_repeated(7) - - # 57 + 19 = 76 operations - r *= x10111 - r.square_repeated(9) - r *= x10011 - r.square_repeated(7) - r *= x1101 - - # 76 + 33 = 109 operations - r.square_repeated(14) - r *= x1010011 - r.square_repeated(9) - r *= x11100001 - r.square_repeated(8) - - # 109 + 18 = 127 operations - r *= x1000001 - r.square_repeated(10) - r *= x1011011 - r.square_repeated(5) - r *= x1101 - - # 127 + 34 = 161 operations - r.square_repeated(8) - r *= x11 - r.square_repeated(12) - r *= x101011 - r.square_repeated(12) - - # 161 + 25 = 186 operations - r *= x10111011 - r.square_repeated(8) - r *= x101111 - r.square_repeated(14) - r *= x10110101 - - # 186 + 28 = 214 - r.square_repeated(9) - r *= x10010001 - r.square_repeated(5) - r *= x1101 - r.square_repeated(12) - - # 214 + 22 = 236 - r *= x11100011 - r.square_repeated(8) - r *= x10010101 - r.square_repeated(11) - r *= x11010011 - - # 236 + 32 = 268 - r.square_repeated(7) - r *= x1100001 - r.square_repeated(11) - r *= x100011 - r.square_repeated(12) - - # 268 + 20 = 288 - r *= x1011011 - r.square_repeated(9) - r *= x11000011 - r.square_repeated(8) - r *= x11100111 - - # 288 + 15 = 303 - r.square_repeated(7) - r *= x1110101 - r.square_repeated(6) - r *= x101 - -# ############################################################ -# -# Dispatch -# -# ############################################################ - -func inv_euclid*(r: var Fp, a: Fp) = +func inv_euclid*(r: var Fp, a: Fp) {.inline.} = ## Inversion modulo p via ## Niels Moller constant-time version of ## Stein's GCD derived from extended binary Euclid algorithm r.mres.steinsGCD(a.mres, Fp.C.getR2modP(), Fp.C.Mod, Fp.C.getPrimePlus1div2()) -func inv*(r: var Fp, a: Fp) = +func inv*(r: var Fp, a: Fp) {.inline.} = ## Inversion modulo p ## ## The inverse of 0 is 0. @@ -522,7 +41,7 @@ func inv*(r: var Fp, a: Fp) = else: r.inv_euclid(a) -func inv*(a: var Fp) = +func inv*(a: var Fp) {.inline.} = ## Inversion modulo p ## ## The inverse of 0 is 0. diff --git a/constantine/arithmetic/finite_fields_square_root.nim b/constantine/arithmetic/finite_fields_square_root.nim index 24d07e2..29ddf27 100644 --- a/constantine/arithmetic/finite_fields_square_root.nim +++ b/constantine/arithmetic/finite_fields_square_root.nim @@ -7,9 +7,9 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import - std/macros, ../primitives, ../config/[common, type_fp, curves], + ../curves/zoo_square_roots, ../io/[io_bigints, io_fields], ./bigints, ./finite_fields, ./limbs_montgomery @@ -112,25 +112,11 @@ func sqrt_if_square_p3mod4[C](a: var Fp[C]): SecretBool {.inline.} = # Tonelli Shanks for any prime # ------------------------------------------------------------ -const - # with e = 2adicity - # p == s * 2^e + 1 - # root_of_unity = smallest_quadratic_nonresidue^s - # exponent = (p-1-2^e)/2^e / 2 - TonelliShanks_exponent_BLS12_377 = BigInt[330].fromHex"0x35c748c2f8a21d58c760b80d94292763445b3e601ea271e3de6c45f741290002e16ba88600000010a11" - TonelliShanks_twoAdicity_BLS12_377 = 46 - TonelliShanks_root_of_unity_BLS12_377 = Fp[BLS12_377].fromHex"0x382d3d99cdbc5d8fe9dee6aa914b0ad14fcaca7022110ec6eaa2bc56228ac41ea03d28cc795186ba6b5ef26b00bbe8" - -{.experimental: "dynamicBindSym".} - -macro tsGet(C: static Curve, value: untyped): untyped = - return bindSym("TonelliShanks_" & $value & "_" & $C) - func precompute_tonelli_shanks[C]( a_pre_exp: var Fp[C], a: Fp[C]) = a_pre_exp = a - a_pre_exp.powUnsafeExponent(C.tsGet(exponent)) + a_pre_exp.powUnsafeExponent(C.tonelliShanks(exponent)) func isSquare_tonelli_shanks[C]( a, a_pre_exp: Fp[C]): SecretBool = @@ -139,7 +125,7 @@ func isSquare_tonelli_shanks[C]( ## Tonelli-Shanks based square root and inverse square root ## ## a^((p-1-2^e)/(2*2^e)) - const e = C.tsGet(twoAdicity) + const e = C.tonelliShanks(twoAdicity) var r {.noInit.}: Fp[C] r.square(a_pre_exp) # a^(2(q-1-2^e)/(2*2^e)) = a^((q-1)/2^e - 1) r *= a # a^((q-1)/2^e) @@ -169,13 +155,13 @@ func sqrt_invsqrt_tonelli_shanks[C]( template z: untyped = a_pre_exp template r: untyped = invsqrt var t {.noInit.}: Fp[C] - const e = C.tsGet(twoAdicity) + const e = C.tonelliShanks(twoAdicity) t.square(z) t *= a r = z var b = t - var root = C.tsGet(root_of_unity) + var root = C.tonelliShanks(root_of_unity) var buf {.noInit.}: Fp[C] diff --git a/constantine/arithmetic/limbs.nim b/constantine/arithmetic/limbs.nim index 224f4e0..6364d05 100644 --- a/constantine/arithmetic/limbs.nim +++ b/constantine/arithmetic/limbs.nim @@ -11,10 +11,10 @@ import ../primitives when UseASM_X86_32: - import ./limbs_asm_x86 + import ./assembly/limbs_asm_x86 when UseASM_X86_64: - import ./limbs_asm_mul_x86 - import ./limbs_asm_mul_x86_adx_bmi2 + import ./assembly/limbs_asm_mul_x86 + import ./assembly/limbs_asm_mul_x86_adx_bmi2 # ############################################################ # diff --git a/constantine/arithmetic/limbs_double_width.nim b/constantine/arithmetic/limbs_double_width.nim index 2193116..098852c 100644 --- a/constantine/arithmetic/limbs_double_width.nim +++ b/constantine/arithmetic/limbs_double_width.nim @@ -12,9 +12,9 @@ import ./limbs when UseASM_X86_32: - import ./limbs_asm_montred_x86 + import ./assembly/limbs_asm_montred_x86 when UseASM_X86_64: - import ./limbs_asm_montred_x86_adx_bmi2 + import ./assembly/limbs_asm_montred_x86_adx_bmi2 # ############################################################ # diff --git a/constantine/arithmetic/limbs_generic_modular.nim b/constantine/arithmetic/limbs_modular.nim similarity index 100% rename from constantine/arithmetic/limbs_generic_modular.nim rename to constantine/arithmetic/limbs_modular.nim diff --git a/constantine/arithmetic/limbs_montgomery.nim b/constantine/arithmetic/limbs_montgomery.nim index c6e53f4..00ab974 100644 --- a/constantine/arithmetic/limbs_montgomery.nim +++ b/constantine/arithmetic/limbs_montgomery.nim @@ -16,8 +16,8 @@ import when UseASM_X86_64: import - ./limbs_asm_montmul_x86, - ./limbs_asm_montmul_x86_adx_bmi2 + ./assembly/limbs_asm_montmul_x86, + ./assembly/limbs_asm_montmul_x86_adx_bmi2 # ############################################################ # diff --git a/constantine/config/curves.nim b/constantine/config/curves.nim index 83629d1..99de3c6 100644 --- a/constantine/config/curves.nim +++ b/constantine/config/curves.nim @@ -158,33 +158,6 @@ macro getPrimePlus1div4_BE*(C: static Curve): untyped = ## Get (P+1) / 4 for an odd prime in big-endian serialized format result = bindSym($C & "_PrimePlus1div4_BE") -# Family specific -# ------------------------------------------------------- -macro canUse_BN_AddchainInversion*(C: static Curve): untyped = - ## A BN curve can use the fast BN inversion if the parameter "u" is positive - if CurveFamilies[C] != BarretoNaehrig: - return newLit false - return bindSym($C & "_BN_can_use_addchain_inversion") - -macro getBN_param_u_BE*(C: static Curve): untyped = - ## Get the ``u`` parameter of a BN curve in canonical big-endian representation - result = bindSym($C & "_BN_u_BE") - -macro getBN_param_6u_minus_1_BE*(C: static Curve): untyped = - ## Get the ``6u-1`` from the ``u`` parameter - ## of a BN curve in canonical big-endian representation - result = bindSym($C & "_BN_6u_minus_1_BE") - -# Endomorphism -# ------------------------------------------------------- -macro getCubicRootOfUnity_mod_p*(C: static Curve): untyped = - ## Get a non-trivial cubic root of unity (mod p) with p the prime field - result = bindSym($C & "_cubicRootOfUnity_mod_p") - -macro getCubicRootOfUnity_mod_r*(C: static Curve): untyped = - ## Get a non-trivial cubic root of unity (mod r) with r the curve order - result = bindSym($C & "_cubicRootOfUnity_mod_r") - # ############################################################ # # Debug info printed at compile-time @@ -202,15 +175,12 @@ macro debugConsts(): untyped {.used.} = let modulus = bindSym(curveName & "_Modulus") let r2modp = bindSym(curveName & "_R2modP") let negInvModWord = bindSym(curveName & "_NegInvModWord") - let cubeRootOfUnity = ident(curveName & "_cubicRootOfUnity") result.add quote do: echo "Curve ", `curveName`,':' echo " Field Modulus: ", `modulus` echo " Montgomery R² (mod P): ", `r2modp` echo " Montgomery -1/P[0] (mod 2^", WordBitWidth, "): ", `negInvModWord` - when declared(`cubeRootOfUnity`): - echo " Cube root of unity: ", `cubeRootOfUnity` result.add quote do: echo "----------------------------------------------------------------------------" diff --git a/constantine/config/curves_declaration.nim b/constantine/config/curves_declaration.nim index 3e860d2..157ed88 100644 --- a/constantine/config/curves_declaration.nim +++ b/constantine/config/curves_declaration.nim @@ -38,15 +38,6 @@ export CurveFamily # which returns the field modulus of the curve # - proc Family*(curve: static Curve): CurveFamily # which returns the curve family -# - proc get_BN_param_u_BE*(curve: static Curve): array[N, byte] -# which returns the "u" parameter of a BN curve -# as a big-endian canonical integer representation -# if it's a BN curve and u is positive -# - proc get_BN_param_6u_minus1_BE*(curve: static Curve): array[N, byte] -# which returns the "6u-1" parameter of a BN curve -# as a big-endian canonical integer representation -# if it's a BN curve and u is positive. -# This is used for optimized field inversion for BN curves declareCurves: # ----------------------------------------------------------------------------- @@ -102,11 +93,6 @@ declareCurves: bitwidth: 254 modulus: "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47" family: BarretoNaehrig - bn_u_bitwidth: 63 - bn_u: "0x44e992b44a6909f1" # u: 4965661367192848881 - cubicRootOfUnity_modP: "0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48" - # For sanity checks - cubicRootOfUnity_modR: "0x30644e72e131a029048b6e193fd84104cc37a73fec2bc5e9b8ca0b2d36636f23" # G1 Equation: Y^2 = X^3 + 3 # G2 Equation: Y^2 = X^3 + 3/(9+𝑖) @@ -140,7 +126,6 @@ declareCurves: family: BarretoLynnScott # u: 3 * 2^46 * (7 * 13 * 499) + 1 # u: 0x8508c00000000001 - cubicRootOfUnity_mod_p: "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000001" # G1 Equation: y² = x³ + 1 # G2 Equation: y² = x³ + 1/ with 𝑗 = √-5 @@ -160,7 +145,6 @@ declareCurves: modulus: "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab" family: BarretoLynnScott # u: -(2^63 + 2^62 + 2^60 + 2^57 + 2^48 + 2^16) - cubicRootOfUnity_mod_p: "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac" # G1 Equation: y² = x³ + 4 # G2 Equation: y² = x³ + 4 (1+i) @@ -175,53 +159,3 @@ declareCurves: sexticTwist: M_Twist sexticNonResidue_fp2: (1, 1) # 1+𝑖 - - curve BN446: - bitwidth: 446 - modulus: "0x2400000000000000002400000002d00000000d800000021c0000001800000000870000000b0400000057c00000015c000000132000000067" - family: BarretoNaehrig - # u = 2^110 + 2^36 + 1 - curve FKM12_447: # Fotiadis-Konstantinou-Martindale - bitwidth: 447 - modulus: "0x4ce300001338c00001c08180000f20cfffffe5a8bffffd08a000000f228000007e8ffffffaddfffffffdc00000009efffffffca000000007" - # TNFS Resistant Families of Pairing-Friendly Elliptic Curves - # Georgios Fotiadis and Elisavet Konstantinou, 2018 - # https://eprint.iacr.org/2018/1017 - # - # Family 17 choice b of - # Optimal TNFS-secure pairings on elliptic curves with composite embedding degree - # Georgios Fotiadis and Chloe Martindale, 2019 - # https://eprint.iacr.org/2019/555 - # - # A short-list of pairing-friendly curves resistant toSpecial TNFS at the 128-bit security level - # Aurore Guillevic - # https://hal.inria.fr/hal-02396352v2/document - # - # p(x) = 1728x^6 + 2160x^5 + 1548x^4 + 756x^3 + 240x^2 + 54x + 7 - # t(x) = −6x² + 1, r(x) = 36x^4 + 36x^3 + 18x^2 + 6x + 1. - # Choice (b):u=−2^72 − 2^71 − 2^36 - # - # Note the paper mentions 446-bit but it's 447 - curve BLS12_461: - # Updating Key Size Estimations for Pairings - # Barbulescu, R. and S. Duquesne, 2018 - # https://hal.archives-ouvertes.fr/hal-01534101/file/main.pdf - bitwidth: 461 - modulus: "0x15555545554d5a555a55d69414935fbd6f1e32d8bacca47b14848b42a8dffa5c1cc00f26aa91557f00400020000555554aaaaaac0000aaaaaaab" - # u = −2^77 + 2^50 + 2^33 - # p = (u - 1)^2 (u^4 - u^2 + 1)/3 + u - - # Note there is another BLS12-461 proposed here: - # https://tools.ietf.org/id/draft-yonezawa-pairing-friendly-curves-00.html#rfc.section.4.2 - curve BN462: - # Pairing-Friendly Curves - # IETF Draft - # https://tools.ietf.org/id/draft-irtf-cfrg-pairing-friendly-curves-02.html - - # Updating Key Size Estimations for Pairings - # Barbulescu, R. and S. Duquesne, 2018 - # https://hal.archives-ouvertes.fr/hal-01534101/file/main.pdf - bitwidth: 462 - modulus: "0x240480360120023ffffffffff6ff0cf6b7d9bfca0000000000d812908f41c8020ffffffffff6ff66fc6ff687f640000000002401b00840138013" - family: BarretoNaehrig - # u = 2^114 + 2^101 - 2^14 - 1 diff --git a/constantine/config/curves_derived.nim b/constantine/config/curves_derived.nim index 93805d4..d618762 100644 --- a/constantine/config/curves_derived.nim +++ b/constantine/config/curves_derived.nim @@ -124,57 +124,4 @@ macro genDerivedConstants*(): untyped = ) ) - # const MyCurve_cubicRootOfUnity_mod_p - block: - let cubicHex = ident(curve & "_cubicRootOfUnity_modP_Hex") - let cubic = used(curve & "_cubicRootOfUnity_mod_p") - let M = bindSym(curve & "_Modulus") - let r2modM = ident(curve & "_R2modP") - let m0ninv = ident(curve & "_NegInvModWord") - result.add quote do: - when declared(`cubicHex`): - const `cubic` = block: - var cubic: Fp[Curve(`curveSym`)] - montyResidue_precompute( - cubic.mres, - fromHex(cubic.mres.typeof, `cubicHex`), - `M`, `r2modM`, `m0ninv` - ) - cubic - # const MyCurve_cubicRootOfUnity_mod_r - block: # For scalar decomposition sanity checks - let cubicHex = ident(curve & "_cubicRootOfUnity_modR_Hex") - let cubic = used(curve & "_cubicRootOfUnity_mod_r") - let getCurveOrderBitwidth = ident"getCurveOrderBitwidth" - result.add quote do: - when declared(`cubicHex`): - const `cubic` = fromHex(BigInt[ - `getCurveOrderBitwidth`(Curve(`curveSym`)) - ], `cubicHex`) - - if CurveFamilies[curveSym] == BarretoNaehrig: - # when declared(MyCurve_BN_param_u): - # const MyCurve_BN_u_BE = toCanonicalIntRepr(MyCurve_BN_param_u) - # const MyCurve_BN_6u_minus_1_BE = bn_6u_minus_1_BE(MyCurve_BN_param_u) - var bnStmts = newStmtList() - bnStmts.add newConstStmt( - used(curve & "_BN_u_BE"), newCall( - bindSym"toCanonicalIntRepr", - ident(curve & "_BN_param_u") - ) - ) - bnStmts.add newConstStmt( - used(curve & "_BN_6u_minus_1_BE"), newCall( - bindSym"bn_6u_minus_1_BE", - ident(curve & "_BN_param_u") - ) - ) - - result.add nnkWhenStmt.newTree( - nnkElifBranch.newTree( - newCall(ident"declared", ident(curve & "_BN_param_u")), - bnStmts - ) - ) - # echo result.toStrLit() diff --git a/constantine/config/curves_parser.nim b/constantine/config/curves_parser.nim index eba05cb..7baaf54 100644 --- a/constantine/config/curves_parser.nim +++ b/constantine/config/curves_parser.nim @@ -109,15 +109,7 @@ type sexticTwist: SexticTwist sexticNonResidue_fp2: NimNode # nnkPar(nnkIntLit, nnkIntLit) - # Endomorphisms - cubicRootOfUnity_modP: NimNode # nnkStrLit - cubicRootOfUnity_modR: NimNode # nnkStrLit - family: CurveFamily - # BN family - # ------------------------ - bn_u_bitwidth: NimNode # nnkIntLit - bn_u: NimNode # nnkStrLit (hex) var curvesDefinitions {.compileTime.}: seq[CurveParams] @@ -182,14 +174,6 @@ proc parseCurveDecls(defs: var seq[CurveParams], curves: NimNode) = params.modulus = sectionVal elif sectionId.eqIdent"family": params.family = parseEnum[CurveFamily]($sectionVal) - elif sectionId.eqIdent"bn_u_bitwidth": - params.bn_u_bitwidth = sectionVal - elif sectionId.eqIdent"bn_u": - params.bn_u = sectionVal - elif sectionId.eqident"cubicRootOfUnity_modP": - params.cubicRootOfUnity_modP = sectionVal - elif sectionId.eqident"cubicRootOfUnity_modR": - params.cubicRootOfUnity_modR = sectionVal elif sectionId.eqIdent"eq_form": params.eq_form = parseEnum[CurveEquationForm]($sectionVal) elif sectionId.eqIdent"coef_a": @@ -323,42 +307,6 @@ proc genMainConstants(defs: var seq[CurveParams]): NimNode = curveDef.sexticNonResidue_fp2 ) - # Endomorphisms - # ----------------------------------------------- - if not curveDef.cubicRootOfUnity_modP.isNil: - curveExtraStmts.add newConstStmt( - exported($curve & "_cubicRootOfUnity_modP_Hex"), - curveDef.cubicRootOfUnity_modP - ) - if not curveDef.cubicRootOfUnity_modR.isNil: - curveExtraStmts.add newConstStmt( - exported($curve & "_cubicRootOfUnity_modR_Hex"), - curveDef.cubicRootOfUnity_modR - ) - - # BN curves - # ----------------------------------------------- - if family == BarretoNaehrig: - if not curveDef.bn_u_bitwidth.isNil and - not curveDef.bn_u.isNil and - ($curveDef.bn_u)[0] != '-': # The parameter must be positive - curveExtraStmts.add newConstStmt( - exported($curve & "_BN_can_use_addchain_inversion"), - newLit true - ) - curveExtraStmts.add newConstStmt( - exported($curve & "_BN_param_u"), - newCall( - bindSym"fromHex", - nnkBracketExpr.newTree(bindSym"BigInt", curveDef.bn_u_bitwidth), - curveDef.bn_u - ) - ) - else: - curveExtraStmts.add newConstStmt( - exported($curve & "_BN_can_use_addchain_inversion"), - newLit false - ) # end for --------------------------------------------------- result = newStmtList() diff --git a/constantine/config/precompute.nim b/constantine/config/precompute.nim index 055b2d0..5844555 100644 --- a/constantine/config/precompute.nim +++ b/constantine/config/precompute.nim @@ -458,35 +458,6 @@ func toCanonicalIntRepr*[bits: static int]( ## (octet-string) result.exportRawUint(a, bigEndian) -func bn_6u_minus_1_BE*[bits: static int]( - u: BigInt[bits] - ): array[(bits+7+3) div 8, byte] {.noInit.} = - ## For a BN curve - ## Precompute 6u-1 (for Little Fermat inversion) - ## and store it in canonical integer representation - # TODO: optimize output size - # each extra 0-bit is an extra useless squaring for a public exponent - # For example, for BN254-Snarks, u = 0x44E992B44A6909F1 (63-bit) - # and 6u+1 is 65-bit (not 66 as inferred) - - # Zero-extend "u" - var u_ext: BigInt[bits+3] - - for i in 0 ..< u.limbs.len: - u_ext.limbs[i] = u.limbs[i] - - # Addition chain to u -> 6u - discard u_ext.dbl() # u_ext = 2u - let u_ext2 = u_ext # u_ext2 = 2u - discard u_ext.dbl() # u_ext = 4u - discard u_ext.cadd(u_ext2, true) # u_ext = 6u - - # Sustract 1 - discard u_ext.sub(1) - - # Export - result.exportRawUint(u_ext, bigEndian) - # ############################################################ # # Compile-time Conversion to Montgomery domain diff --git a/constantine/curves/README.md b/constantine/curves/README.md new file mode 100644 index 0000000..7a84038 --- /dev/null +++ b/constantine/curves/README.md @@ -0,0 +1,9 @@ +# Curve-specific constants and procedures + +This folder holds curve-specific constants and procedure in particular: + +- Inversion addition chains +- Final exponentiation addition chains +- Square root constants for Tonelli Shanks +- Lattice decomposition constants for endomorphism acceleration +- Frobenius endomorphism constants diff --git a/constantine/curves/bls12_377_frobenius.nim b/constantine/curves/bls12_377_frobenius.nim new file mode 100644 index 0000000..cbe7dea --- /dev/null +++ b/constantine/curves/bls12_377_frobenius.nim @@ -0,0 +1,119 @@ +# 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 + ../config/curves, + ../towers, + ../io/io_towers + +# Frobenius map - on extension fields +# ----------------------------------------------------------------- + +# c = (SNR^((p-1)/6)^coef). +# Then for frobenius(2): c * conjugate(c) +# And for frobenius(3): c² * conjugate(c) +const BLS12_377_FrobeniusMapCoefficients* = [ + # frobenius(1) + [Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^0 + "0x1", + "0x0" + ), + Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^1 + "0x9a9975399c019633c1e30682567f915c8a45e0f94ebc8ec681bf34a3aa559db57668e558eb0188e938a9d1104f2031", + "0x0" + ), + Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^2 = SNR^((p-1)/3) + "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000002", + "0x0" + ), + Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^3 = SNR^((p-1)/2) + "0x1680a40796537cac0c534db1a79beb1400398f50ad1dec1bce649cf436b0f6299588459bff27d8e6e76d5ecf1391c63", + "0x0" + ), + Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^4 = SNR^(2(p-1)/3) + "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000001", + "0x0" + ), + Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^5 + "0xcd70cb3fc936348d0351d498233f1fe379531411832232f6648a9a9fc0b9c4e3e21b7467077c05853e2c1be0e9fc32", + "0x0" + )], + # frobenius(2) + [Fp2[BLS12_377].fromHex( # norm(SNR)^((p-1)/6)^1 + "0x1", + "0x0" + ), + Fp2[BLS12_377].fromHex( # norm(SNR)^((p-1)/6)^2 + "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000002", + "0x0" + ), + Fp2[BLS12_377].fromHex( + "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000001", + "0x0" + ), + Fp2[BLS12_377].fromHex( + "0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000000", + "0x0" + ), + Fp2[BLS12_377].fromHex( + "0x1ae3a4617c510eabc8756ba8f8c524eb8882a75cc9bc8e359064ee822fb5bffd1e945779fffffffffffffffffffffff", + "0x0" + ), + Fp2[BLS12_377].fromHex( + "0x1ae3a4617c510eabc8756ba8f8c524eb8882a75cc9bc8e359064ee822fb5bffd1e94577a00000000000000000000000", + "0x0" + )], + # frobenius(3) + [Fp2[BLS12_377].fromHex( + "0x1", + "0x0" + ), + Fp2[BLS12_377].fromHex( + "0x1680a40796537cac0c534db1a79beb1400398f50ad1dec1bce649cf436b0f6299588459bff27d8e6e76d5ecf1391c63", + "0x0" + ), + Fp2[BLS12_377].fromHex( + "0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000000", + "0x0" + ), + Fp2[BLS12_377].fromHex( + "0x4630059e5fd9200575d0e552278a89da1f40fdf62334cd620d1860769e389d7db2d8ea700d82721691ea130ec6e39e", + "0x0" + ), + Fp2[BLS12_377].fromHex( + "0x1", + "0x0" + ), + Fp2[BLS12_377].fromHex( + "0x1680a40796537cac0c534db1a79beb1400398f50ad1dec1bce649cf436b0f6299588459bff27d8e6e76d5ecf1391c63", + "0x0" + )]] + +# ψ (Psi) - Untwist-Frobenius-Twist Endomorphisms on twisted curves +# ----------------------------------------------------------------- + +# BLS12_377 is a D-Twist: SNR^((p-1)/6) +const BLS12_377_FrobeniusPsi_psi1_coef1* = Fp2[BLS12_377].fromHex( + "0x9a9975399c019633c1e30682567f915c8a45e0f94ebc8ec681bf34a3aa559db57668e558eb0188e938a9d1104f2031", + "0x0" +) +# SNR^((p-1)/3) +const BLS12_377_FrobeniusPsi_psi1_coef2* = Fp2[BLS12_377].fromHex( + "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000002", + "0x0" +) +# SNR^((p-1)/2) +const BLS12_377_FrobeniusPsi_psi1_coef3* = Fp2[BLS12_377].fromHex( + "0x1680a40796537cac0c534db1a79beb1400398f50ad1dec1bce649cf436b0f6299588459bff27d8e6e76d5ecf1391c63", + "0x0" +) +# norm(SNR)^((p-1)/3) +const BLS12_377_FrobeniusPsi_psi2_coef2* = Fp2[BLS12_377].fromHex( + "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000001", + "0x0" +) diff --git a/constantine/curves/bls12_377_glv.nim b/constantine/curves/bls12_377_glv.nim new file mode 100644 index 0000000..369b181 --- /dev/null +++ b/constantine/curves/bls12_377_glv.nim @@ -0,0 +1,69 @@ +# 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 + ../config/[curves, type_bigint, type_fp], + ../io/[io_bigints, io_fields] + +# BLS12-377 G1 +# ---------------------------------------------------------------------------------------- + +const BLS12_377_cubicRootofUnity_mod_p* = + Fp[BLS12_377].fromHex"0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000001" + +const BLS12_377_Lattice_G1* = ( + # (BigInt, isNeg) + ((BigInt[127].fromHex"0x452217cc900000010a11800000000000", false), # u² - 1 + (BigInt[1].fromHex"0x1", true)), # -1 + ((BigInt[1].fromHex"0x1", false), # 1 + (BigInt[127].fromHex"0x452217cc900000010a11800000000001", false)) # u² +) + +const BLS12_377_Babai_G1* = ( + # Vector for Babai rounding + # (BigInt, isNeg) + (BigInt[130].fromHex"0x3b3f7aa969fd371607f72ed32af90182c", false), + (BigInt[4].fromHex"0xd", false) +) + +# BLS12-377 G2 +# ---------------------------------------------------------------------------------------- + +const BLS12_377_Lattice_G2* = ( + # Curve of order 254 -> mini scalars of size 65 + # x = -0xd201000000010000 + # Value, isNeg + ((BigInt[64].fromHex"0x8508c00000000001", true), # -x + (BigInt[1].fromHex"0x1", false), # 1 + (BigInt[1].fromHex"0x0", false), # 0 + (BigInt[1].fromHex"0x0", false)), # 0 + + ((BigInt[1].fromHex"0x0", false), # 0 + (BigInt[64].fromHex"0x8508c00000000001", true), # -x + (BigInt[1].fromHex"0x1", false), # 1 + (BigInt[1].fromHex"0x0", false)), # 0 + + ((BigInt[1].fromHex"0x0", false), # 0 + (BigInt[1].fromHex"0x0", false), # 0 + (BigInt[64].fromHex"0x8508c00000000001", true), # -x + (BigInt[1].fromHex"0x1", false)), # 1 + + ((BigInt[1].fromHex"0x1", false), # 1 + (BigInt[1].fromHex"0x0", false), # 0 + (BigInt[1].fromHex"0x1", true), # -1 + (BigInt[64].fromHex"0x8508c00000000001", true)) # -x +) + +const BLS12_377_Babai_G2* = ( + # Vector for Babai rounding + # Value, isNeg + (BigInt[193].fromHex"0x1eca0125755aed064f63abaff9084ce152979759b442f60d1", true), + (BigInt[130].fromHex"0x3b3f7aa969fd371607f72ed32af90181f", true), + (BigInt[67].fromhex"0x72030ba8ee9c06415", true), + (BigInt[1].fromhex"0x0", false) +) diff --git a/constantine/curves/bls12_377_pairing.nim b/constantine/curves/bls12_377_pairing.nim new file mode 100644 index 0000000..f0c00f7 --- /dev/null +++ b/constantine/curves/bls12_377_pairing.nim @@ -0,0 +1,56 @@ +# Constantine +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Copyright (c) 2020-Present Mamy André-Ratsimbazafy +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + ../config/[curves, type_bigint], + ../towers, + ../io/io_bigints, + ../pairing/cyclotomic_fp12 + +# The bit count must be exact for the Miller loop +const BLS12_377_pairing_ate_param* = block: + # BLS Miller loop is parametrized by u + # +1 so that we can take *3 and NAF encode it + BigInt[64+1].fromHex("0x8508c00000000001") + +const BLS12_377_pairing_ate_param_isNeg* = false + +const BLS12_377_pairing_finalexponent* = block: + # (p^12 - 1) / r + # BigInt[4269].fromHex"0x1b2ff68c1abdc48ab4f04ed12cc8f9b2f161b41c7eb8865b9ad3c9bb0571dd94c6bde66548dc13624d9d741024ceb315f46a89cc2482605eb6afc6d8977e5e2ccbec348dd362d59ec2b5bc62a1b467ae44572215548abc98bb4193886ed89cceaedd0221aba84fb33e5584ac29619a87a00c315178155496857c995eab4a8a9af95f4015db27955ae408d6927d0ab37d52f3917c4ddec88f8159f7bcba7eb65f1aae4eeb4e70cb20227159c08a7fdfea9b62bb308918eac3202569dd1bcdd86b431e3646356fc3fb79f89b30775e006993adb629586b6c874b7688f86f11ef7ad94a40eb020da3c532b317232fa56dc564637b331a8e8832eab84269f00b506602c8594b7f7da5a5d8d851fff6ab1d38a354fc8e0b8958e2a9e5ce2d7e50ec36d761d9505fe5e1f317257e2df2952fcd4c93b85278c20488b4ccaee94db3fec1ce8283473e4b493843fa73abe99af8bafce29170b2b863b9513b5a47312991f60c5a4f6872b5d574212bf00d797c0bea3c0f7dfd748e63679fda9b1c50f2df74de38f38e004ae0df997a10db31d209cacbf58ba0678bfe7cd0985bc43258d72d8d5106c21635ae1e527eb01fca3032d50d97756ec9ee756eaba7f21652a808a4e2539e838ef7ec4b178b29e3b976c46bd0ecdd32c1fb75e6e0aef2d8b5661f595a98023f3520381aba8da6cce785dbb0a0bba025478d75ee749619cdb7c42a21098ece86a00c6c2046c1e00000063c69000000000000" + # (p^12 - 1) / r * 3 + BigInt[4271].fromHex"0x518fe3a450394da01ed0ec73865aed18d4251c557c299312d07b5d31105598be5439b32fda943a26e8d85c306e6c1941dd3f9d646d87211c240f5489c67b1a8663c49da97a2880dc48213527e51d370acd05663ffda035ca31c4ba994c89d66c0c97066502f8ef19bb008e047c24cf96e02493f4683ffdc39075cc1c01df9fd0ec1dc0419176c010ac1a83b777201a77f8dab474e99c59ae840de7362f7c231d500aecc1eb52616067540d419f7f9fbfd22831919b4ac04960703d9753698941c95aa2d2a04f4bf26de9d191661a013cbb09227c09424595e2639ae94d35ce708bdec2c10628eb4f981945698ef049502d2a71994fab9898c028c73dd021f13208590be27e78f0f18a88f5ffe40157a9e9fef5aa229c0aa7fdb16a887af2c4a486258bf11fb1a5d945707a89d7bf8f67e5bb28f76a460d9a1e660cbbe91bfc456b8789d5bae1dba8cbef5b03bcd0ea30f6a7b45218292b2bf3b20ed5937cb5e2250eee395821805c6383d0286c7423beb42e79f85dab2a36df8fd154f2d89e5e9aaadaaa00e0a29ecc6e329195761d6063e0a2e136a3fb7671c9134c970a8588a7f3144642a10a5af77c105f5e90987f28c6604c5dcb604c02f7d642f7f819eea6fadb8aace7c4e146a17dab2c644d4372c6979845f261b4a20cd88a20325e0c0fc806bd9f60a8502fa8f466b6919311e232e06fd6a861cb5dc24d69274c7e631cac6b93e0254460d445a0000012b53b000000000000" + +func pow_x*(r: var Fp12[BLS12_377], a: Fp12[BLS12_377], invert = BLS12_377_pairing_ate_param_isNeg) = + ## f^x with x the curve parameter + ## For BLS12_377 f^-0x8508c00000000001 + ## Warning: The parameter is odd and needs a correction + r.cyclotomic_square(a) + r *= a + r.cyclotomic_square() + r *= a + let t111 = r + + r.cycl_sqr_repeated(2) + let t111000 = r + + r *= t111 + let t100011 = r + + r.cyclotomic_square() + r *= t100011 + r *= t111000 + + r.cycl_sqr_repeated(10) + r *= t100011 + + r.cycl_sqr_repeated(46) + r *= a + + if invert: + r.cyclotomic_inv() diff --git a/constantine/curves/bls12_377_square_root.nim b/constantine/curves/bls12_377_square_root.nim new file mode 100644 index 0000000..8f74af7 --- /dev/null +++ b/constantine/curves/bls12_377_square_root.nim @@ -0,0 +1,20 @@ +# 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 + ../config/[curves, type_bigint, type_fp], + ../io/[io_bigints, io_fields] + +const + # with e = 2adicity + # p == s * 2^e + 1 + # root_of_unity = smallest_quadratic_nonresidue^s + # exponent = (p-1-2^e)/2^e / 2 + BLS12_377_TonelliShanks_exponent* = BigInt[330].fromHex"0x35c748c2f8a21d58c760b80d94292763445b3e601ea271e3de6c45f741290002e16ba88600000010a11" + BLS12_377_TonelliShanks_twoAdicity* = 46 + BLS12_377_TonelliShanks_root_of_unity* = Fp[BLS12_377].fromHex"0x382d3d99cdbc5d8fe9dee6aa914b0ad14fcaca7022110ec6eaa2bc56228ac41ea03d28cc795186ba6b5ef26b00bbe8" diff --git a/constantine/curves/bls12_381_frobenius.nim b/constantine/curves/bls12_381_frobenius.nim new file mode 100644 index 0000000..1d63cd0 --- /dev/null +++ b/constantine/curves/bls12_381_frobenius.nim @@ -0,0 +1,119 @@ +# 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 + ../config/curves, + ../towers, + ../io/io_towers + +# Frobenius map - on extension fields +# ----------------------------------------------------------------- + +# c = (SNR^((p-1)/6)^coef). +# Then for frobenius(2): c * conjugate(c) +# And for frobenius(3): c² * conjugate(c) +const BLS12_381_FrobeniusMapCoefficients* = [ + # frobenius(1) + [Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^0 + "0x1", + "0x0" + ), + Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^1 + "0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8", + "0xfc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3" + ), + Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^2 = SNR^((p-1)/3) + "0x0", + "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac" + ), + Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^3 = SNR^((p-1)/2) + "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09", + "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09" + ), + Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^4 = SNR^(2(p-1)/3) + "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad", + "0x0" + ), + Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^5 + "0x5b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116", + "0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995" + )], + # frobenius(2) + [Fp2[BLS12_381].fromHex( # norm(SNR)^((p-1)/6)^1 + "0x1", + "0x0" + ), + Fp2[BLS12_381].fromHex( # norm(SNR)^((p-1)/6)^2 + "0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffff", + "0x0" + ), + Fp2[BLS12_381].fromHex( + "0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe", + "0x0" + ), + Fp2[BLS12_381].fromHex( + "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa", + "0x0" + ), + Fp2[BLS12_381].fromHex( + "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac", + "0x0" + ), + Fp2[BLS12_381].fromHex( + "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad", + "0x0" + )], + # frobenius(3) + [Fp2[BLS12_381].fromHex( + "0x1", + "0x0" + ), + Fp2[BLS12_381].fromHex( + "0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2", + "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09" + ), + Fp2[BLS12_381].fromHex( + "0x0", + "0x1" + ), + Fp2[BLS12_381].fromHex( + "0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2", + "0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2" + ), + Fp2[BLS12_381].fromHex( + "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa", + "0x0" + ), + Fp2[BLS12_381].fromHex( + "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09", + "0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2" + )]] + +# ψ (Psi) - Untwist-Frobenius-Twist Endomorphisms on twisted curves +# ----------------------------------------------------------------- + +# BLS12_381 is a M-twist: (1/SNR)^((p-1)/6) +const BLS12_381_FrobeniusPsi_psi1_coef1* = Fp2[BLS12_381].fromHex( + "0x5b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116", + "0x5b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116" +) +# (1/SNR)^((p-1)/3) +const BLS12_381_FrobeniusPsi_psi1_coef2* = Fp2[BLS12_381].fromHex( + "0x0", + "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad" +) +# (1/SNR)^((p-1)/2) +const BLS12_381_FrobeniusPsi_psi1_coef3* = Fp2[BLS12_381].fromHex( + "0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2", + "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09" +) +# norm(SNR)^((p-1)/3) +const BLS12_381_FrobeniusPsi_psi2_coef2* = Fp2[BLS12_381].fromHex( + "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac", + "0x0" +) diff --git a/constantine/curves/bls12_381_glv.nim b/constantine/curves/bls12_381_glv.nim new file mode 100644 index 0000000..dab4bfc --- /dev/null +++ b/constantine/curves/bls12_381_glv.nim @@ -0,0 +1,69 @@ +# 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 + ../config/[curves, type_bigint, type_fp], + ../io/[io_bigints, io_fields] + +# BLS12-381 G1 +# ---------------------------------------------------------------------------------------- + +const BLS12_381_cubicRootOfUnity_mod_p* = + Fp[BLS12_381].fromHex"0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac" + +const BLS12_381_Lattice_G1* = ( + # (BigInt, isNeg) + ((BigInt[128].fromHex"0xac45a4010001a40200000000ffffffff", false), # u² - 1 + (BigInt[1].fromHex"0x1", true)), # -1 + ((BigInt[1].fromHex"0x1", false), # 1 + (BigInt[128].fromHex"0xac45a4010001a4020000000100000000", false)) # u² +) + +const BLS12_381_Babai_G1* = ( + # Vector for Babai rounding + # (BigInt, isNeg) + (BigInt[129].fromHex"0x17c6becf1e01faadd63f6e522f6cfee30", false), + (BigInt[2].fromHex"0x2", false) +) + +# BLS12-381 G2 +# ---------------------------------------------------------------------------------------- + +const BLS12_381_Lattice_G2* = ( + # Curve of order 254 -> mini scalars of size 65 + # x = -0xd201000000010000 + # Value, isNeg + ((BigInt[64].fromHex"0xd201000000010000", false), # -x + (BigInt[1].fromHex"0x1", false), # 1 + (BigInt[1].fromHex"0x0", false), # 0 + (BigInt[1].fromHex"0x0", false)), # 0 + + ((BigInt[1].fromHex"0x0", false), # 0 + (BigInt[64].fromHex"0xd201000000010000", false), # -x + (BigInt[1].fromHex"0x1", false), # 1 + (BigInt[1].fromHex"0x0", false)), # 0 + + ((BigInt[1].fromHex"0x0", false), # 0 + (BigInt[1].fromHex"0x0", false), # 0 + (BigInt[64].fromHex"0xd201000000010000", false), # -x + (BigInt[1].fromHex"0x1", false)), # 1 + + ((BigInt[1].fromHex"0x1", false), # 1 + (BigInt[1].fromHex"0x0", false), # 0 + (BigInt[1].fromHex"0x1", true), # -1 + (BigInt[64].fromHex"0xd201000000010000", false)) # -x +) + +const BLS12_381_Babai_G2* = ( + # Vector for Babai rounding + # Value, isNeg + (BigInt[193].fromHex"0x1381204ca56cd56b533cfcc0d3e76ec2892078a5e8573b29c", false), + (BigInt[129].fromHex"0x17c6becf1e01faadd63f6e522f6cfee2f", true), + (BigInt[65].fromhex"0x1cfbe4f7bd0027db0", false), + (BigInt[1].fromhex"0x0", false) +) diff --git a/constantine/curves/bls12_381_inversion.nim b/constantine/curves/bls12_381_inversion.nim new file mode 100644 index 0000000..eb555aa --- /dev/null +++ b/constantine/curves/bls12_381_inversion.nim @@ -0,0 +1,219 @@ +# 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 + ../config/curves, + ../arithmetic/finite_fields + +# ############################################################ +# +# Specialized inversion for BLS12-381 +# +# ############################################################ + +func inv_addchain*(r: var Fp[BLS12_381], a: Fp[BLS12_381]) = + var + x10 {.noinit.}: Fp[BLS12_381] + x100 {.noinit.}: Fp[BLS12_381] + x1000 {.noinit.}: Fp[BLS12_381] + x1001 {.noinit.}: Fp[BLS12_381] + x1011 {.noinit.}: Fp[BLS12_381] + x1101 {.noinit.}: Fp[BLS12_381] + x10001 {.noinit.}: Fp[BLS12_381] + x10100 {.noinit.}: Fp[BLS12_381] + x11001 {.noinit.}: Fp[BLS12_381] + x11010 {.noinit.}: Fp[BLS12_381] + x110100 {.noinit.}: Fp[BLS12_381] + x110110 {.noinit.}: Fp[BLS12_381] + x110111 {.noinit.}: Fp[BLS12_381] + x1001101 {.noinit.}: Fp[BLS12_381] + x1001111 {.noinit.}: Fp[BLS12_381] + x1010101 {.noinit.}: Fp[BLS12_381] + x1011101 {.noinit.}: Fp[BLS12_381] + x1100111 {.noinit.}: Fp[BLS12_381] + x1101001 {.noinit.}: Fp[BLS12_381] + x1110111 {.noinit.}: Fp[BLS12_381] + x1111011 {.noinit.}: Fp[BLS12_381] + x10001001 {.noinit.}: Fp[BLS12_381] + x10010101 {.noinit.}: Fp[BLS12_381] + x10010111 {.noinit.}: Fp[BLS12_381] + x10101001 {.noinit.}: Fp[BLS12_381] + x10110001 {.noinit.}: Fp[BLS12_381] + x10111111 {.noinit.}: Fp[BLS12_381] + x11000011 {.noinit.}: Fp[BLS12_381] + x11010000 {.noinit.}: Fp[BLS12_381] + x11010111 {.noinit.}: Fp[BLS12_381] + x11100001 {.noinit.}: Fp[BLS12_381] + x11100101 {.noinit.}: Fp[BLS12_381] + x11101011 {.noinit.}: Fp[BLS12_381] + x11110101 {.noinit.}: Fp[BLS12_381] + x11111111 {.noinit.}: Fp[BLS12_381] + + x10 .square(a) + x100 .square(x10) + x1000 .square(x100) + x1001 .prod(a, x1000) + x1011 .prod(x10, x1001) + x1101 .prod(x10, x1011) + x10001 .prod(x100, x1101) + x10100 .prod(x1001, x1011) + x11001 .prod(x1000, x10001) + x11010 .prod(a, x11001) + x110100 .square(x11010) + x110110 .prod(x10, x110100) + x110111 .prod(a, x110110) + x1001101 .prod(x11001, x110100) + x1001111 .prod(x10, x1001101) + x1010101 .prod(x1000, x1001101) + x1011101 .prod(x1000, x1010101) + x1100111 .prod(x11010, x1001101) + x1101001 .prod(x10, x1100111) + x1110111 .prod(x11010, x1011101) + x1111011 .prod(x100, x1110111) + x10001001 .prod(x110100, x1010101) + x10010101 .prod(x11010, x1111011) + x10010111 .prod(x10, x10010101) + x10101001 .prod(x10100, x10010101) + x10110001 .prod(x1000, x10101001) + x10111111 .prod(x110110, x10001001) + x11000011 .prod(x100, x10111111) + x11010000 .prod(x1101, x11000011) + x11010111 .prod(x10100, x11000011) + x11100001 .prod(x10001, x11010000) + x11100101 .prod(x100, x11100001) + x11101011 .prod(x10100, x11010111) + x11110101 .prod(x10100, x11100001) + x11111111 .prod(x10100, x11101011) # 35 operations + + # TODO: we can accumulate in a partially reduced + # doubled-size `r` to avoid the final substractions. + # and only reduce at the end. + # This requires the number of op to be less than log2(p) == 381 + + # 35 + 22 = 57 operations + r.prod(x10111111, x11100001) + r.square_repeated(8) + r *= x10001 + r.square_repeated(11) + r *= x11110101 + + # 57 + 28 = 85 operations + r.square_repeated(11) + r *= x11100101 + r.square_repeated(8) + r *= x11111111 + r.square_repeated(7) + + # 88 + 22 = 107 operations + r *= x1001101 + r.square_repeated(9) + r *= x1101001 + r.square_repeated(10) + r *= x10110001 + + # 107+24 = 131 operations + r.square_repeated(7) + r *= x1011101 + r.square_repeated(9) + r *= x1111011 + r.square_repeated(6) + + # 131+23 = 154 operations + r *= x11001 + r.square_repeated(11) + r *= x1101001 + r.square_repeated(9) + r *= x11101011 + + # 154+28 = 182 operations + r.square_repeated(10) + r *= x11010111 + r.square_repeated(6) + r *= x11001 + r.square_repeated(10) + + # 182+23 = 205 operations + r *= x1110111 + r.square_repeated(9) + r *= x10010111 + r.square_repeated(11) + r *= x1001111 + + # 205+30 = 235 operations + r.square_repeated(10) + r *= x11100001 + r.square_repeated(9) + r *= x10001001 + r.square_repeated(9) + + # 235+21 = 256 operations + r *= x10111111 + r.square_repeated(8) + r *= x1100111 + r.square_repeated(10) + r *= x11000011 + + # 256+28 = 284 operations + r.square_repeated(9) + r *= x10010101 + r.square_repeated(12) + r *= x1111011 + r.square_repeated(5) + + # 284 + 21 = 305 operations + r *= x1011 + r.square_repeated(11) + r *= x1111011 + r.square_repeated(7) + r *= x1001 + + # 305+32 = 337 operations + r.square_repeated(13) + r *= x11110101 + r.square_repeated(9) + r *= x10111111 + r.square_repeated(8) + + # 337+22 = 359 operations + r *= x11111111 + r.square_repeated(8) + r *= x11101011 + r.square_repeated(11) + r *= x10101001 + + # 359+24 = 383 operations + r.square_repeated(8) + r *= x11111111 + r.square_repeated(8) + r *= x11111111 + r.square_repeated(6) + + # 383+22 = 405 operations + r *= x110111 + r.square_repeated(10) + r *= x11111111 + r.square_repeated(9) + r *= x11111111 + + # 405+26 = 431 operations + r.square_repeated(8) + r *= x11111111 + r.square_repeated(8) + r *= x11111111 + r.square_repeated(8) + + # 431+19 = 450 operations + r *= x11111111 + r.square_repeated(7) + r *= x1010101 + r.square_repeated(9) + r *= x10101001 + + # Total 450 operations: + # - 74 multiplications + # - 376 squarings diff --git a/constantine/curves/bls12_381_pairing.nim b/constantine/curves/bls12_381_pairing.nim new file mode 100644 index 0000000..9b725e6 --- /dev/null +++ b/constantine/curves/bls12_381_pairing.nim @@ -0,0 +1,51 @@ +# Constantine +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Copyright (c) 2020-Present Mamy André-Ratsimbazafy +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + ../config/[curves, type_bigint], + ../towers, + ../io/io_bigints, + ../pairing/cyclotomic_fp12 + +# The bit count must be exact for the Miller loop +const BLS12_381_pairing_ate_param* = block: + # BLS Miller loop is parametrized by u + BigInt[64+2].fromHex("0xd201000000010000") # +2 so that we can take *3 and NAF encode it + +const BLS12_381_pairing_ate_param_isNeg* = true + +const BLS12_381_pairing_finalexponent* = block: + # (p^12 - 1) / r + # BigInt[4314].fromHex"0x2ee1db5dcc825b7e1bda9c0496a1c0a89ee0193d4977b3f7d4507d07363baa13f8d14a917848517badc3a43d1073776ab353f2c30698e8cc7deada9c0aadff5e9cfee9a074e43b9a660835cc872ee83ff3a0f0f1c0ad0d6106feaf4e347aa68ad49466fa927e7bb9375331807a0dce2630d9aa4b113f414386b0e8819328148978e2b0dd39099b86e1ab656d2670d93e4d7acdd350da5359bc73ab61a0c5bf24c374693c49f570bcd2b01f3077ffb10bf24dde41064837f27611212596bc293c8d4c01f25118790f4684d0b9c40a68eb74bb22a40ee7169cdc1041296532fef459f12438dfc8e2886ef965e61a474c5c85b0129127a1b5ad0463434724538411d1676a53b5a62eb34c05739334f46c02c3f0bd0c55d3109cd15948d0a1fad20044ce6ad4c6bec3ec03ef19592004cedd556952c6d8823b19dadd7c2498345c6e5308f1c511291097db60b1749bf9b71a9f9e0100418a3ef0bc627751bbd81367066bca6a4c1b6dcfc5cceb73fc56947a403577dfa9e13c24ea820b09c1d9f7c31759c3635de3f7a3639991708e88adce88177456c49637fd7961be1a4c7e79fb02faa732e2f3ec2bea83d196283313492caa9d4aff1c910e9622d2a73f62537f2701aaef6539314043f7bbce5b78c7869aeb2181a67e49eeed2161daf3f881bd88592d767f67c4717489119226c2f011d4cab803e9d71650a6f80698e2f8491d12191a04406fbc8fbd5f48925f98630e68bfb24c0bcb9b55df57510" + # (p^12 - 1) / r * 3 + BigInt[4316].fromHex"0x8ca592196587127a538fd40dc3e541f9dca04bb7dc671be77cf17715a2b2fe3bea73dfb468d8f473094aecb7315a664019fbd84913caba6579c08fd42009fe1bd6fcbce15eacb2cf3218a165958cb8bfdae2d2d54207282314fc0dea9d6ff3a07dbd34efb77b732ba5f994816e296a72928cfee133bdc3ca9412b984b9783d9c6aa81297ab1cd294a502304773528bbae8706979f28efa0d355b0224e2513d6e4a5d3bb4dde0523678105d9167ff1323d6e99ac312d8a7d762336370c4347bb5a7e405d6f3496b2dd38e722d4c1f3ac25e3167ec2cb543d69430c37c2f98fcdd0dd36caa9f5aa7994cec31b24ed5e515911037b376e521070d29c9d56cfa8c3574363efb20f28c19e4105ab99edd44084bd23725017931d6740bda71e5f07600ce6b407e543c4bc40bcd4c0b600e6c98003bf8548986b14d9098746dc89d154af91ad54f337b31c79222145dd3ed254fdeda0300c49ebcd2352765f533883a3513435f3ee452496f5166c25bf503bd6ec0a0679efda3b46ebf86211d458de749460d4a2a19abe6ea2accb451ab9a096b98465d044dc2a7f86c253a4ee57b6df108eff598a8dbc483bf8b74c2789939db85ffd7e0fd55b32bc26877f5be26fa7d750500ce2fab93c0cbe7336b126a5693d0c16484f37addccc7642590dbe98538990b88637e374d545d9b34b67448d0357e60280bbd8542f1f4e813caa8e8db57364b4e0cc14f35af381dd9b71ec9292b3a3f16e42362d2019e05f30" + +func pow_xdiv2*(r: var Fp12[BLS12_381], a: Fp12[BLS12_381], invert = BLS12_381_pairing_ate_param_isNeg) = + ## f^(x/2) with x the curve parameter + ## For BLS12_381 f^-0xd201000000010000 + + r.cyclotomic_square(a) + r *= a + r.cycl_sqr_repeated(2) + r *= a + r.cycl_sqr_repeated(3) + r *= a + r.cycl_sqr_repeated(9) + r *= a + r.cycl_sqr_repeated(32) # TODO: use Karabina? + r *= a + r.cycl_sqr_repeated(16-1) # Don't do the last iteration + + if invert: + r.cyclotomic_inv() + +func pow_x*(r: var Fp12[BLS12_381], a: Fp12[BLS12_381], invert = BLS12_381_pairing_ate_param_isNeg) = + ## f^x with x the curve parameter + ## For BLS12_381 f^-0xd201000000010000 + r.pow_xdiv2(a, invert) + r.cyclotomic_square() diff --git a/constantine/curves/bn254_nogami_frobenius.nim b/constantine/curves/bn254_nogami_frobenius.nim new file mode 100644 index 0000000..7209200 --- /dev/null +++ b/constantine/curves/bn254_nogami_frobenius.nim @@ -0,0 +1,119 @@ +# 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 + ../config/curves, + ../towers, + ../io/io_towers + +# Frobenius map - on extension fields +# ----------------------------------------------------------------- + +# c = (SNR^((p-1)/6)^coef). +# Then for frobenius(2): c * conjugate(c) +# And for frobenius(3): c² * conjugate(c) +const BN254_Nogami_FrobeniusMapCoefficients* = [ + # frobenius(1) + [Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^0 + "0x1", + "0x0" + ), + Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^1 + "0x1b377619212e7c8cb6499b50a846953f850974924d3f77c2e17de6c06f2a6de9", + "0x9ebee691ed1837503eab22f57b96ac8dc178b6db2c08850c582193f90d5922a" + ), + Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^2 = SNR^((p-1)/3) + "0x0", + "0x25236482400000017080eb4000000006181800000000000cd98000000000000b" + ), + Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^3 = SNR^((p-1)/2) + "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5", + "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5" + ), + Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^4 = SNR^(2(p-1)/3) + "0x25236482400000017080eb4000000006181800000000000cd98000000000000c", + "0x0" + ), + Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^5 + "0x19f3db6884cdca43c2b0d5792cd135accb1baea0b017046e859975ab54b5ef9b", + "0xb2f8919bb3235bdf7837806d32eca5b9605515f4fe8fba521668a54ab4a1078" + )], + # frobenius(2) + [Fp2[BN254_Nogami].fromHex( # norm(SNR)^((p-1)/6)^1 + "0x1", + "0x0" + ), + Fp2[BN254_Nogami].fromHex( # norm(SNR)^((p-1)/6)^2 + "0x49b36240000000024909000000000006cd80000000000008", + "0x0" + ), + Fp2[BN254_Nogami].fromHex( + "0x49b36240000000024909000000000006cd80000000000007", + "0x0" + ), + Fp2[BN254_Nogami].fromHex( + "0x2523648240000001ba344d80000000086121000000000013a700000000000012", + "0x0" + ), + Fp2[BN254_Nogami].fromHex( + "0x25236482400000017080eb4000000006181800000000000cd98000000000000b", + "0x0" + ), + Fp2[BN254_Nogami].fromHex( + "0x25236482400000017080eb4000000006181800000000000cd98000000000000c", + "0x0" + )], + # frobenius(3) + [Fp2[BN254_Nogami].fromHex( + "0x1", + "0x0" + ), + Fp2[BN254_Nogami].fromHex( + "0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e", + "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5" + ), + Fp2[BN254_Nogami].fromHex( + "0x0", + "0x1" + ), + Fp2[BN254_Nogami].fromHex( + "0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e", + "0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e" + ), + Fp2[BN254_Nogami].fromHex( + "0x2523648240000001ba344d80000000086121000000000013a700000000000012", + "0x0" + ), + Fp2[BN254_Nogami].fromHex( + "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5", + "0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e" + )]] + +# ψ (Psi) - Untwist-Frobenius-Twist Endomorphisms on twisted curves +# ----------------------------------------------------------------- + +# BN254_Snarks is a D-Twist: SNR^((p-1)/6) +const BN254_Nogami_FrobeniusPsi_psi1_coef1* = Fp2[BN254_Nogami].fromHex( + "0x1b377619212e7c8cb6499b50a846953f850974924d3f77c2e17de6c06f2a6de9", + "0x9ebee691ed1837503eab22f57b96ac8dc178b6db2c08850c582193f90d5922a" +) +# SNR^((p-1)/3) +const BN254_Nogami_FrobeniusPsi_psi1_coef2* = Fp2[BN254_Nogami].fromHex( + "0x0", + "0x25236482400000017080eb4000000006181800000000000cd98000000000000b" +) +# SNR^((p-1)/2) +const BN254_Nogami_FrobeniusPsi_psi1_coef3* = Fp2[BN254_Nogami].fromHex( + "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5", + "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5" +) +# norm(SNR)^((p-1)/3) +const BN254_Nogami_FrobeniusPsi_psi2_coef2* = Fp2[BN254_Nogami].fromHex( + "0x49b36240000000024909000000000006cd80000000000007", + "0x0" +) diff --git a/constantine/curves/bn254_nogami_pairing.nim b/constantine/curves/bn254_nogami_pairing.nim new file mode 100644 index 0000000..2627847 --- /dev/null +++ b/constantine/curves/bn254_nogami_pairing.nim @@ -0,0 +1,37 @@ +# 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 + ../config/[curves, type_bigint], + ../towers, + ../io/io_bigints, + ../pairing/cyclotomic_fp12 + +# The bit count must be exact for the Miller loop +const BN254_Nogami_pairing_ate_param* = block: + # BN Miller loop is parametrized by 6u+2 + # 65+2 bit for NAF x3 encoding + BigInt[65+2].fromHex"0x18300000000000004" + +const BN254_Nogami_pairing_ate_param_isNeg* = true + +const BN254_Nogami_pairing_finalexponent* = block: + # (p^12 - 1) / r + BigInt[2786].fromHex"0x2928fbb36b391596ee3fe4cbe857330da83e46fedf04d235a4a8daf5ff9f6eabcb4e3f20aa06f0a0d96b24f9af0cbbce750d61627dcbf5fec9139b8f1c46c86b49b4f8a202af26e4504f2c0f56570e9bd5b94c403f385d1908556486e24b396ddc2cdf13d06542f84fe8e82ccbad7b7423fc1ef4e8cc73d605e3e867c0a75f45ea7f6356d9846ce35d5a34f30396938818ad41914b97b99c289a7259b5d2e09477a77bd3c409b19f19e893f8ade90b0aed1b5fc8a07a3cebb41d4e9eee96b21a832ddb1e93e113edfb704fa532848c18593cd0ee90444a1b3499a800177ea38bdec62ec5191f2b6bbee449722f98d2173ad33077545c2ad10347e125a56fb40f086e9a4e62ad336a72c8b202ac3c1473d73b93d93dc0795ca0ca39226e7b4c1bb92f99248ec0806e0ad70744e9f2238736790f5185ea4c70808442a7d530c6ccd56b55a6973867ec6c73599bbd020bbe105da9c6b5c009ad8946cd6f0" + +func pow_u*(r: var Fp12[BN254_Nogami], a: Fp12[BN254_Nogami], invert = BN254_Nogami_pairing_ate_param_isNeg) = + ## f^u with u the curve parameter + ## For BN254_Nogami f^-0x4080000000000001 + r = a + r.cycl_sqr_repeated(7) + r *= a + r.cycl_sqr_repeated(55) + r *= a + + if invert: + r.cyclotomic_inv() diff --git a/constantine/curves/bn254_snarks_frobenius.nim b/constantine/curves/bn254_snarks_frobenius.nim new file mode 100644 index 0000000..1aab674 --- /dev/null +++ b/constantine/curves/bn254_snarks_frobenius.nim @@ -0,0 +1,119 @@ +# 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 + ../config/curves, + ../towers, + ../io/io_towers + +# Frobenius map - on extension fields +# ----------------------------------------------------------------- + +# c = (SNR^((p-1)/6)^coef). +# Then for frobenius(2): c * conjugate(c) +# And for frobenius(3): c² * conjugate(c) +const BN254_Snarks_FrobeniusMapCoefficients* = [ + # frobenius(1) + [Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^0 + "0x1", + "0x0" + ), + Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^1 + "0x1284b71c2865a7dfe8b99fdd76e68b605c521e08292f2176d60b35dadcc9e470", + "0x246996f3b4fae7e6a6327cfe12150b8e747992778eeec7e5ca5cf05f80f362ac" + ), + Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^2 = SNR^((p-1)/3) + "0x2fb347984f7911f74c0bec3cf559b143b78cc310c2c3330c99e39557176f553d", + "0x16c9e55061ebae204ba4cc8bd75a079432ae2a1d0b7c9dce1665d51c640fcba2" + ), + Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^3 = SNR^((p-1)/2) + "0x63cf305489af5dcdc5ec698b6e2f9b9dbaae0eda9c95998dc54014671a0135a", + "0x7c03cbcac41049a0704b5a7ec796f2b21807dc98fa25bd282d37f632623b0e3" + ), + Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^4 = SNR^(2(p-1)/3) + "0x5b54f5e64eea80180f3c0b75a181e84d33365f7be94ec72848a1f55921ea762", + "0x2c145edbe7fd8aee9f3a80b03b0b1c923685d2ea1bdec763c13b4711cd2b8126" + ), + Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^5 + "0x183c1e74f798649e93a3661a4353ff4425c459b55aa1bd32ea2c810eab7692f", + "0x12acf2ca76fd0675a27fb246c7729f7db080cb99678e2ac024c6b8ee6e0c2c4b" + )], + # frobenius(2) + [Fp2[BN254_Snarks].fromHex( # norm(SNR)^((p-1)/6)^1 + "0x1", + "0x0" + ), + Fp2[BN254_Snarks].fromHex( # norm(SNR)^((p-1)/6)^2 + "0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd49", + "0x0" + ), + Fp2[BN254_Snarks].fromHex( + "0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48", + "0x0" + ), + Fp2[BN254_Snarks].fromHex( + "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46", + "0x0" + ), + Fp2[BN254_Snarks].fromHex( + "0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe", + "0x0" + ), + Fp2[BN254_Snarks].fromHex( + "0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177ffffff", + "0x0" + )], + # frobenius(3) + [Fp2[BN254_Snarks].fromHex( + "0x1", + "0x0" + ), + Fp2[BN254_Snarks].fromHex( + "0x19dc81cfcc82e4bbefe9608cd0acaa90894cb38dbe55d24ae86f7d391ed4a67f", + "0xabf8b60be77d7306cbeee33576139d7f03a5e397d439ec7694aa2bf4c0c101" + ), + Fp2[BN254_Snarks].fromHex( + "0x856e078b755ef0abaff1c77959f25ac805ffd3d5d6942d37b746ee87bdcfb6d", + "0x4f1de41b3d1766fa9f30e6dec26094f0fdf31bf98ff2631380cab2baaa586de" + ), + Fp2[BN254_Snarks].fromHex( + "0x2a275b6d9896aa4cdbf17f1dca9e5ea3bbd689a3bea870f45fcc8ad066dce9ed", + "0x28a411b634f09b8fb14b900e9507e9327600ecc7d8cf6ebab94d0cb3b2594c64" + ), + Fp2[BN254_Snarks].fromHex( + "0xbc58c6611c08dab19bee0f7b5b2444ee633094575b06bcb0e1a92bc3ccbf066", + "0x23d5e999e1910a12feb0f6ef0cd21d04a44a9e08737f96e55fe3ed9d730c239f" + ), + Fp2[BN254_Snarks].fromHex( + "0x13c49044952c0905711699fa3b4d3f692ed68098967c84a5ebde847076261b43", + "0x16db366a59b1dd0b9fb1b2282a48633d3e2ddaea200280211f25041384282499" + )]] + +# ψ (Psi) - Untwist-Frobenius-Twist Endomorphisms on twisted curves +# ----------------------------------------------------------------- + +# BN254_Snarks is a D-Twist: SNR^((p-1)/6) +const BN254_Snarks_FrobeniusPsi_psi1_coef1* = Fp2[BN254_Snarks].fromHex( + "0x1284b71c2865a7dfe8b99fdd76e68b605c521e08292f2176d60b35dadcc9e470", + "0x246996f3b4fae7e6a6327cfe12150b8e747992778eeec7e5ca5cf05f80f362ac" +) +# SNR^((p-1)/3) +const BN254_Snarks_FrobeniusPsi_psi1_coef2* = Fp2[BN254_Snarks].fromHex( + "0x2fb347984f7911f74c0bec3cf559b143b78cc310c2c3330c99e39557176f553d", + "0x16c9e55061ebae204ba4cc8bd75a079432ae2a1d0b7c9dce1665d51c640fcba2" +) +# SNR^((p-1)/2) +const BN254_Snarks_FrobeniusPsi_psi1_coef3* = Fp2[BN254_Snarks].fromHex( + "0x63cf305489af5dcdc5ec698b6e2f9b9dbaae0eda9c95998dc54014671a0135a", + "0x7c03cbcac41049a0704b5a7ec796f2b21807dc98fa25bd282d37f632623b0e3" +) +# norm(SNR)^((p-1)/3) +const BN254_Snarks_FrobeniusPsi_psi2_coef2* = Fp2[BN254_Snarks].fromHex( + "0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48", + "0x0" +) diff --git a/constantine/curves/bn254_snarks_glv.nim b/constantine/curves/bn254_snarks_glv.nim new file mode 100644 index 0000000..d262f5e --- /dev/null +++ b/constantine/curves/bn254_snarks_glv.nim @@ -0,0 +1,72 @@ +# 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 + ../config/[curves, type_bigint, type_fp], + ../io/[io_bigints, io_fields] + +# BN254 Snarks G1 +# ---------------------------------------------------------------------------------------- + +const BN254_Snarks_cubicRootofUnity_mod_p* = + Fp[BN254_Snarks].fromHex"0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48" + +# Chapter 6.3.1 - Guide to Pairing-based Cryptography +const BN254_Snarks_Lattice_G1* = ( + # Curve of order 254 -> mini scalars of size 127 + # u = 0x44E992B44A6909F1 + # (BigInt, isNeg) + ((BigInt[64].fromHex"0x89d3256894d213e3", false), # 2u + 1 + (BigInt[127].fromHex"0x6f4d8248eeb859fd0be4e1541221250b", false)), # 6u² + 4u + 1 + ((BigInt[127].fromHex"0x6f4d8248eeb859fc8211bbeb7d4f1128", false), # 6u² + 2u + (BigInt[64].fromHex"0x89d3256894d213e3", true)) # -2u - 1 +) + +const BN254_Snarks_Babai_G1* = ( + # Vector for Babai rounding + # (BigInt, isNeg) + (BigInt[66].fromHex"0x2d91d232ec7e0b3d7", false), # (2u + 1) << 2^256 // r + (BigInt[130].fromHex"0x24ccef014a773d2d25398fd0300ff6565", false) # (6u² + 4u + 1) << 2^256 // r +) + +# BN254 Snarks G2 +# ---------------------------------------------------------------------------------------- + +const BN254_Snarks_Lattice_G2* = ( + # Curve of order 254 -> mini scalars of size 65 + # x = 0x44E992B44A6909F1 + # Value, isNeg + ((BigInt[63].fromHex"0x44e992b44a6909f2", false), # x+1 + (BigInt[63].fromHex"0x44e992b44a6909f1", false), # x + (BigInt[63].fromHex"0x44e992b44a6909f1", false), # x + (BigInt[64].fromHex"0x89d3256894d213e2", true)), # -2x + + ((BigInt[64].fromHex"0x89d3256894d213e3", false), # 2x+1 + (BigInt[63].fromHex"0x44e992b44a6909f1", true), # -x + (BigInt[63].fromHex"0x44e992b44a6909f2", true), # -x-1 + (BigInt[63].fromHex"0x44e992b44a6909f1", true)), # -x + + ((BigInt[64].fromHex"0x89d3256894d213e2", false), # 2x + (BigInt[64].fromHex"0x89d3256894d213e3", false), # 2x+1 + (BigInt[64].fromHex"0x89d3256894d213e3", false), # 2x+1 + (BigInt[64].fromHex"0x89d3256894d213e3", false)), # 2x+1 + + ((BigInt[63].fromHex"0x44e992b44a6909f0", false), # x-1 + (BigInt[65].fromHex"0x113a64ad129a427c6", false), # 4x+2 + (BigInt[64].fromHex"0x89d3256894d213e1", true), # -2x+1 + (BigInt[63].fromHex"0x44e992b44a6909f0", false)), # x-1 + ) + +const BN254_Snarks_Babai_G2* = ( + # Vector for Babai rounding + # Value, isNeg + (BigInt[128].fromHex"0xc444fab18d269b9dd0cb46fd51906254", false), # 2x²+3x+1 << 2^256 // r + (BigInt[193].fromHex"0x13d00631561b2572922df9f942d7d77c7001378f5ee78976d", false), # 3x³+8x²+x << 2^256 // r + (BigInt[192].fromhex"0x9e80318ab0d92b94916fcfca16bebbe436510546a93478ab", false), # 6x³+4x²+x << 2^256 // r + (BigInt[128].fromhex"0xc444fab18d269b9af7ae23ce89afae7d", true) # -2x²-x << 2^256 // r +) diff --git a/constantine/curves/bn254_snarks_inversion.nim b/constantine/curves/bn254_snarks_inversion.nim new file mode 100644 index 0000000..8409259 --- /dev/null +++ b/constantine/curves/bn254_snarks_inversion.nim @@ -0,0 +1,158 @@ +# 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 + ../config/curves, + ../arithmetic/finite_fields + +# ############################################################ +# +# Specialized inversion for BN254-Snarks +# +# ############################################################ + +func inv_addchain*(r: var Fp[BN254_Snarks], a: Fp[BN254_Snarks]) = + var + x10 {.noInit.}: Fp[BN254_Snarks] + x11 {.noInit.}: Fp[BN254_Snarks] + x101 {.noInit.}: Fp[BN254_Snarks] + x110 {.noInit.}: Fp[BN254_Snarks] + x1000 {.noInit.}: Fp[BN254_Snarks] + x1101 {.noInit.}: Fp[BN254_Snarks] + x10010 {.noInit.}: Fp[BN254_Snarks] + x10011 {.noInit.}: Fp[BN254_Snarks] + x10100 {.noInit.}: Fp[BN254_Snarks] + x10111 {.noInit.}: Fp[BN254_Snarks] + x11100 {.noInit.}: Fp[BN254_Snarks] + x100000 {.noInit.}: Fp[BN254_Snarks] + x100011 {.noInit.}: Fp[BN254_Snarks] + x101011 {.noInit.}: Fp[BN254_Snarks] + x101111 {.noInit.}: Fp[BN254_Snarks] + x1000001 {.noInit.}: Fp[BN254_Snarks] + x1010011 {.noInit.}: Fp[BN254_Snarks] + x1011011 {.noInit.}: Fp[BN254_Snarks] + x1100001 {.noInit.}: Fp[BN254_Snarks] + x1110101 {.noInit.}: Fp[BN254_Snarks] + x10010001 {.noInit.}: Fp[BN254_Snarks] + x10010101 {.noInit.}: Fp[BN254_Snarks] + x10110101 {.noInit.}: Fp[BN254_Snarks] + x10111011 {.noInit.}: Fp[BN254_Snarks] + x11000001 {.noInit.}: Fp[BN254_Snarks] + x11000011 {.noInit.}: Fp[BN254_Snarks] + x11010011 {.noInit.}: Fp[BN254_Snarks] + x11100001 {.noInit.}: Fp[BN254_Snarks] + x11100011 {.noInit.}: Fp[BN254_Snarks] + x11100111 {.noInit.}: Fp[BN254_Snarks] + + x10 .square(a) + x11 .prod(x10, a) + x101 .prod(x10, x11) + x110 .prod(x101, a) + x1000 .prod(x10, x110) + x1101 .prod(x101, x1000) + x10010 .prod(x101, x1101) + x10011 .prod(x10010, a) + x10100 .prod(x10011, a) + x10111 .prod(x11, x10100) + x11100 .prod(x101, x10111) + x100000 .prod(x1101, x10011) + x100011 .prod(x11, x100000) + x101011 .prod(x1000, x100011) + x101111 .prod(x10011, x11100) + x1000001 .prod(x10010, x101111) + x1010011 .prod(x10010, x1000001) + x1011011 .prod(x1000, x1010011) + x1100001 .prod(x110, x1011011) + x1110101 .prod(x10100, x1100001) + x10010001 .prod(x11100, x1110101) + x10010101 .prod(x100000, x1110101) + x10110101 .prod(x100000, x10010101) + x10111011 .prod(x110, x10110101) + x11000001 .prod(x110, x10111011) + x11000011 .prod(x10, x11000001) + x11010011 .prod(x10010, x11000001) + x11100001 .prod(x100000, x11000001) + x11100011 .prod(x10, x11100001) + x11100111 .prod(x110, x11100001) # 30 operations + + # 30 + 27 = 57 operations + r.square(x11000001) + r.square_repeated(7) + r *= x10010001 + r.square_repeated(10) + r *= x11100111 + r.square_repeated(7) + + # 57 + 19 = 76 operations + r *= x10111 + r.square_repeated(9) + r *= x10011 + r.square_repeated(7) + r *= x1101 + + # 76 + 33 = 109 operations + r.square_repeated(14) + r *= x1010011 + r.square_repeated(9) + r *= x11100001 + r.square_repeated(8) + + # 109 + 18 = 127 operations + r *= x1000001 + r.square_repeated(10) + r *= x1011011 + r.square_repeated(5) + r *= x1101 + + # 127 + 34 = 161 operations + r.square_repeated(8) + r *= x11 + r.square_repeated(12) + r *= x101011 + r.square_repeated(12) + + # 161 + 25 = 186 operations + r *= x10111011 + r.square_repeated(8) + r *= x101111 + r.square_repeated(14) + r *= x10110101 + + # 186 + 28 = 214 + r.square_repeated(9) + r *= x10010001 + r.square_repeated(5) + r *= x1101 + r.square_repeated(12) + + # 214 + 22 = 236 + r *= x11100011 + r.square_repeated(8) + r *= x10010101 + r.square_repeated(11) + r *= x11010011 + + # 236 + 32 = 268 + r.square_repeated(7) + r *= x1100001 + r.square_repeated(11) + r *= x100011 + r.square_repeated(12) + + # 268 + 20 = 288 + r *= x1011011 + r.square_repeated(9) + r *= x11000011 + r.square_repeated(8) + r *= x11100111 + + # 288 + 15 = 303 + r.square_repeated(7) + r *= x1110101 + r.square_repeated(6) + r *= x101 diff --git a/constantine/curves/bn254_snarks_pairing.nim b/constantine/curves/bn254_snarks_pairing.nim new file mode 100644 index 0000000..19d3184 --- /dev/null +++ b/constantine/curves/bn254_snarks_pairing.nim @@ -0,0 +1,107 @@ +# 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 + ../config/[curves, type_bigint], + ../towers, + ../io/io_bigints, + ../pairing/cyclotomic_fp12 + +# The bit count must be exact for the Miller loop +const BN254_Snarks_pairing_ate_param* = block: + # BN Miller loop is parametrized by 6u+2 + BigInt[65+2].fromHex"0x19d797039be763ba8" + +const BN254_Snarks_pairing_ate_param_isNeg* = false + +const BN254_Snarks_pairing_finalexponent* = block: + # (p^12 - 1) / r + BigInt[2790].fromHex"0x2f4b6dc97020fddadf107d20bc842d43bf6369b1ff6a1c71015f3f7be2e1e30a73bb94fec0daf15466b2383a5d3ec3d15ad524d8f70c54efee1bd8c3b21377e563a09a1b705887e72eceaddea3790364a61f676baaf977870e88d5c6c8fef0781361e443ae77f5b63a2a2264487f2940a8b1ddb3d15062cd0fb2015dfc6668449aed3cc48a82d0d602d268c7daab6a41294c0cc4ebe5664568dfc50e1648a45a4a1e3a5195846a3ed011a337a02088ec80e0ebae8755cfe107acf3aafb40494e406f804216bb10cf430b0f37856b42db8dc5514724ee93dfb10826f0dd4a0364b9580291d2cd65664814fde37ca80bb4ea44eacc5e641bbadf423f9a2cbf813b8d145da90029baee7ddadda71c7f3811c4105262945bba1668c3be69a3c230974d83561841d766f9c9d570bb7fbe04c7e8a6c3c760c0de81def35692da361102b6b9b2b918837fa97896e84abb40a4efb7e54523a486964b64ca86f120" + +func pow_u*(r: var Fp12[BN254_Snarks], a: Fp12[BN254_Snarks], invert = BN254_Snarks_pairing_ate_param_isNeg) = + ## f^u with u the curve parameter + ## For BN254_Snarks f^0x44e992b44a6909f1 + when false: + cyclotomic_exp( + r, a, + BigInt[63].fromHex("0x44e992b44a6909f1"), + invert + ) + else: + var # Hopefully the compiler optimizes away unused Fp12 + # because those are huge + x10 {.noInit.}: Fp12[BN254_Snarks] + x11 {.noInit.}: Fp12[BN254_Snarks] + x100 {.noInit.}: Fp12[BN254_Snarks] + x110 {.noInit.}: Fp12[BN254_Snarks] + x1100 {.noInit.}: Fp12[BN254_Snarks] + x1111 {.noInit.}: Fp12[BN254_Snarks] + x10010 {.noInit.}: Fp12[BN254_Snarks] + x10110 {.noInit.}: Fp12[BN254_Snarks] + x11100 {.noInit.}: Fp12[BN254_Snarks] + x101110 {.noInit.}: Fp12[BN254_Snarks] + x1001010 {.noInit.}: Fp12[BN254_Snarks] + x1111000 {.noInit.}: Fp12[BN254_Snarks] + x10001110 {.noInit.}: Fp12[BN254_Snarks] + + x10 .cyclotomic_square(a) + x11 .prod(x10, a) + x100 .prod(x11, a) + x110 .prod(x10, x100) + x1100 .cyclotomic_square(x110) + x1111 .prod(x11, x1100) + x10010 .prod(x11, x1111) + x10110 .prod(x100, x10010) + x11100 .prod(x110, x10110) + x101110 .prod(x10010, x11100) + x1001010 .prod(x11100, x101110) + x1111000 .prod(x101110, x1001010) + x10001110 .prod(x10110, x1111000) + + var + i15 {.noInit.}: Fp12[BN254_Snarks] + i16 {.noInit.}: Fp12[BN254_Snarks] + i17 {.noInit.}: Fp12[BN254_Snarks] + i18 {.noInit.}: Fp12[BN254_Snarks] + i20 {.noInit.}: Fp12[BN254_Snarks] + i21 {.noInit.}: Fp12[BN254_Snarks] + i22 {.noInit.}: Fp12[BN254_Snarks] + i26 {.noInit.}: Fp12[BN254_Snarks] + i27 {.noInit.}: Fp12[BN254_Snarks] + i61 {.noInit.}: Fp12[BN254_Snarks] + + i15.cyclotomic_square(x10001110) + i15 *= x1001010 + i16.prod(x10001110, i15) + i17.prod(x1111, i16) + i18.prod(i16, i17) + + i20.cyclotomic_square(i18) + i20 *= i17 + i21.prod(x1111000, i20) + i22.prod(i15, i21) + + i26.cyclotomic_square(i22) + i26.cyclotomic_square() + i26 *= i22 + i26 *= i18 + + i27.prod(i22, i26) + + i61.prod(i26, i27) + i61.cycl_sqr_repeated(17) + i61 *= i27 + i61.cycl_sqr_repeated(14) + i61 *= i21 + + r = i61 + r.cycl_sqr_repeated(16) + r *= i20 + + if invert: + r.cyclotomic_inv() diff --git a/constantine/curves/secp256k1_inversion.nim b/constantine/curves/secp256k1_inversion.nim new file mode 100644 index 0000000..b5fd0d5 --- /dev/null +++ b/constantine/curves/secp256k1_inversion.nim @@ -0,0 +1,96 @@ +# 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 + ../config/curves, + ../arithmetic/finite_fields + +# ############################################################ +# +# Specialized inversion for Secp256k1 +# +# ############################################################ + +func inv_addchain*(r: var Fp[Secp256k1], a: Fp[Secp256k1]) {.used.}= + ## We invert via Little Fermat's theorem + ## a^(-1) ≡ a^(p-2) (mod p) + ## with p = "0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F" + ## We take advantage of the prime special form to hardcode + ## the sequence of squarings and multiplications for the modular exponentiation + ## + ## See libsecp256k1 + ## + ## The binary representation of (p - 2) has 5 blocks of 1s, with lengths in + ## { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: + ## [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] + + var + x2{.noInit.}: Fp[Secp256k1] + x3{.noInit.}: Fp[Secp256k1] + x6{.noInit.}: Fp[Secp256k1] + x9{.noInit.}: Fp[Secp256k1] + x11{.noInit.}: Fp[Secp256k1] + x22{.noInit.}: Fp[Secp256k1] + x44{.noInit.}: Fp[Secp256k1] + x88{.noInit.}: Fp[Secp256k1] + x176{.noInit.}: Fp[Secp256k1] + x220{.noInit.}: Fp[Secp256k1] + x223{.noInit.}: Fp[Secp256k1] + + x2.square(a) + x2 *= a + + x3.square(x2) + x3 *= a + + x6 = x3 + x6.square_repeated(3) + x6 *= x3 + + x9 = x6 + x9.square_repeated(3) + x9 *= x3 + + x11 = x9 + x11.square_repeated(2) + x11 *= x2 + + x22 = x11 + x22.square_repeated(11) + x22 *= x11 + + x44 = x22 + x44.square_repeated(22) + x44 *= x22 + + x88 = x44 + x88.square_repeated(44) + x88 *= x44 + + x176 = x88 + x88.square_repeated(88) + x176 *= x88 + + x220 = x176 + x220.square_repeated(44) + x220 *= x44 + + x223 = x220 + x223.square_repeated(3) + x223 *= x3 + + # The final result is then assembled using a sliding window over the blocks + r = x223 + r.square_repeated(23) + r *= x22 + r.square_repeated(5) + r *= a + r.square_repeated(3) + r *= x2 + r.square_repeated(2) + r *= a diff --git a/constantine/curves/zoo_frobenius.nim b/constantine/curves/zoo_frobenius.nim new file mode 100644 index 0000000..6c8d5e1 --- /dev/null +++ b/constantine/curves/zoo_frobenius.nim @@ -0,0 +1,34 @@ +# Constantine +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Copyright (c) 2020-Present Mamy André-Ratsimbazafy +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + std/macros, + ../config/curves, + ./bls12_377_frobenius, + ./bls12_381_frobenius, + ./bn254_nogami_frobenius, + ./bn254_snarks_frobenius + +{.experimental: "dynamicBindSym".} + +macro frobMapConst*(C: static Curve, coef, p_pow: static int): untyped = + ## Access the field Frobenius map a -> a^(p^p_pow) + ## Call with + ## frobMapConst(Curve, coef, p_pow) + ## + ## With pow the + return nnkBracketExpr.newTree( + nnkBracketExpr.newTree( + bindSym($C & "_FrobeniusMapCoefficients"), + newLit(p_pow-1) + ), + newLit coef + ) + +macro frobPsiConst*(C: static Curve, psipow, coefpow: static int): untyped = + return bindSym($C & "_FrobeniusPsi_psi" & $psipow & "_coef" & $coefpow) diff --git a/constantine/curves/zoo_glv.nim b/constantine/curves/zoo_glv.nim new file mode 100644 index 0000000..6a9f421 --- /dev/null +++ b/constantine/curves/zoo_glv.nim @@ -0,0 +1,37 @@ +# Constantine +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Copyright (c) 2020-Present Mamy André-Ratsimbazafy +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + std/macros, + ../config/[curves, type_fp], + ../towers, + ./bls12_377_glv, + ./bls12_381_glv, + # ./bn254_nogami_glv, + ./bn254_snarks_glv + +{.experimental: "dynamicBindSym".} + +macro dispatch(C: static Curve, tag: static string, G: static string): untyped = + result = bindSym($C & "_" & tag & "_" & G) + +template babai*(F: typedesc[Fp or Fp2]): untyped = + ## Return the GLV Babai roundings vector + const G = if F is Fp: "G1" + else: "G2" + dispatch(F.C, "Babai", G) + +template lattice*(F: typedesc[Fp or Fp2]): untyped = + ## Returns the GLV Decomposition Lattice + const G = if F is Fp: "G1" + else: "G2" + dispatch(F.C, "Lattice", G) + +macro getCubicRootOfUnity_mod_p*(C: static Curve): untyped = + ## Get a non-trivial cubic root of unity (mod p) with p the prime field + result = bindSym($C & "_cubicRootOfUnity_mod_p") diff --git a/constantine/curves/zoo_inversions.nim b/constantine/curves/zoo_inversions.nim new file mode 100644 index 0000000..b9e20d8 --- /dev/null +++ b/constantine/curves/zoo_inversions.nim @@ -0,0 +1,17 @@ +# 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 + ./bls12_381_inversion, + ./bn254_snarks_inversion, + ./secp256k1_inversion + +export + bls12_381_inversion, + bn254_snarks_inversion, + secp256k1_inversion diff --git a/constantine/curves/zoo_pairings.nim b/constantine/curves/zoo_pairings.nim new file mode 100644 index 0000000..c25ac21 --- /dev/null +++ b/constantine/curves/zoo_pairings.nim @@ -0,0 +1,23 @@ +# Constantine +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Copyright (c) 2020-Present Mamy André-Ratsimbazafy +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + std/macros, + ../config/curves, + ./bls12_377_pairing, + ./bls12_381_pairing, + ./bn254_nogami_pairing, + ./bn254_snarks_pairing + +{.experimental: "dynamicBindSym".} + +macro pairing*(C: static Curve, value: untyped): untyped = + ## Get pairing related constants + return bindSym($C & "_pairing_" & $value) + +export pow_x, pow_xdiv2, pow_u diff --git a/constantine/curves/zoo_square_roots.nim b/constantine/curves/zoo_square_roots.nim new file mode 100644 index 0000000..1b52b53 --- /dev/null +++ b/constantine/curves/zoo_square_roots.nim @@ -0,0 +1,18 @@ +# Constantine +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Copyright (c) 2020-Present Mamy André-Ratsimbazafy +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + std/macros, + ../config/curves, + ./bls12_377_square_root + +{.experimental: "dynamicBindSym".} + +macro tonelliShanks*(C: static Curve, value: untyped): untyped = + ## Get Square Root via Tonelli-Shanks related constants + return bindSym($C & "_TonelliShanks_" & $value) diff --git a/constantine/elliptic/README.md b/constantine/elliptic/README.md index 82c345d..a0d5021 100644 --- a/constantine/elliptic/README.md +++ b/constantine/elliptic/README.md @@ -117,6 +117,12 @@ We use the complete addition law from Bos2014 for Jacobian coordinates, note tha https://eprint.iacr.org/2014/130 https://www.imsc.res.in/~ecc14/slides/costello.pdf +- Efficient and Secure Algorithms for GLV-Based Scalar\ + Multiplication and their Implementation\ + on GLV-GLSCurves (Extended Version)\ + Armando Faz-Hernández, Patrick Longa, Ana H. Sánchez, 2013\ + https://eprint.iacr.org/2013/158.pdf + - Remote Timing Attacks are Still Practical\ Billy Bob Brumley and Nicola Tuveri\ https://eprint.iacr.org/2011/232 diff --git a/constantine/elliptic/ec_endomorphism_accel.nim b/constantine/elliptic/ec_endomorphism_accel.nim index 058fd46..992b24f 100644 --- a/constantine/elliptic/ec_endomorphism_accel.nim +++ b/constantine/elliptic/ec_endomorphism_accel.nim @@ -12,13 +12,13 @@ import # Internal ../primitives, ../config/[common, curves, type_bigint], + ../curves/zoo_glv, ../arithmetic, ../io/io_bigints, ../towers, ../isogeny/frobenius, ./ec_weierstrass_affine, - ./ec_weierstrass_projective, - ./ec_endomorphism_params + ./ec_weierstrass_projective # ############################################################ # @@ -33,6 +33,84 @@ import # - GLV and GLS endomorphisms on G2 (Galbraith-Lin-Scott) # - NAF recoding (windowed Non-Adjacent-Form) +# Decomposition into scalars -> miniscalars +# ---------------------------------------------------------------------------------------- + +type + MultiScalar[M, LengthInBits: static int] = array[M, BigInt[LengthInBits]] + ## Decomposition of a secret scalar in multiple scalars + +func decomposeEndo*[M, scalBits, L: static int]( + miniScalars: var MultiScalar[M, L], + scalar: BigInt[scalBits], + F: typedesc[Fp or Fp2] + ) = + ## Decompose a secret scalar into M mini-scalars + ## using a curve endomorphism(s) characteristics. + ## + ## A scalar decomposition might lead to negative miniscalar(s). + ## For proper handling it requires either: + ## 1. Negating it and then negating the corresponding curve point P + ## 2. Adding an extra bit to the recoding, which will do the right thing™ + ## + ## For implementation solution 1 is faster: + ## - Double + Add is about 5000~8000 cycles on 6 64-bits limbs (BLS12-381) + ## - Conditional negate is about 10 cycles per Fp, on G2 projective we have 3 (coords) * 2 (Fp2) * 10 (cycles) ~= 60 cycles + ## We need to test the mini scalar, which is 65 bits so 2 Fp so about 2 cycles + ## and negate it as well. + ## + ## However solution 1 seems to cause issues (TODO) + ## with some of the BLS12-381 test cases (6 and 9) + ## - 0x5668a2332db27199dcfb7cbdfca6317c2ff128db26d7df68483e0a095ec8e88f + ## - 0x644dc62869683f0c93f38eaef2ba6912569dc91ec2806e46b4a3dd6a4421dad1 + + # Equal when no window or no negative handling, greater otherwise + static: doAssert L >= (scalBits + M - 1) div M + 1 + const w = F.C.getCurveOrderBitwidth().wordsRequired() + + when F is Fp: + var alphas{.noInit.}: ( + BigInt[scalBits + babai(F)[0][0].bits], + BigInt[scalBits + babai(F)[1][0].bits] + ) + else: + var alphas{.noInit.}: ( + BigInt[scalBits + babai(F)[0][0].bits], + BigInt[scalBits + babai(F)[1][0].bits], + BigInt[scalBits + babai(F)[2][0].bits], + BigInt[scalBits + babai(F)[3][0].bits] + ) + + staticFor i, 0, M: + when bool babai(F)[i][0].isZero(): + alphas[i].setZero() + else: + alphas[i].prod_high_words(babai(F)[i][0], scalar, w) + when babai(F)[i][1]: + # prod_high_words works like logical right shift + # When negative, we should add 1 to properly round toward -infinity + alphas[i] += SecretWord(1) + + # We have k0 = s - 𝛼0 b00 - 𝛼1 b10 ... - 𝛼m bm0 + # and kj = 0 - 𝛼j b0j - 𝛼1 b1j ... - 𝛼m bmj + var + k: array[M, BigInt[scalBits]] # zero-init required + alphaB {.noInit.}: BigInt[scalBits] + k[0] = scalar + staticFor miniScalarIdx, 0, M: + staticFor basisIdx, 0, M: + when not bool lattice(F)[basisIdx][miniScalarIdx][0].isZero(): + when bool lattice(F)[basisIdx][miniScalarIdx][0].isOne(): + alphaB.copyTruncatedFrom(alphas[basisIdx]) + else: + alphaB.prod(alphas[basisIdx], lattice(F)[basisIdx][miniScalarIdx][0]) + + when lattice(F)[basisIdx][miniScalarIdx][1] xor babai(F)[basisIdx][1]: + k[miniScalarIdx] += alphaB + else: + k[miniScalarIdx] -= alphaB + + miniScalars[miniScalarIdx].copyTruncatedFrom(k[miniScalarIdx]) # Secret scalar + dynamic point # ---------------------------------------------------------------- diff --git a/constantine/elliptic/ec_endomorphism_params.nim b/constantine/elliptic/ec_endomorphism_params.nim deleted file mode 100644 index a19d079..0000000 --- a/constantine/elliptic/ec_endomorphism_params.nim +++ /dev/null @@ -1,289 +0,0 @@ -# Constantine -# Copyright (c) 2018-2019 Status Research & Development GmbH -# Copyright (c) 2020-Present Mamy André-Ratsimbazafy -# Licensed and distributed under either of -# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). -# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import - std/macros, - # Internal - ../primitives, - ../config/[common, curves, type_bigint], - ../arithmetic, - ../io/io_bigints, - ../towers, - ./ec_weierstrass_projective - -# ############################################################ -# -# Endomorphism acceleration decomposition parameters -# for Scalar Multiplication -# -# ############################################################ -# -# TODO: cleanup, those should be derived in the config folder -# and stored in a constant -# or generated from sage into a config file read at compile-time - -type - MultiScalar*[M, LengthInBits: static int] = array[M, BigInt[LengthInBits]] - ## Decomposition of a secret scalar in multiple scalars - -# BN254 Snarks G1 -# ---------------------------------------------------------------------------------------- - -# Chapter 6.3.1 - Guide to Pairing-based Cryptography -const Lattice_BN254_Snarks_G1 = ( - # Curve of order 254 -> mini scalars of size 127 - # u = 0x44E992B44A6909F1 - # (BigInt, isNeg) - ((BigInt[64].fromHex"0x89d3256894d213e3", false), # 2u + 1 - (BigInt[127].fromHex"0x6f4d8248eeb859fd0be4e1541221250b", false)), # 6u² + 4u + 1 - ((BigInt[127].fromHex"0x6f4d8248eeb859fc8211bbeb7d4f1128", false), # 6u² + 2u - (BigInt[64].fromHex"0x89d3256894d213e3", true)) # -2u - 1 -) - -const Babai_BN254_Snarks_G1 = ( - # Vector for Babai rounding - # (BigInt, isNeg) - (BigInt[66].fromHex"0x2d91d232ec7e0b3d7", false), # (2u + 1) << 2^256 // r - (BigInt[130].fromHex"0x24ccef014a773d2d25398fd0300ff6565", false) # (6u² + 4u + 1) << 2^256 // r -) - -# BLS12-377 G1 -# ---------------------------------------------------------------------------------------- - -const Lattice_BLS12_377_G1 = ( - # (BigInt, isNeg) - ((BigInt[127].fromHex"0x452217cc900000010a11800000000000", false), # u² - 1 - (BigInt[1].fromHex"0x1", true)), # -1 - ((BigInt[1].fromHex"0x1", false), # 1 - (BigInt[127].fromHex"0x452217cc900000010a11800000000001", false)) # u² -) - -const Babai_BLS12_377_G1 = ( - # Vector for Babai rounding - # (BigInt, isNeg) - (BigInt[130].fromHex"0x3b3f7aa969fd371607f72ed32af90182c", false), - (BigInt[4].fromHex"0xd", false) -) - -# BLS12-381 G1 -# ---------------------------------------------------------------------------------------- - -const Lattice_BLS12_381_G1 = ( - # (BigInt, isNeg) - ((BigInt[128].fromHex"0xac45a4010001a40200000000ffffffff", false), # u² - 1 - (BigInt[1].fromHex"0x1", true)), # -1 - ((BigInt[1].fromHex"0x1", false), # 1 - (BigInt[128].fromHex"0xac45a4010001a4020000000100000000", false)) # u² -) - -const Babai_BLS12_381_G1 = ( - # Vector for Babai rounding - # (BigInt, isNeg) - (BigInt[129].fromHex"0x17c6becf1e01faadd63f6e522f6cfee30", false), - (BigInt[2].fromHex"0x2", false) -) - -# BN254 Snarks G2 -# ---------------------------------------------------------------------------------------- - -const Lattice_BN254_Snarks_G2 = ( - # Curve of order 254 -> mini scalars of size 65 - # x = 0x44E992B44A6909F1 - # Value, isNeg - ((BigInt[63].fromHex"0x44e992b44a6909f2", false), # x+1 - (BigInt[63].fromHex"0x44e992b44a6909f1", false), # x - (BigInt[63].fromHex"0x44e992b44a6909f1", false), # x - (BigInt[64].fromHex"0x89d3256894d213e2", true)), # -2x - - ((BigInt[64].fromHex"0x89d3256894d213e3", false), # 2x+1 - (BigInt[63].fromHex"0x44e992b44a6909f1", true), # -x - (BigInt[63].fromHex"0x44e992b44a6909f2", true), # -x-1 - (BigInt[63].fromHex"0x44e992b44a6909f1", true)), # -x - - ((BigInt[64].fromHex"0x89d3256894d213e2", false), # 2x - (BigInt[64].fromHex"0x89d3256894d213e3", false), # 2x+1 - (BigInt[64].fromHex"0x89d3256894d213e3", false), # 2x+1 - (BigInt[64].fromHex"0x89d3256894d213e3", false)), # 2x+1 - - ((BigInt[63].fromHex"0x44e992b44a6909f0", false), # x-1 - (BigInt[65].fromHex"0x113a64ad129a427c6", false), # 4x+2 - (BigInt[64].fromHex"0x89d3256894d213e1", true), # -2x+1 - (BigInt[63].fromHex"0x44e992b44a6909f0", false)), # x-1 - ) - -const Babai_BN254_Snarks_G2 = ( - # Vector for Babai rounding - # Value, isNeg - (BigInt[128].fromHex"0xc444fab18d269b9dd0cb46fd51906254", false), # 2x²+3x+1 << 2^256 // r - (BigInt[193].fromHex"0x13d00631561b2572922df9f942d7d77c7001378f5ee78976d", false), # 3x³+8x²+x << 2^256 // r - (BigInt[192].fromhex"0x9e80318ab0d92b94916fcfca16bebbe436510546a93478ab", false), # 6x³+4x²+x << 2^256 // r - (BigInt[128].fromhex"0xc444fab18d269b9af7ae23ce89afae7d", true) # -2x²-x << 2^256 // r -) - -# BLS12-377 G2 -# ---------------------------------------------------------------------------------------- - -const Lattice_BLS12_377_G2 = ( - # Curve of order 254 -> mini scalars of size 65 - # x = -0xd201000000010000 - # Value, isNeg - ((BigInt[64].fromHex"0x8508c00000000001", true), # -x - (BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x0", false)), # 0 - - ((BigInt[1].fromHex"0x0", false), # 0 - (BigInt[64].fromHex"0x8508c00000000001", true), # -x - (BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false)), # 0 - - ((BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[64].fromHex"0x8508c00000000001", true), # -x - (BigInt[1].fromHex"0x1", false)), # 1 - - ((BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x1", true), # -1 - (BigInt[64].fromHex"0x8508c00000000001", true)) # -x -) - -const Babai_BLS12_377_G2 = ( - # Vector for Babai rounding - # Value, isNeg - (BigInt[193].fromHex"0x1eca0125755aed064f63abaff9084ce152979759b442f60d1", true), - (BigInt[130].fromHex"0x3b3f7aa969fd371607f72ed32af90181f", true), - (BigInt[67].fromhex"0x72030ba8ee9c06415", true), - (BigInt[1].fromhex"0x0", false) -) - -# BLS12-381 G2 -# ---------------------------------------------------------------------------------------- - -const Lattice_BLS12_381_G2 = ( - # Curve of order 254 -> mini scalars of size 65 - # x = -0xd201000000010000 - # Value, isNeg - ((BigInt[64].fromHex"0xd201000000010000", false), # -x - (BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x0", false)), # 0 - - ((BigInt[1].fromHex"0x0", false), # 0 - (BigInt[64].fromHex"0xd201000000010000", false), # -x - (BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false)), # 0 - - ((BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[64].fromHex"0xd201000000010000", false), # -x - (BigInt[1].fromHex"0x1", false)), # 1 - - ((BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x1", true), # -1 - (BigInt[64].fromHex"0xd201000000010000", false)) # -x -) - -const Babai_BLS12_381_G2 = ( - # Vector for Babai rounding - # Value, isNeg - (BigInt[193].fromHex"0x1381204ca56cd56b533cfcc0d3e76ec2892078a5e8573b29c", false), - (BigInt[129].fromHex"0x17c6becf1e01faadd63f6e522f6cfee2f", true), - (BigInt[65].fromhex"0x1cfbe4f7bd0027db0", false), - (BigInt[1].fromhex"0x0", false) -) - -# Decomposition routine -# ---------------------------------------------------------------------------------------- - -{.experimental: "dynamicbindsym".} -macro dispatch(prefix: static string, C: static Curve, G: static string): untyped = - result = bindSym(prefix & $C & "_" & G) - -template babai(F: typedesc[Fp or Fp2]): untyped = - const G = if F is Fp: "G1" - else: "G2" - dispatch("Babai_", F.C, G) - -template lattice(F: typedesc[Fp or Fp2]): untyped = - const G = if F is Fp: "G1" - else: "G2" - dispatch("Lattice_", F.C, G) - -func decomposeEndo*[M, scalBits, L: static int]( - miniScalars: var MultiScalar[M, L], - scalar: BigInt[scalBits], - F: typedesc[Fp or Fp2] - ) = - ## Decompose a secret scalar into M mini-scalars - ## using a curve endomorphism(s) characteristics. - ## - ## A scalar decomposition might lead to negative miniscalar(s). - ## For proper handling it requires either: - ## 1. Negating it and then negating the corresponding curve point P - ## 2. Adding an extra bit to the recoding, which will do the right thing™ - ## - ## For implementation solution 1 is faster: - ## - Double + Add is about 5000~8000 cycles on 6 64-bits limbs (BLS12-381) - ## - Conditional negate is about 10 cycles per Fp, on G2 projective we have 3 (coords) * 2 (Fp2) * 10 (cycles) ~= 60 cycles - ## We need to test the mini scalar, which is 65 bits so 2 Fp so about 2 cycles - ## and negate it as well. - ## - ## However solution 1 seems to cause issues (TODO) - ## with some of the BLS12-381 test cases (6 and 9) - ## - 0x5668a2332db27199dcfb7cbdfca6317c2ff128db26d7df68483e0a095ec8e88f - ## - 0x644dc62869683f0c93f38eaef2ba6912569dc91ec2806e46b4a3dd6a4421dad1 - - # Equal when no window or no negative handling, greater otherwise - static: doAssert L >= (scalBits + M - 1) div M + 1 - const w = F.C.getCurveOrderBitwidth().wordsRequired() - - when F is Fp: - var alphas{.noInit.}: ( - BigInt[scalBits + babai(F)[0][0].bits], - BigInt[scalBits + babai(F)[1][0].bits] - ) - else: - var alphas{.noInit.}: ( - BigInt[scalBits + babai(F)[0][0].bits], - BigInt[scalBits + babai(F)[1][0].bits], - BigInt[scalBits + babai(F)[2][0].bits], - BigInt[scalBits + babai(F)[3][0].bits] - ) - - staticFor i, 0, M: - when bool babai(F)[i][0].isZero(): - alphas[i].setZero() - else: - alphas[i].prod_high_words(babai(F)[i][0], scalar, w) - when babai(F)[i][1]: - # prod_high_words works like logical right shift - # When negative, we should add 1 to properly round toward -infinity - alphas[i] += SecretWord(1) - - # We have k0 = s - 𝛼0 b00 - 𝛼1 b10 ... - 𝛼m bm0 - # and kj = 0 - 𝛼j b0j - 𝛼1 b1j ... - 𝛼m bmj - var - k: array[M, BigInt[scalBits]] # zero-init required - alphaB {.noInit.}: BigInt[scalBits] - k[0] = scalar - staticFor miniScalarIdx, 0, M: - staticFor basisIdx, 0, M: - when not bool lattice(F)[basisIdx][miniScalarIdx][0].isZero(): - when bool lattice(F)[basisIdx][miniScalarIdx][0].isOne(): - alphaB.copyTruncatedFrom(alphas[basisIdx]) - else: - alphaB.prod(alphas[basisIdx], lattice(F)[basisIdx][miniScalarIdx][0]) - - when lattice(F)[basisIdx][miniScalarIdx][1] xor babai(F)[basisIdx][1]: - k[miniScalarIdx] += alphaB - else: - k[miniScalarIdx] -= alphaB - - miniScalars[miniScalarIdx].copyTruncatedFrom(k[miniScalarIdx]) diff --git a/constantine/io/io_towers.nim b/constantine/io/io_towers.nim index 41ab40c..f712e31 100644 --- a/constantine/io/io_towers.nim +++ b/constantine/io/io_towers.nim @@ -12,8 +12,6 @@ import std/typetraits, # Internal ./io_bigints, ./io_fields, - ../config/curves, - ../arithmetic/finite_fields, ../towers # No exceptions allowed diff --git a/constantine/isogeny/frobenius.nim b/constantine/isogeny/frobenius.nim index f13c5da..47ab215 100644 --- a/constantine/isogeny/frobenius.nim +++ b/constantine/isogeny/frobenius.nim @@ -8,9 +8,9 @@ import std/macros, - ../config/[common, curves], - ../io/io_towers, - ../towers, ../arithmetic + ../arithmetic, + ../towers, + ../curves/zoo_frobenius # Frobenius Map # ------------------------------------------------------------ @@ -66,331 +66,12 @@ template mulCheckSparse[Fp2](a: var Fp2, b: Fp2) = # Frobenius map - on extension fields # ----------------------------------------------------------------- -# c = (SNR^((p-1)/6)^coef). -# Then for frobenius(2): c * conjugate(c) -# And for frobenius(3): c² * conjugate(c) -const FrobMapConst_BLS12_377 = [ - # frobenius(1) - [Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^0 - "0x1", - "0x0" - ), - Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^1 - "0x9a9975399c019633c1e30682567f915c8a45e0f94ebc8ec681bf34a3aa559db57668e558eb0188e938a9d1104f2031", - "0x0" - ), - Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^2 = SNR^((p-1)/3) - "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000002", - "0x0" - ), - Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^3 = SNR^((p-1)/2) - "0x1680a40796537cac0c534db1a79beb1400398f50ad1dec1bce649cf436b0f6299588459bff27d8e6e76d5ecf1391c63", - "0x0" - ), - Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^4 = SNR^(2(p-1)/3) - "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000001", - "0x0" - ), - Fp2[BLS12_377].fromHex( # SNR^((p-1)/6)^5 - "0xcd70cb3fc936348d0351d498233f1fe379531411832232f6648a9a9fc0b9c4e3e21b7467077c05853e2c1be0e9fc32", - "0x0" - )], - # frobenius(2) - [Fp2[BLS12_377].fromHex( # norm(SNR)^((p-1)/6)^1 - "0x1", - "0x0" - ), - Fp2[BLS12_377].fromHex( # norm(SNR)^((p-1)/6)^2 - "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000002", - "0x0" - ), - Fp2[BLS12_377].fromHex( - "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000001", - "0x0" - ), - Fp2[BLS12_377].fromHex( - "0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000000", - "0x0" - ), - Fp2[BLS12_377].fromHex( - "0x1ae3a4617c510eabc8756ba8f8c524eb8882a75cc9bc8e359064ee822fb5bffd1e945779fffffffffffffffffffffff", - "0x0" - ), - Fp2[BLS12_377].fromHex( - "0x1ae3a4617c510eabc8756ba8f8c524eb8882a75cc9bc8e359064ee822fb5bffd1e94577a00000000000000000000000", - "0x0" - )], - # frobenius(3) - [Fp2[BLS12_377].fromHex( - "0x1", - "0x0" - ), - Fp2[BLS12_377].fromHex( - "0x1680a40796537cac0c534db1a79beb1400398f50ad1dec1bce649cf436b0f6299588459bff27d8e6e76d5ecf1391c63", - "0x0" - ), - Fp2[BLS12_377].fromHex( - "0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000000", - "0x0" - ), - Fp2[BLS12_377].fromHex( - "0x4630059e5fd9200575d0e552278a89da1f40fdf62334cd620d1860769e389d7db2d8ea700d82721691ea130ec6e39e", - "0x0" - ), - Fp2[BLS12_377].fromHex( - "0x1", - "0x0" - ), - Fp2[BLS12_377].fromHex( - "0x1680a40796537cac0c534db1a79beb1400398f50ad1dec1bce649cf436b0f6299588459bff27d8e6e76d5ecf1391c63", - "0x0" - )]] - -# c = (SNR^((p-1)/6)^coef). -# Then for frobenius(2): c * conjugate(c) -# And for frobenius(3): c² * conjugate(c) -const FrobMapConst_BLS12_381 = [ - # frobenius(1) - [Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^0 - "0x1", - "0x0" - ), - Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^1 - "0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8", - "0xfc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3" - ), - Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^2 = SNR^((p-1)/3) - "0x0", - "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac" - ), - Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^3 = SNR^((p-1)/2) - "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09", - "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09" - ), - Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^4 = SNR^(2(p-1)/3) - "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad", - "0x0" - ), - Fp2[BLS12_381].fromHex( # SNR^((p-1)/6)^5 - "0x5b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116", - "0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995" - )], - # frobenius(2) - [Fp2[BLS12_381].fromHex( # norm(SNR)^((p-1)/6)^1 - "0x1", - "0x0" - ), - Fp2[BLS12_381].fromHex( # norm(SNR)^((p-1)/6)^2 - "0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffff", - "0x0" - ), - Fp2[BLS12_381].fromHex( - "0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe", - "0x0" - ), - Fp2[BLS12_381].fromHex( - "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa", - "0x0" - ), - Fp2[BLS12_381].fromHex( - "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac", - "0x0" - ), - Fp2[BLS12_381].fromHex( - "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad", - "0x0" - )], - # frobenius(3) - [Fp2[BLS12_381].fromHex( - "0x1", - "0x0" - ), - Fp2[BLS12_381].fromHex( - "0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2", - "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09" - ), - Fp2[BLS12_381].fromHex( - "0x0", - "0x1" - ), - Fp2[BLS12_381].fromHex( - "0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2", - "0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2" - ), - Fp2[BLS12_381].fromHex( - "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa", - "0x0" - ), - Fp2[BLS12_381].fromHex( - "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09", - "0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2" - )]] - -const FrobMapConst_BN254_Nogami = [ - # frobenius(1) - [Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^0 - "0x1", - "0x0" - ), - Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^1 - "0x1b377619212e7c8cb6499b50a846953f850974924d3f77c2e17de6c06f2a6de9", - "0x9ebee691ed1837503eab22f57b96ac8dc178b6db2c08850c582193f90d5922a" - ), - Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^2 = SNR^((p-1)/3) - "0x0", - "0x25236482400000017080eb4000000006181800000000000cd98000000000000b" - ), - Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^3 = SNR^((p-1)/2) - "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5", - "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5" - ), - Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^4 = SNR^(2(p-1)/3) - "0x25236482400000017080eb4000000006181800000000000cd98000000000000c", - "0x0" - ), - Fp2[BN254_Nogami].fromHex( # SNR^((p-1)/6)^5 - "0x19f3db6884cdca43c2b0d5792cd135accb1baea0b017046e859975ab54b5ef9b", - "0xb2f8919bb3235bdf7837806d32eca5b9605515f4fe8fba521668a54ab4a1078" - )], - # frobenius(2) - [Fp2[BN254_Nogami].fromHex( # norm(SNR)^((p-1)/6)^1 - "0x1", - "0x0" - ), - Fp2[BN254_Nogami].fromHex( # norm(SNR)^((p-1)/6)^2 - "0x49b36240000000024909000000000006cd80000000000008", - "0x0" - ), - Fp2[BN254_Nogami].fromHex( - "0x49b36240000000024909000000000006cd80000000000007", - "0x0" - ), - Fp2[BN254_Nogami].fromHex( - "0x2523648240000001ba344d80000000086121000000000013a700000000000012", - "0x0" - ), - Fp2[BN254_Nogami].fromHex( - "0x25236482400000017080eb4000000006181800000000000cd98000000000000b", - "0x0" - ), - Fp2[BN254_Nogami].fromHex( - "0x25236482400000017080eb4000000006181800000000000cd98000000000000c", - "0x0" - )], - # frobenius(3) - [Fp2[BN254_Nogami].fromHex( - "0x1", - "0x0" - ), - Fp2[BN254_Nogami].fromHex( - "0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e", - "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5" - ), - Fp2[BN254_Nogami].fromHex( - "0x0", - "0x1" - ), - Fp2[BN254_Nogami].fromHex( - "0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e", - "0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e" - ), - Fp2[BN254_Nogami].fromHex( - "0x2523648240000001ba344d80000000086121000000000013a700000000000012", - "0x0" - ), - Fp2[BN254_Nogami].fromHex( - "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5", - "0x1439ab09c60b248f398c5d77b755f92b9edc5f19d2873545be471151a747e4e" - )]] - -const FrobMapConst_BN254_Snarks = [ - # frobenius(1) - [Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^0 - "0x1", - "0x0" - ), - Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^1 - "0x1284b71c2865a7dfe8b99fdd76e68b605c521e08292f2176d60b35dadcc9e470", - "0x246996f3b4fae7e6a6327cfe12150b8e747992778eeec7e5ca5cf05f80f362ac" - ), - Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^2 = SNR^((p-1)/3) - "0x2fb347984f7911f74c0bec3cf559b143b78cc310c2c3330c99e39557176f553d", - "0x16c9e55061ebae204ba4cc8bd75a079432ae2a1d0b7c9dce1665d51c640fcba2" - ), - Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^3 = SNR^((p-1)/2) - "0x63cf305489af5dcdc5ec698b6e2f9b9dbaae0eda9c95998dc54014671a0135a", - "0x7c03cbcac41049a0704b5a7ec796f2b21807dc98fa25bd282d37f632623b0e3" - ), - Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^4 = SNR^(2(p-1)/3) - "0x5b54f5e64eea80180f3c0b75a181e84d33365f7be94ec72848a1f55921ea762", - "0x2c145edbe7fd8aee9f3a80b03b0b1c923685d2ea1bdec763c13b4711cd2b8126" - ), - Fp2[BN254_Snarks].fromHex( # SNR^((p-1)/6)^5 - "0x183c1e74f798649e93a3661a4353ff4425c459b55aa1bd32ea2c810eab7692f", - "0x12acf2ca76fd0675a27fb246c7729f7db080cb99678e2ac024c6b8ee6e0c2c4b" - )], - # frobenius(2) - [Fp2[BN254_Snarks].fromHex( # norm(SNR)^((p-1)/6)^1 - "0x1", - "0x0" - ), - Fp2[BN254_Snarks].fromHex( # norm(SNR)^((p-1)/6)^2 - "0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd49", - "0x0" - ), - Fp2[BN254_Snarks].fromHex( - "0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48", - "0x0" - ), - Fp2[BN254_Snarks].fromHex( - "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46", - "0x0" - ), - Fp2[BN254_Snarks].fromHex( - "0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe", - "0x0" - ), - Fp2[BN254_Snarks].fromHex( - "0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177ffffff", - "0x0" - )], - # frobenius(3) - [Fp2[BN254_Snarks].fromHex( - "0x1", - "0x0" - ), - Fp2[BN254_Snarks].fromHex( - "0x19dc81cfcc82e4bbefe9608cd0acaa90894cb38dbe55d24ae86f7d391ed4a67f", - "0xabf8b60be77d7306cbeee33576139d7f03a5e397d439ec7694aa2bf4c0c101" - ), - Fp2[BN254_Snarks].fromHex( - "0x856e078b755ef0abaff1c77959f25ac805ffd3d5d6942d37b746ee87bdcfb6d", - "0x4f1de41b3d1766fa9f30e6dec26094f0fdf31bf98ff2631380cab2baaa586de" - ), - Fp2[BN254_Snarks].fromHex( - "0x2a275b6d9896aa4cdbf17f1dca9e5ea3bbd689a3bea870f45fcc8ad066dce9ed", - "0x28a411b634f09b8fb14b900e9507e9327600ecc7d8cf6ebab94d0cb3b2594c64" - ), - Fp2[BN254_Snarks].fromHex( - "0xbc58c6611c08dab19bee0f7b5b2444ee633094575b06bcb0e1a92bc3ccbf066", - "0x23d5e999e1910a12feb0f6ef0cd21d04a44a9e08737f96e55fe3ed9d730c239f" - ), - Fp2[BN254_Snarks].fromHex( - "0x13c49044952c0905711699fa3b4d3f692ed68098967c84a5ebde847076261b43", - "0x16db366a59b1dd0b9fb1b2282a48633d3e2ddaea200280211f25041384282499" - )]] - -{.experimental: "dynamicBindSym".} - -macro frobMapConst(C: static Curve): untyped = - return bindSym("FrobMapConst_" & $C) - func frobenius_map*[C](r: var Fp4[C], a: Fp4[C], k: static int = 1) {.inline.} = ## Computes a^(p^k) ## The p-power frobenius automorphism on 𝔽p4 r.c0.frobenius_map(a.c0, k) r.c1.frobenius_map(a.c1, k) - r.c1.mulCheckSparse frobMapConst(C)[k-1][3] + r.c1.mulCheckSparse frobMapConst(C, 3, k) func frobenius_map*[C](r: var Fp6[C], a: Fp6[C], k: static int = 1) {.inline.} = ## Computes a^(p^k) @@ -398,8 +79,8 @@ func frobenius_map*[C](r: var Fp6[C], a: Fp6[C], k: static int = 1) {.inline.} = r.c0.frobenius_map(a.c0, k) r.c1.frobenius_map(a.c1, k) r.c2.frobenius_map(a.c2, k) - r.c1.mulCheckSparse frobMapConst(C)[k-1][2] - r.c2.mulCheckSparse frobMapConst(C)[k-1][4] + r.c1.mulCheckSparse frobMapConst(C, 2, k) + r.c2.mulCheckSparse frobMapConst(C, 4, k) func frobenius_map*[C](r: var Fp12[C], a: Fp12[C], k: static int = 1) {.inline.} = ## Computes a^(p^k) @@ -409,108 +90,20 @@ func frobenius_map*[C](r: var Fp12[C], a: Fp12[C], k: static int = 1) {.inline.} for r_fp2, a_fp2 in fields(r_fp4, a_fp4): r_fp2.frobenius_map(a_fp2, k) - r.c0.c0.mulCheckSparse frobMapConst(C)[k-1][0] - r.c0.c1.mulCheckSparse frobMapConst(C)[k-1][3] - r.c1.c0.mulCheckSparse frobMapConst(C)[k-1][1] - r.c1.c1.mulCheckSparse frobMapConst(C)[k-1][4] - r.c2.c0.mulCheckSparse frobMapConst(C)[k-1][2] - r.c2.c1.mulCheckSparse frobMapConst(C)[k-1][5] + r.c0.c0.mulCheckSparse frobMapConst(C, 0, k) + r.c0.c1.mulCheckSparse frobMapConst(C, 3, k) + r.c1.c0.mulCheckSparse frobMapConst(C, 1, k) + r.c1.c1.mulCheckSparse frobMapConst(C, 4, k) + r.c2.c0.mulCheckSparse frobMapConst(C, 2, k) + r.c2.c1.mulCheckSparse frobMapConst(C, 5, k) # ψ (Psi) - Untwist-Frobenius-Twist Endomorphisms on twisted curves # ----------------------------------------------------------------- -# TODO: generate those constants via Sage in a Json file -# and parse at compile-time # Constants: # Assuming embedding degree of 12 and a sextic twist # with SNR the sextic non-residue # -# BN254_Snarks is a D-Twist: SNR^((p-1)/6) -const FrobPsiConst_BN254_Snarks_psi1_coef1 = Fp2[BN254_Snarks].fromHex( - "0x1284b71c2865a7dfe8b99fdd76e68b605c521e08292f2176d60b35dadcc9e470", - "0x246996f3b4fae7e6a6327cfe12150b8e747992778eeec7e5ca5cf05f80f362ac" -) -# SNR^((p-1)/3) -const FrobPsiConst_BN254_Snarks_psi1_coef2 = Fp2[BN254_Snarks].fromHex( - "0x2fb347984f7911f74c0bec3cf559b143b78cc310c2c3330c99e39557176f553d", - "0x16c9e55061ebae204ba4cc8bd75a079432ae2a1d0b7c9dce1665d51c640fcba2" -) -# SNR^((p-1)/2) -const FrobPsiConst_BN254_Snarks_psi1_coef3 = Fp2[BN254_Snarks].fromHex( - "0x63cf305489af5dcdc5ec698b6e2f9b9dbaae0eda9c95998dc54014671a0135a", - "0x7c03cbcac41049a0704b5a7ec796f2b21807dc98fa25bd282d37f632623b0e3" -) -# norm(SNR)^((p-1)/3) -const FrobPsiConst_BN254_Snarks_psi2_coef2 = Fp2[BN254_Snarks].fromHex( - "0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48", - "0x0" -) - -# BN254_Nogami is a D-Twist: SNR^((p-1)/6) -const FrobPsiConst_BN254_Nogami_psi1_coef1 = Fp2[BN254_Nogami].fromHex( - "0x1b377619212e7c8cb6499b50a846953f850974924d3f77c2e17de6c06f2a6de9", - "0x9ebee691ed1837503eab22f57b96ac8dc178b6db2c08850c582193f90d5922a" -) -# SNR^((p-1)/3) -const FrobPsiConst_BN254_Nogami_psi1_coef2 = Fp2[BN254_Nogami].fromHex( - "0x0", - "0x25236482400000017080eb4000000006181800000000000cd98000000000000b" -) -# SNR^((p-1)/2) -const FrobPsiConst_BN254_Nogami_psi1_coef3 = Fp2[BN254_Nogami].fromHex( - "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5", - "0x23dfc9d1a39f4db8c69b87a8848aa075a7333a0e62d78cbf4b1b8eeae58b81c5" -) -# norm(SNR)^((p-1)/3) -const FrobPsiConst_BN254_Nogami_psi2_coef2 = Fp2[BN254_Nogami].fromHex( - "0x49b36240000000024909000000000006cd80000000000007", - "0x0" -) - -# BLS12_377 is a D-Twist: SNR^((p-1)/6) -const FrobPsiConst_BLS12_377_psi1_coef1 = Fp2[BLS12_377].fromHex( - "0x9a9975399c019633c1e30682567f915c8a45e0f94ebc8ec681bf34a3aa559db57668e558eb0188e938a9d1104f2031", - "0x0" -) -# SNR^((p-1)/3) -const FrobPsiConst_BLS12_377_psi1_coef2 = Fp2[BLS12_377].fromHex( - "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000002", - "0x0" -) -# SNR^((p-1)/2) -const FrobPsiConst_BLS12_377_psi1_coef3 = Fp2[BLS12_377].fromHex( - "0x1680a40796537cac0c534db1a79beb1400398f50ad1dec1bce649cf436b0f6299588459bff27d8e6e76d5ecf1391c63", - "0x0" -) -# norm(SNR)^((p-1)/3) -const FrobPsiConst_BLS12_377_psi2_coef2 = Fp2[BLS12_377].fromHex( - "0x9b3af05dd14f6ec619aaf7d34594aabc5ed1347970dec00452217cc900000008508c00000000001", - "0x0" -) - -# BLS12_381 is a M-twist: (1/SNR)^((p-1)/6) -const FrobPsiConst_BLS12_381_psi1_coef1 = Fp2[BLS12_381].fromHex( - "0x5b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116", - "0x5b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116" -) -# (1/SNR)^((p-1)/3) -const FrobPsiConst_BLS12_381_psi1_coef2 = Fp2[BLS12_381].fromHex( - "0x0", - "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad" -) -# (1/SNR)^((p-1)/2) -const FrobPsiConst_BLS12_381_psi1_coef3 = Fp2[BLS12_381].fromHex( - "0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2", - "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09" -) -# norm(SNR)^((p-1)/3) -const FrobPsiConst_BLS12_381_psi2_coef2 = Fp2[BLS12_381].fromHex( - "0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac", - "0x0" -) - -macro frobPsiConst(C: static Curve, psipow, coefpow: static int): untyped = - return bindSym("FrobPsiConst_" & $C & "_psi" & $psipow & "_coef" & $coefpow) func frobenius_psi*[PointG2](r: var PointG2, P: PointG2) = ## "Untwist-Frobenius-Twist" endomorphism diff --git a/constantine/pairing/cyclotomic_fp12.nim b/constantine/pairing/cyclotomic_fp12.nim index ee0f2b0..ea85cc7 100644 --- a/constantine/pairing/cyclotomic_fp12.nim +++ b/constantine/pairing/cyclotomic_fp12.nim @@ -225,6 +225,11 @@ func cyclotomic_square*[C](a: var Fp12[C]) = else: {.error: "Not implemented".} +func cycl_sqr_repeated*(f: var Fp12, num: int) {.inline.} = + ## Repeated cyclotomic squarings + for _ in 0 ..< num: + f.cyclotomic_square() + iterator unpack(scalarByte: byte): bool = yield bool((scalarByte and 0b10000000) shr 7) yield bool((scalarByte and 0b01000000) shr 6) diff --git a/constantine/pairing/pairing_bls12.nim b/constantine/pairing/pairing_bls12.nim index d79160b..f8ce825 100644 --- a/constantine/pairing/pairing_bls12.nim +++ b/constantine/pairing/pairing_bls12.nim @@ -7,12 +7,8 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import - std/macros, - ../primitives, - ../config/[common, curves], - ../arithmetic, + ../config/[curves, type_fp], ../towers, - ../io/io_bigints, ../elliptic/[ ec_weierstrass_affine, ec_weierstrass_projective @@ -20,7 +16,8 @@ import ../isogeny/frobenius, ./lines_projective, ./mul_fp12_by_lines, - ./cyclotomic_fp12 + ./cyclotomic_fp12, + ../curves/zoo_pairings # ############################################################ # @@ -45,41 +42,10 @@ import # Craig Costello, Tanja Lange, and Michael Naehrig, 2009 # https://eprint.iacr.org/2009/615.pdf -# TODO: should be part of curve parameters -# The bit count must be exact for the Miller loop -const BLS12_377_ate_param = block: - # BLS Miller loop is parametrized by u - BigInt[64+1].fromHex("0x8508c00000000001") # +1 so that we can take *3 and NAF encode it - -const BLS12_377_ate_param_isNeg = false - -const BLS12_381_ate_param = block: - # BLS Miller loop is parametrized by u - BigInt[64+2].fromHex("0xd201000000010000") # +2 so that we can take *3 and NAF encode it - -const BLS12_381_ate_param_isNeg = true - -# Generic slow pairing implementation +# Generic pairing implementation # ---------------------------------------------------------------- -const BLS12_377_finalexponent = block: - # (p^12 - 1) / r - # BigInt[4269].fromHex"0x1b2ff68c1abdc48ab4f04ed12cc8f9b2f161b41c7eb8865b9ad3c9bb0571dd94c6bde66548dc13624d9d741024ceb315f46a89cc2482605eb6afc6d8977e5e2ccbec348dd362d59ec2b5bc62a1b467ae44572215548abc98bb4193886ed89cceaedd0221aba84fb33e5584ac29619a87a00c315178155496857c995eab4a8a9af95f4015db27955ae408d6927d0ab37d52f3917c4ddec88f8159f7bcba7eb65f1aae4eeb4e70cb20227159c08a7fdfea9b62bb308918eac3202569dd1bcdd86b431e3646356fc3fb79f89b30775e006993adb629586b6c874b7688f86f11ef7ad94a40eb020da3c532b317232fa56dc564637b331a8e8832eab84269f00b506602c8594b7f7da5a5d8d851fff6ab1d38a354fc8e0b8958e2a9e5ce2d7e50ec36d761d9505fe5e1f317257e2df2952fcd4c93b85278c20488b4ccaee94db3fec1ce8283473e4b493843fa73abe99af8bafce29170b2b863b9513b5a47312991f60c5a4f6872b5d574212bf00d797c0bea3c0f7dfd748e63679fda9b1c50f2df74de38f38e004ae0df997a10db31d209cacbf58ba0678bfe7cd0985bc43258d72d8d5106c21635ae1e527eb01fca3032d50d97756ec9ee756eaba7f21652a808a4e2539e838ef7ec4b178b29e3b976c46bd0ecdd32c1fb75e6e0aef2d8b5661f595a98023f3520381aba8da6cce785dbb0a0bba025478d75ee749619cdb7c42a21098ece86a00c6c2046c1e00000063c69000000000000" - # (p^12 - 1) / r * 3 - BigInt[4271].fromHex"0x518fe3a450394da01ed0ec73865aed18d4251c557c299312d07b5d31105598be5439b32fda943a26e8d85c306e6c1941dd3f9d646d87211c240f5489c67b1a8663c49da97a2880dc48213527e51d370acd05663ffda035ca31c4ba994c89d66c0c97066502f8ef19bb008e047c24cf96e02493f4683ffdc39075cc1c01df9fd0ec1dc0419176c010ac1a83b777201a77f8dab474e99c59ae840de7362f7c231d500aecc1eb52616067540d419f7f9fbfd22831919b4ac04960703d9753698941c95aa2d2a04f4bf26de9d191661a013cbb09227c09424595e2639ae94d35ce708bdec2c10628eb4f981945698ef049502d2a71994fab9898c028c73dd021f13208590be27e78f0f18a88f5ffe40157a9e9fef5aa229c0aa7fdb16a887af2c4a486258bf11fb1a5d945707a89d7bf8f67e5bb28f76a460d9a1e660cbbe91bfc456b8789d5bae1dba8cbef5b03bcd0ea30f6a7b45218292b2bf3b20ed5937cb5e2250eee395821805c6383d0286c7423beb42e79f85dab2a36df8fd154f2d89e5e9aaadaaa00e0a29ecc6e329195761d6063e0a2e136a3fb7671c9134c970a8588a7f3144642a10a5af77c105f5e90987f28c6604c5dcb604c02f7d642f7f819eea6fadb8aace7c4e146a17dab2c644d4372c6979845f261b4a20cd88a20325e0c0fc806bd9f60a8502fa8f466b6919311e232e06fd6a861cb5dc24d69274c7e631cac6b93e0254460d445a0000012b53b000000000000" - -const BLS12_381_finalexponent = block: - # (p^12 - 1) / r - # BigInt[4314].fromHex"0x2ee1db5dcc825b7e1bda9c0496a1c0a89ee0193d4977b3f7d4507d07363baa13f8d14a917848517badc3a43d1073776ab353f2c30698e8cc7deada9c0aadff5e9cfee9a074e43b9a660835cc872ee83ff3a0f0f1c0ad0d6106feaf4e347aa68ad49466fa927e7bb9375331807a0dce2630d9aa4b113f414386b0e8819328148978e2b0dd39099b86e1ab656d2670d93e4d7acdd350da5359bc73ab61a0c5bf24c374693c49f570bcd2b01f3077ffb10bf24dde41064837f27611212596bc293c8d4c01f25118790f4684d0b9c40a68eb74bb22a40ee7169cdc1041296532fef459f12438dfc8e2886ef965e61a474c5c85b0129127a1b5ad0463434724538411d1676a53b5a62eb34c05739334f46c02c3f0bd0c55d3109cd15948d0a1fad20044ce6ad4c6bec3ec03ef19592004cedd556952c6d8823b19dadd7c2498345c6e5308f1c511291097db60b1749bf9b71a9f9e0100418a3ef0bc627751bbd81367066bca6a4c1b6dcfc5cceb73fc56947a403577dfa9e13c24ea820b09c1d9f7c31759c3635de3f7a3639991708e88adce88177456c49637fd7961be1a4c7e79fb02faa732e2f3ec2bea83d196283313492caa9d4aff1c910e9622d2a73f62537f2701aaef6539314043f7bbce5b78c7869aeb2181a67e49eeed2161daf3f881bd88592d767f67c4717489119226c2f011d4cab803e9d71650a6f80698e2f8491d12191a04406fbc8fbd5f48925f98630e68bfb24c0bcb9b55df57510" - # (p^12 - 1) / r * 3 - BigInt[4316].fromHex"0x8ca592196587127a538fd40dc3e541f9dca04bb7dc671be77cf17715a2b2fe3bea73dfb468d8f473094aecb7315a664019fbd84913caba6579c08fd42009fe1bd6fcbce15eacb2cf3218a165958cb8bfdae2d2d54207282314fc0dea9d6ff3a07dbd34efb77b732ba5f994816e296a72928cfee133bdc3ca9412b984b9783d9c6aa81297ab1cd294a502304773528bbae8706979f28efa0d355b0224e2513d6e4a5d3bb4dde0523678105d9167ff1323d6e99ac312d8a7d762336370c4347bb5a7e405d6f3496b2dd38e722d4c1f3ac25e3167ec2cb543d69430c37c2f98fcdd0dd36caa9f5aa7994cec31b24ed5e515911037b376e521070d29c9d56cfa8c3574363efb20f28c19e4105ab99edd44084bd23725017931d6740bda71e5f07600ce6b407e543c4bc40bcd4c0b600e6c98003bf8548986b14d9098746dc89d154af91ad54f337b31c79222145dd3ed254fdeda0300c49ebcd2352765f533883a3513435f3ee452496f5166c25bf503bd6ec0a0679efda3b46ebf86211d458de749460d4a2a19abe6ea2accb451ab9a096b98465d044dc2a7f86c253a4ee57b6df108eff598a8dbc483bf8b74c2789939db85ffd7e0fd55b32bc26877f5be26fa7d750500ce2fab93c0cbe7336b126a5693d0c16484f37addccc7642590dbe98538990b88637e374d545d9b34b67448d0357e60280bbd8542f1f4e813caa8e8db57364b4e0cc14f35af381dd9b71ec9292b3a3f16e42362d2019e05f30" - -{.experimental: "dynamicBindSym".} - -macro get(C: static Curve, value: untyped): untyped = - return bindSym($C & "_" & $value) - -func millerLoopGenericBLS12*[C: static Curve]( +func millerLoopGenericBLS12*[C]( f: var Fp12[C], P: ECP_SWei_Aff[Fp[C]], Q: ECP_SWei_Aff[Fp2[C]] @@ -129,8 +95,8 @@ func millerLoopGenericBLS12*[C: static Curve]( else: f.mul_sparse_by_line_xy000z(line) - template u: untyped = C.get(ate_param) - let u3 = 3*C.get(ate_param) + template u: untyped = C.pairing(ate_param) + let u3 = 3*C.pairing(ate_param) for i in countdown(u3.bits - 2, 1): f.square() line.line_double(T, P) @@ -145,7 +111,7 @@ func millerLoopGenericBLS12*[C: static Curve]( line.line_add(T, nQ, P) f.mul(line) - when C.get(ate_param_isNeg): + when C.pairing(ate_param_isNeg): # In GT, x^-1 == conjugate(x) # Remark 7.1, chapter 7.1.1 of Guide to Pairing-Based Cryptography, El Mrabet, 2017 f.conj() @@ -153,7 +119,7 @@ func millerLoopGenericBLS12*[C: static Curve]( func finalExpGeneric[C: static Curve](f: var Fp12[C]) = ## A generic and slow implementation of final exponentiation ## for sanity checks purposes. - f.powUnsafeExponent(C.get(finalexponent), window = 3) + f.powUnsafeExponent(C.pairing(finalexponent), window = 3) func pairing_bls12_reference*[C](gt: var Fp12[C], P: ECP_SWei_Proj[Fp[C]], Q: ECP_SWei_Proj[Fp2[C]]) = ## Compute the optimal Ate Pairing for BLS12 curves @@ -171,66 +137,7 @@ func pairing_bls12_reference*[C](gt: var Fp12[C], P: ECP_SWei_Proj[Fp[C]], Q: EC # Optimized pairing implementation # ---------------------------------------------------------------- -func cycl_sqr_repeated(f: var Fp12, num: int) = - ## Repeated cyclotomic squarings - for _ in 0 ..< num: - f.cyclotomic_square() - -func pow_xdiv2(r: var Fp12[BLS12_381], a: Fp12[BLS12_381], invert = BLS12_381_ate_param_isNeg) = - ## f^(x/2) with x the curve parameter - ## For BLS12_381 f^-0xd201000000010000 - - r.cyclotomic_square(a) - r *= a - r.cycl_sqr_repeated(2) - r *= a - r.cycl_sqr_repeated(3) - r *= a - r.cycl_sqr_repeated(9) - r *= a - r.cycl_sqr_repeated(32) # TODO: use Karabina? - r *= a - r.cycl_sqr_repeated(16-1) # Don't do the last iteration - - if invert: - r.cyclotomic_inv() - -func pow_x(r: var Fp12[BLS12_381], a: Fp12[BLS12_381], invert = BLS12_381_ate_param_isNeg) = - ## f^x with x the curve parameter - ## For BLS12_381 f^-0xd201000000010000 - r.pow_xdiv2(a, invert) - r.cyclotomic_square() - -func pow_x(r: var Fp12[BLS12_377], a: Fp12[BLS12_377], invert = BLS12_377_ate_param_isNeg) = - ## f^x with x the curve parameter - ## For BLS12_377 f^-0x8508c00000000001 - ## Warning: The parameter is odd and needs a correction - r.cyclotomic_square(a) - r *= a - r.cyclotomic_square() - r *= a - let t111 = r - - r.cycl_sqr_repeated(2) - let t111000 = r - - r *= t111 - let t100011 = r - - r.cyclotomic_square() - r *= t100011 - r *= t111000 - - r.cycl_sqr_repeated(10) - r *= t100011 - - r.cycl_sqr_repeated(46) - r *= a - - if invert: - r.cyclotomic_inv() - -func finalExpHard_BLS12*[C: static Curve](f: var Fp12[C]) = +func finalExpHard_BLS12*[C](f: var Fp12[C]) = ## Hard part of the final exponentiation ## Specialized for BLS12 curves ## @@ -259,7 +166,7 @@ func finalExpHard_BLS12*[C: static Curve](f: var Fp12[C]) = v2.cyclotomic_square(f) # v2 = f² # (x−1)² - when C.get(ate_param).isEven.bool: + when C.pairing(ate_param).isEven.bool: v0.pow_xdiv2(v2) # v0 = (f²)^(x/2) = f^x else: v0.pow_x(f) diff --git a/constantine/pairing/pairing_bn.nim b/constantine/pairing/pairing_bn.nim index 1a2256c..f342e76 100644 --- a/constantine/pairing/pairing_bn.nim +++ b/constantine/pairing/pairing_bn.nim @@ -7,10 +7,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import - std/macros, - ../primitives, - ../config/[common, curves], - ../arithmetic, + ../config/[curves, type_fp], ../towers, ../io/io_bigints, ../elliptic/[ @@ -20,7 +17,8 @@ import ./lines_projective, ./mul_fp12_by_lines, ./cyclotomic_fp12, - ../isogeny/frobenius + ../isogeny/frobenius, + ../curves/zoo_pairings # ############################################################ # @@ -42,37 +40,10 @@ import # Craig Costello, Tanja Lange, and Michael Naehrig, 2009 # https://eprint.iacr.org/2009/615.pdf -# TODO: should be part of curve parameters -# The bit count must be exact for the Miller loop -const BN254_Snarks_ate_param = block: - # BN Miller loop is parametrized by 6u+2 - BigInt[65+2].fromHex"0x19d797039be763ba8" - -const BN254_Snarks_ate_param_isNeg = false - -const BN254_Nogami_ate_param = block: - # BN Miller loop is parametrized by 6u+2 - BigInt[65+2].fromHex"0x18300000000000004" # 65+2 bit for NAF x3 encoding - -const BN254_Nogami_ate_param_isNeg = true - -# Generic slow pairing implementation +# Generic pairing implementation # ---------------------------------------------------------------- -const BN254_Snarks_finalexponent = block: - # (p^12 - 1) / r - BigInt[2790].fromHex"0x2f4b6dc97020fddadf107d20bc842d43bf6369b1ff6a1c71015f3f7be2e1e30a73bb94fec0daf15466b2383a5d3ec3d15ad524d8f70c54efee1bd8c3b21377e563a09a1b705887e72eceaddea3790364a61f676baaf977870e88d5c6c8fef0781361e443ae77f5b63a2a2264487f2940a8b1ddb3d15062cd0fb2015dfc6668449aed3cc48a82d0d602d268c7daab6a41294c0cc4ebe5664568dfc50e1648a45a4a1e3a5195846a3ed011a337a02088ec80e0ebae8755cfe107acf3aafb40494e406f804216bb10cf430b0f37856b42db8dc5514724ee93dfb10826f0dd4a0364b9580291d2cd65664814fde37ca80bb4ea44eacc5e641bbadf423f9a2cbf813b8d145da90029baee7ddadda71c7f3811c4105262945bba1668c3be69a3c230974d83561841d766f9c9d570bb7fbe04c7e8a6c3c760c0de81def35692da361102b6b9b2b918837fa97896e84abb40a4efb7e54523a486964b64ca86f120" - -const BN254_Nogami_finalexponent = block: - # (p^12 - 1) / r - BigInt[2786].fromHex"0x2928fbb36b391596ee3fe4cbe857330da83e46fedf04d235a4a8daf5ff9f6eabcb4e3f20aa06f0a0d96b24f9af0cbbce750d61627dcbf5fec9139b8f1c46c86b49b4f8a202af26e4504f2c0f56570e9bd5b94c403f385d1908556486e24b396ddc2cdf13d06542f84fe8e82ccbad7b7423fc1ef4e8cc73d605e3e867c0a75f45ea7f6356d9846ce35d5a34f30396938818ad41914b97b99c289a7259b5d2e09477a77bd3c409b19f19e893f8ade90b0aed1b5fc8a07a3cebb41d4e9eee96b21a832ddb1e93e113edfb704fa532848c18593cd0ee90444a1b3499a800177ea38bdec62ec5191f2b6bbee449722f98d2173ad33077545c2ad10347e125a56fb40f086e9a4e62ad336a72c8b202ac3c1473d73b93d93dc0795ca0ca39226e7b4c1bb92f99248ec0806e0ad70744e9f2238736790f5185ea4c70808442a7d530c6ccd56b55a6973867ec6c73599bbd020bbe105da9c6b5c009ad8946cd6f0" - -{.experimental: "dynamicBindSym".} - -macro get(C: static Curve, value: untyped): untyped = - return bindSym($C & "_" & $value) - -func millerLoopGenericBN*[C: static Curve]( +func millerLoopGenericBN*[C]( f: var Fp12[C], P: ECP_SWei_Aff[Fp[C]], Q: ECP_SWei_Aff[Fp2[C]] @@ -123,8 +94,8 @@ func millerLoopGenericBN*[C: static Curve]( else: f.mul_sparse_by_line_xy000z(line) - template u: untyped = C.get(ate_param) - let u3 = 3*C.get(ate_param) + template u: untyped = C.pairing(ate_param) + let u3 = 3*C.pairing(ate_param) for i in countdown(u3.bits - 2, 1): f.square() line.line_double(T, P) @@ -138,13 +109,13 @@ func millerLoopGenericBN*[C: static Curve]( line.line_add(T, nQ, P) f.mul(line) - when C.get(ate_param_isNeg): + when C.pairing(ate_param_isNeg): # In GT, x^-1 == conjugate(x) # Remark 7.1, chapter 7.1.1 of Guide to Pairing-Based Cryptography, El Mrabet, 2017 f.conj() # Ate pairing for BN curves need adjustment after Miller loop - when C.get(ate_param_isNeg): + when C.pairing(ate_param_isNeg): T.neg() var V {.noInit.}: typeof(Q) @@ -160,7 +131,7 @@ func millerLoopGenericBN*[C: static Curve]( func finalExpGeneric[C: static Curve](f: var Fp12[C]) = ## A generic and slow implementation of final exponentiation ## for sanity checks purposes. - f.powUnsafeExponent(C.get(finalexponent), window = 3) + f.powUnsafeExponent(C.pairing(finalexponent), window = 3) func pairing_bn_reference*[C](gt: var Fp12[C], P: ECP_SWei_Proj[Fp[C]], Q: ECP_SWei_Proj[Fp2[C]]) = ## Compute the optimal Ate Pairing for BN curves @@ -178,106 +149,6 @@ func pairing_bn_reference*[C](gt: var Fp12[C], P: ECP_SWei_Proj[Fp[C]], Q: ECP_S # Optimized pairing implementation # ---------------------------------------------------------------- -func cycl_sqr_repeated(f: var Fp12, num: int) = - ## Repeated cyclotomic squarings - for _ in 0 ..< num: - f.cyclotomic_square() - -func pow_u(r: var Fp12[BN254_Nogami], a: Fp12[BN254_Nogami], invert = BN254_Nogami_ate_param_isNeg) = - ## f^u with u the curve parameter - ## For BN254_Nogami f^-0x4080000000000001 - r = a - r.cycl_sqr_repeated(7) - r *= a - r.cycl_sqr_repeated(55) - r *= a - - if invert: - r.cyclotomic_inv() - -func pow_u(r: var Fp12[BN254_Snarks], a: Fp12[BN254_Snarks], invert = BN254_Snarks_ate_param_isNeg) = - ## f^u with u the curve parameter - ## For BN254_Snarks f^0x44e992b44a6909f1 - when false: - cyclotomic_exp( - r, a, - BigInt[63].fromHex("0x44e992b44a6909f1"), - invert - ) - else: - var # Hopefully the compiler optimizes away unused Fp12 - # because those are huge - x10 {.noInit.}: Fp12[BN254_Snarks] - x11 {.noInit.}: Fp12[BN254_Snarks] - x100 {.noInit.}: Fp12[BN254_Snarks] - x110 {.noInit.}: Fp12[BN254_Snarks] - x1100 {.noInit.}: Fp12[BN254_Snarks] - x1111 {.noInit.}: Fp12[BN254_Snarks] - x10010 {.noInit.}: Fp12[BN254_Snarks] - x10110 {.noInit.}: Fp12[BN254_Snarks] - x11100 {.noInit.}: Fp12[BN254_Snarks] - x101110 {.noInit.}: Fp12[BN254_Snarks] - x1001010 {.noInit.}: Fp12[BN254_Snarks] - x1111000 {.noInit.}: Fp12[BN254_Snarks] - x10001110 {.noInit.}: Fp12[BN254_Snarks] - - x10 .cyclotomic_square(a) - x11 .prod(x10, a) - x100 .prod(x11, a) - x110 .prod(x10, x100) - x1100 .cyclotomic_square(x110) - x1111 .prod(x11, x1100) - x10010 .prod(x11, x1111) - x10110 .prod(x100, x10010) - x11100 .prod(x110, x10110) - x101110 .prod(x10010, x11100) - x1001010 .prod(x11100, x101110) - x1111000 .prod(x101110, x1001010) - x10001110 .prod(x10110, x1111000) - - var - i15 {.noInit.}: Fp12[BN254_Snarks] - i16 {.noInit.}: Fp12[BN254_Snarks] - i17 {.noInit.}: Fp12[BN254_Snarks] - i18 {.noInit.}: Fp12[BN254_Snarks] - i20 {.noInit.}: Fp12[BN254_Snarks] - i21 {.noInit.}: Fp12[BN254_Snarks] - i22 {.noInit.}: Fp12[BN254_Snarks] - i26 {.noInit.}: Fp12[BN254_Snarks] - i27 {.noInit.}: Fp12[BN254_Snarks] - i61 {.noInit.}: Fp12[BN254_Snarks] - - i15.cyclotomic_square(x10001110) - i15 *= x1001010 - i16.prod(x10001110, i15) - i17.prod(x1111, i16) - i18.prod(i16, i17) - - i20.cyclotomic_square(i18) - i20 *= i17 - i21.prod(x1111000, i20) - i22.prod(i15, i21) - - i26.cyclotomic_square(i22) - i26.cyclotomic_square() - i26 *= i22 - i26 *= i18 - - i27.prod(i22, i26) - - i61.prod(i26, i27) - i61.cycl_sqr_repeated(17) - i61 *= i27 - i61.cycl_sqr_repeated(14) - i61 *= i21 - - r = i61 - r.cycl_sqr_repeated(16) - r *= i20 - - if invert: - r.cyclotomic_inv() - func finalExpHard_BN*[C: static Curve](f: var Fp12[C]) = ## Hard part of the final exponentiation ## Specialized for BN curves @@ -302,7 +173,7 @@ func finalExpHard_BN*[C: static Curve](f: var Fp12[C]) = t1 *= t0 # t1 = f^6|u| t2.pow_u(t1, invert = false) # t2 = f^6u² - if C.get(ate_param_is_Neg): + if C.pairing(ate_param_is_Neg): t3.cyclotomic_inv(t1) # t3 = f^6u else: t3 = t1 # t3 = f^6u @@ -311,7 +182,7 @@ func finalExpHard_BN*[C: static Curve](f: var Fp12[C]) = t4.pow_u(t3) # t4 = f^12u³ t4 *= t1 # t4 = f^(6u + 6u² + 12u³) = f^λ₂ - if not C.get(ate_param_is_Neg): + if not C.pairing(ate_param_is_Neg): t0.cyclotomic_inv() # t0 = f^-2u t3.prod(t4, t0) # t3 = f^(4u + 6u² + 12u³) diff --git a/tests/t_bigints_mod_vs_gmp.nim b/tests/t_bigints_mod_vs_gmp.nim index 6a9c654..241df7c 100644 --- a/tests/t_bigints_mod_vs_gmp.nim +++ b/tests/t_bigints_mod_vs_gmp.nim @@ -33,10 +33,15 @@ const CryptoModSizes = [ # Barreto-Naehrig 254, # BN254 # Barreto-Lynn-Scott + 377, # BLS12-377 381, # BLS12-381 - 383, # BLS12-383 - 461, # BLS12-461 - 480, # BLS24-480 + # Brezing-Weng + 761, # BW6-761 + # Cocks-Pinch + 782, # CP6-782 + # Miyaji-Nakabayashi-Takano + 298, # MNT4-298, MNT6-298 + 753, # MNT4-753, MNT6-753 # NIST recommended curves for US Federal Government (FIPS) # https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf 192, diff --git a/tests/t_finite_fields_powinv.nim b/tests/t_finite_fields_powinv.nim index 2608b91..9271c78 100644 --- a/tests/t_finite_fields_powinv.nim +++ b/tests/t_finite_fields_powinv.nim @@ -198,10 +198,6 @@ proc main() = testRandomDiv2 Secp256k1 testRandomDiv2 BLS12_377 testRandomDiv2 BLS12_381 - testRandomDiv2 BN446 - testRandomDiv2 FKM12_447 - testRandomDiv2 BLS12_461 - testRandomDiv2 BN462 suite "Modular inversion over prime fields" & " [" & $WordBitwidth & "-bit mode]": test "Specific tests on Fp[BLS12_381]": @@ -289,10 +285,6 @@ proc main() = testRandomInv Secp256k1 testRandomInv BLS12_377 testRandomInv BLS12_381 - testRandomInv BN446 - testRandomInv FKM12_447 - testRandomInv BLS12_461 - testRandomInv BN462 main() diff --git a/tests/t_finite_fields_sqrt.nim b/tests/t_finite_fields_sqrt.nim index 9387f3b..93436e3 100644 --- a/tests/t_finite_fields_sqrt.nim +++ b/tests/t_finite_fields_sqrt.nim @@ -129,17 +129,13 @@ proc main() = randomSqrtCheck Secp256k1 randomSqrtCheck BLS12_377 # p ≢ 3 (mod 4) randomSqrtCheck BLS12_381 - randomSqrtCheck BN446 - randomSqrtCheck FKM12_447 - randomSqrtCheck BLS12_461 - randomSqrtCheck BN462 suite "Modular square root - 32-bit bugs highlighted by property-based testing " & " [" & $WordBitwidth & "-bit mode]": - test "FKM12_447 - #30": - var a: Fp[FKM12_447] - a.fromHex"0x406e5e74ee09c84fa0c59f2db3ac814a4937e2f57ecd3c0af4265e04598d643c5b772a6549a2d9b825445c34b8ba100fe8d912e61cfda43d" - a.square() - check: bool a.isSquare() + # test "FKM12_447 - #30": - Deactivated, we don't support the curve as no one uses it. + # var a: Fp[FKM12_447] + # a.fromHex"0x406e5e74ee09c84fa0c59f2db3ac814a4937e2f57ecd3c0af4265e04598d643c5b772a6549a2d9b825445c34b8ba100fe8d912e61cfda43d" + # a.square() + # check: bool a.isSquare() test "Fused modular square root on 32-bit - inconsistent with isSquare - #42": var a: Fp[BLS12_381] diff --git a/tests/t_fp12_frobenius.nim b/tests/t_fp12_frobenius.nim index c858bf1..b0d6126 100644 --- a/tests/t_fp12_frobenius.nim +++ b/tests/t_fp12_frobenius.nim @@ -18,10 +18,6 @@ const TestCurves = [ BN254_Snarks, BLS12_377, BLS12_381, - # BN446 - # FKM12_447 - # BLS12_461 - # BN462 ] runFrobeniusTowerTests( diff --git a/tests/t_fp2.nim b/tests/t_fp2.nim index 6f97a87..6d942cb 100644 --- a/tests/t_fp2.nim +++ b/tests/t_fp2.nim @@ -14,14 +14,10 @@ import ./t_fp_tower_template const TestCurves = [ - # BN254_Nogami + BN254_Nogami, BN254_Snarks, BLS12_377, BLS12_381, - # BN446 - # FKM12_447 - # BLS12_461 - # BN462 ] runTowerTests( diff --git a/tests/t_fp2_frobenius.nim b/tests/t_fp2_frobenius.nim index 2123959..8b5847e 100644 --- a/tests/t_fp2_frobenius.nim +++ b/tests/t_fp2_frobenius.nim @@ -18,10 +18,6 @@ const TestCurves = [ BN254_Snarks, BLS12_377, BLS12_381, - # BN446 - # FKM12_447 - # BLS12_461 - # BN462 ] runFrobeniusTowerTests( diff --git a/tests/t_fp4_frobenius.nim b/tests/t_fp4_frobenius.nim index c07efbd..fd505ab 100644 --- a/tests/t_fp4_frobenius.nim +++ b/tests/t_fp4_frobenius.nim @@ -16,12 +16,8 @@ import const TestCurves = [ BN254_Nogami, BN254_Snarks, - # BLS12_377, + BLS12_377, BLS12_381, - # BN446 - # FKM12_447 - # BLS12_461 - # BN462 ] runFrobeniusTowerTests( diff --git a/tests/t_fp6_frobenius.nim b/tests/t_fp6_frobenius.nim index 0c54354..99b0e45 100644 --- a/tests/t_fp6_frobenius.nim +++ b/tests/t_fp6_frobenius.nim @@ -16,12 +16,8 @@ import const TestCurves = [ BN254_Nogami, BN254_Snarks, - # BLS12_377, + BLS12_377, BLS12_381, - # BN446 - # FKM12_447 - # BLS12_461 - # BN462 ] runFrobeniusTowerTests( diff --git a/tests/t_precomputed.nim b/tests/t_fp_cubic_root.nim similarity index 71% rename from tests/t_precomputed.nim rename to tests/t_fp_cubic_root.nim index 0518937..f32a96f 100644 --- a/tests/t_precomputed.nim +++ b/tests/t_fp_cubic_root.nim @@ -10,7 +10,7 @@ import std/unittest, ../constantine/config/common, ../constantine/arithmetic, ../constantine/config/curves, - ../constantine/io/[io_bigints, io_fields] + ../constantine/curves/zoo_glv echo "\n------------------------------------------------------\n" @@ -22,19 +22,10 @@ proc checkCubeRootOfUnity(curve: static Curve) = check: bool cru.isOne() - test $curve & " cube root of unity (mod r)": - var cru: BigInt[3 * curve.getCurveOrderBitwidth()] - cru.prod(curve.getCubicRootOfUnity_mod_r(), curve.getCubicRootOfUnity_mod_r()) - cru.mul(curve.getCubicRootOfUnity_mod_r()) - - var r: BigInt[curve.getCurveOrderBitwidth()] - r.reduce(cru, curve.getCurveOrder) - - check: bool r.isOne() - proc main() = suite "Sanity checks on precomputed values" & " [" & $WordBitwidth & "-bit mode]": checkCubeRootOfUnity(BN254_Snarks) - # checkCubeRootOfUnity(BLS12_381) + checkCubeRootOfUnity(BLS12_377) + checkCubeRootOfUnity(BLS12_381) main()