Merge pull request #94 from mratsim/reorg-curves-constants
Reorg curves constants
This commit is contained in:
commit
51586c7272
146
README.md
146
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`.
|
||||
|
|
|
@ -37,10 +37,6 @@ const AvailableCurves = [
|
|||
# Secp256k1,
|
||||
BLS12_377,
|
||||
BLS12_381,
|
||||
# BN446,
|
||||
# FKM12_447,
|
||||
# BLS12_461,
|
||||
# BN462
|
||||
]
|
||||
|
||||
proc main() =
|
||||
|
|
|
@ -38,10 +38,6 @@ const AvailableCurves = [
|
|||
# Secp256k1,
|
||||
BLS12_377,
|
||||
BLS12_381,
|
||||
# BN446,
|
||||
# FKM12_447,
|
||||
# BLS12_461,
|
||||
# BN462
|
||||
]
|
||||
|
||||
proc main() =
|
||||
|
|
|
@ -35,10 +35,6 @@ const AvailableCurves = [
|
|||
# Secp256k1,
|
||||
BLS12_377,
|
||||
BLS12_381,
|
||||
# BN446,
|
||||
# FKM12_447,
|
||||
# BLS12_461,
|
||||
# BN462
|
||||
]
|
||||
|
||||
proc main() =
|
||||
|
|
|
@ -31,10 +31,6 @@ const AvailableCurves = [
|
|||
BN254_Snarks,
|
||||
BLS12_377,
|
||||
BLS12_381
|
||||
# BN446,
|
||||
# FKM12_447,
|
||||
# BLS12_461,
|
||||
# BN462
|
||||
]
|
||||
|
||||
proc main() =
|
||||
|
|
|
@ -31,10 +31,6 @@ const AvailableCurves = [
|
|||
BN254_Snarks,
|
||||
BLS12_377,
|
||||
BLS12_381
|
||||
# BN446,
|
||||
# FKM12_447,
|
||||
# BLS12_461,
|
||||
# BN462
|
||||
]
|
||||
|
||||
proc main() =
|
||||
|
|
|
@ -30,11 +30,7 @@ const AvailableCurves = [
|
|||
BN254_Nogami,
|
||||
BN254_Snarks,
|
||||
BLS12_377,
|
||||
BLS12_381
|
||||
# BN446,
|
||||
# FKM12_447,
|
||||
# BLS12_461,
|
||||
# BN462
|
||||
BLS12_381,
|
||||
]
|
||||
|
||||
proc main() =
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -10,8 +10,8 @@ import
|
|||
# Standard library
|
||||
std/macros,
|
||||
# Internal
|
||||
../config/common,
|
||||
../primitives
|
||||
../../config/common,
|
||||
../../primitives
|
||||
|
||||
# ############################################################
|
||||
#
|
|
@ -10,9 +10,9 @@ import
|
|||
# Standard library
|
||||
std/macros,
|
||||
# Internal
|
||||
../config/common,
|
||||
../primitives,
|
||||
./limbs
|
||||
../../config/common,
|
||||
../../primitives,
|
||||
../limbs
|
||||
|
||||
# ############################################################
|
||||
#
|
|
@ -10,9 +10,9 @@ import
|
|||
# Standard library
|
||||
std/macros,
|
||||
# Internal
|
||||
../config/common,
|
||||
../primitives,
|
||||
./limbs,
|
||||
../../config/common,
|
||||
../../primitives,
|
||||
../limbs,
|
||||
./limbs_asm_montred_x86
|
||||
|
||||
# ############################################################
|
|
@ -10,9 +10,9 @@ import
|
|||
# Standard library
|
||||
std/macros,
|
||||
# Internal
|
||||
../config/common,
|
||||
../primitives,
|
||||
./limbs,
|
||||
../../config/common,
|
||||
../../primitives,
|
||||
../limbs,
|
||||
./limbs_asm_montred_x86
|
||||
|
||||
# ############################################################
|
|
@ -10,9 +10,9 @@ import
|
|||
# Standard library
|
||||
std/macros,
|
||||
# Internal
|
||||
../config/common,
|
||||
../primitives,
|
||||
./limbs
|
||||
../../config/common,
|
||||
../../primitives,
|
||||
../limbs
|
||||
|
||||
# ############################################################
|
||||
#
|
|
@ -10,9 +10,9 @@ import
|
|||
# Standard library
|
||||
std/macros,
|
||||
# Internal
|
||||
../config/common,
|
||||
../primitives,
|
||||
./limbs,
|
||||
../../config/common,
|
||||
../../primitives,
|
||||
../limbs,
|
||||
./limbs_asm_montred_x86
|
||||
|
||||
# ############################################################
|
|
@ -10,8 +10,8 @@ import
|
|||
# Standard library
|
||||
std/macros,
|
||||
# Internal
|
||||
../config/common,
|
||||
../primitives
|
||||
../../config/common,
|
||||
../../primitives
|
||||
|
||||
# ############################################################
|
||||
#
|
|
@ -10,8 +10,8 @@ import
|
|||
# Standard library
|
||||
std/macros,
|
||||
# Internal
|
||||
../config/common,
|
||||
../primitives
|
||||
../../config/common,
|
||||
../../primitives
|
||||
|
||||
# ############################################################
|
||||
#
|
|
@ -10,8 +10,8 @@ import
|
|||
# Standard library
|
||||
std/macros,
|
||||
# Internal
|
||||
../config/common,
|
||||
../primitives
|
||||
../../config/common,
|
||||
../../primitives
|
||||
|
||||
# ############################################################
|
||||
#
|
|
@ -10,7 +10,7 @@ import
|
|||
../config/[common, type_bigint],
|
||||
../primitives,
|
||||
./limbs,
|
||||
./limbs_generic_modular,
|
||||
./limbs_modular,
|
||||
./limbs_montgomery
|
||||
|
||||
export BigInt
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
|
|
|
@ -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 "----------------------------------------------------------------------------"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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"
|
||||
)
|
|
@ -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)
|
||||
)
|
|
@ -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()
|
|
@ -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"
|
|
@ -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"
|
||||
)
|
|
@ -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)
|
||||
)
|
|
@ -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
|
|
@ -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()
|
|
@ -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"
|
||||
)
|
|
@ -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()
|
|
@ -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"
|
||||
)
|
|
@ -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
|
||||
)
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -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)
|
|
@ -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")
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
# ----------------------------------------------------------------
|
||||
|
|
|
@ -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])
|
|
@ -12,8 +12,6 @@ import
|
|||
std/typetraits,
|
||||
# Internal
|
||||
./io_bigints, ./io_fields,
|
||||
../config/curves,
|
||||
../arithmetic/finite_fields,
|
||||
../towers
|
||||
|
||||
# No exceptions allowed
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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³)
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -18,10 +18,6 @@ const TestCurves = [
|
|||
BN254_Snarks,
|
||||
BLS12_377,
|
||||
BLS12_381,
|
||||
# BN446
|
||||
# FKM12_447
|
||||
# BLS12_461
|
||||
# BN462
|
||||
]
|
||||
|
||||
runFrobeniusTowerTests(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -18,10 +18,6 @@ const TestCurves = [
|
|||
BN254_Snarks,
|
||||
BLS12_377,
|
||||
BLS12_381,
|
||||
# BN446
|
||||
# FKM12_447
|
||||
# BLS12_461
|
||||
# BN462
|
||||
]
|
||||
|
||||
runFrobeniusTowerTests(
|
||||
|
|
|
@ -16,12 +16,8 @@ import
|
|||
const TestCurves = [
|
||||
BN254_Nogami,
|
||||
BN254_Snarks,
|
||||
# BLS12_377,
|
||||
BLS12_377,
|
||||
BLS12_381,
|
||||
# BN446
|
||||
# FKM12_447
|
||||
# BLS12_461
|
||||
# BN462
|
||||
]
|
||||
|
||||
runFrobeniusTowerTests(
|
||||
|
|
|
@ -16,12 +16,8 @@ import
|
|||
const TestCurves = [
|
||||
BN254_Nogami,
|
||||
BN254_Snarks,
|
||||
# BLS12_377,
|
||||
BLS12_377,
|
||||
BLS12_381,
|
||||
# BN446
|
||||
# FKM12_447
|
||||
# BLS12_461
|
||||
# BN462
|
||||
]
|
||||
|
||||
runFrobeniusTowerTests(
|
||||
|
|
|
@ -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()
|
Loading…
Reference in New Issue