Optimized subgroup checks and cofactor clearing (#169)
* Move cofactor clearing to dedicated per-curve subgroups file * Add BLS12-381 fast subgroup checks * Implement fast cofactor clearing for BN254_snarks * Add fast subgroup check to BN254Snarks * add BLS12_377 optimized cofactor and subgroup functions * Add BN254_Nogami * Add GT-subgroup tests * Use the new subgroup checks for Eth1 EVM precompiles
This commit is contained in:
parent
c42e2a0251
commit
f6c02fe075
|
@ -16,10 +16,9 @@ import
|
||||||
# Internals
|
# Internals
|
||||||
../constantine/config/[curves, common],
|
../constantine/config/[curves, common],
|
||||||
../constantine/arithmetic,
|
../constantine/arithmetic,
|
||||||
../constantine/io/io_bigints,
|
|
||||||
../constantine/towers,
|
../constantine/towers,
|
||||||
../constantine/elliptic/[ec_shortweierstrass_projective, ec_shortweierstrass_affine],
|
../constantine/ec_shortweierstrass,
|
||||||
../constantine/hash_to_curve/cofactors,
|
../constantine/curves/zoo_subgroups,
|
||||||
../constantine/pairing/[
|
../constantine/pairing/[
|
||||||
cyclotomic_fp12,
|
cyclotomic_fp12,
|
||||||
lines_projective,
|
lines_projective,
|
||||||
|
@ -48,17 +47,17 @@ template bench(op: string, C: static Curve, iters: int, body: untyped): untyped
|
||||||
measure(iters, startTime, stopTime, startClk, stopClk, body)
|
measure(iters, startTime, stopTime, startClk, stopClk, body)
|
||||||
report(op, $C, startTime, stopTime, startClk, stopClk, iters)
|
report(op, $C, startTime, stopTime, startClk, stopClk, iters)
|
||||||
|
|
||||||
func clearCofactorReference[F; G: static Subgroup](
|
func clearCofactor[F; G: static Subgroup](
|
||||||
ec: var ECP_ShortW_Aff[F, G]) =
|
ec: var ECP_ShortW_Aff[F, G]) =
|
||||||
# For now we don't have any affine operation defined
|
# For now we don't have any affine operation defined
|
||||||
var t {.noInit.}: ECP_ShortW_Prj[F, G]
|
var t {.noInit.}: ECP_ShortW_Prj[F, G]
|
||||||
t.projectiveFromAffine(ec)
|
t.projectiveFromAffine(ec)
|
||||||
t.clearCofactorReference()
|
t.clearCofactor()
|
||||||
ec.affineFromProjective(t)
|
ec.affineFromProjective(t)
|
||||||
|
|
||||||
func random_point*(rng: var RngState, EC: typedesc): EC {.noInit.} =
|
func random_point*(rng: var RngState, EC: typedesc): EC {.noInit.} =
|
||||||
result = rng.random_unsafe(EC)
|
result = rng.random_unsafe(EC)
|
||||||
result.clearCofactorReference()
|
result.clearCofactor()
|
||||||
|
|
||||||
proc lineDoubleBench*(C: static Curve, iters: int) =
|
proc lineDoubleBench*(C: static Curve, iters: int) =
|
||||||
var line: Line[Fp2[C]]
|
var line: Line[Fp2[C]]
|
||||||
|
|
|
@ -21,7 +21,8 @@ import
|
||||||
ec_shortweierstrass_projective,
|
ec_shortweierstrass_projective,
|
||||||
ec_shortweierstrass_jacobian,
|
ec_shortweierstrass_jacobian,
|
||||||
ec_scalar_mul, ec_endomorphism_accel],
|
ec_scalar_mul, ec_endomorphism_accel],
|
||||||
../constantine/hash_to_curve/[cofactors, hash_to_curve],
|
../constantine/curves/zoo_subgroups,
|
||||||
|
../constantine/hash_to_curve/hash_to_curve,
|
||||||
../constantine/pairing/[
|
../constantine/pairing/[
|
||||||
cyclotomic_fp12,
|
cyclotomic_fp12,
|
||||||
pairing_bls12,
|
pairing_bls12,
|
||||||
|
|
|
@ -143,6 +143,19 @@ const testDesc: seq[tuple[path: string, useGMP: bool]] = @[
|
||||||
# Edge cases highlighted by past bugs
|
# Edge cases highlighted by past bugs
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
("tests/t_ec_shortw_prj_edge_cases.nim", false),
|
("tests/t_ec_shortw_prj_edge_cases.nim", false),
|
||||||
|
|
||||||
|
# Subgroups and cofactors
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
("tests/t_ec_subgroups_bn254_nogami.nim", false),
|
||||||
|
("tests/t_ec_subgroups_bn254_snarks.nim", false),
|
||||||
|
("tests/t_ec_subgroups_bls12_377.nim", false),
|
||||||
|
("tests/t_ec_subgroups_bls12_381.nim", false),
|
||||||
|
|
||||||
|
("tests/t_pairing_bn254_nogami_gt_subgroup.nim", false),
|
||||||
|
("tests/t_pairing_bn254_snarks_gt_subgroup.nim", false),
|
||||||
|
("tests/t_pairing_bls12_377_gt_subgroup.nim", false),
|
||||||
|
("tests/t_pairing_bls12_381_gt_subgroup.nim", false),
|
||||||
|
|
||||||
# Pairing
|
# Pairing
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
# ("tests/t_pairing_bls12_377_line_functions.nim", false),
|
# ("tests/t_pairing_bls12_377_line_functions.nim", false),
|
||||||
|
|
|
@ -4,6 +4,8 @@ This folder holds curve-specific constants and procedure in particular:
|
||||||
|
|
||||||
- Inversion addition chains
|
- Inversion addition chains
|
||||||
- Final exponentiation addition chains
|
- Final exponentiation addition chains
|
||||||
- Square root constants for Tonelli Shanks
|
- Square root addition chains and constants for Tonelli Shanks
|
||||||
- Lattice decomposition constants for endomorphism acceleration
|
- Lattice decomposition constants for endomorphism acceleration
|
||||||
- Frobenius endomorphism constants
|
- Frobenius endomorphism constants
|
||||||
|
- Cofactor clearing
|
||||||
|
- Subgroup checks
|
|
@ -7,11 +7,12 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../config/[curves, type_bigint, type_ff],
|
../config/[common, curves, type_bigint, type_ff],
|
||||||
../io/io_bigints,
|
../io/io_bigints,
|
||||||
../towers,
|
../towers,
|
||||||
../elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
|
../elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
|
||||||
../pairing/[cyclotomic_fp12, miller_loops]
|
../pairing/[cyclotomic_fp12, miller_loops],
|
||||||
|
../isogeny/frobenius
|
||||||
|
|
||||||
# Slow generic implementation
|
# Slow generic implementation
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
@ -84,3 +85,16 @@ func pow_x*(r: var Fp12[BLS12_377], a: Fp12[BLS12_377], invert = BLS12_377_pairi
|
||||||
|
|
||||||
if invert:
|
if invert:
|
||||||
r.cyclotomic_inv()
|
r.cyclotomic_inv()
|
||||||
|
|
||||||
|
func isInPairingSubgroup*(a: Fp12[BLS12_377]): SecretBool =
|
||||||
|
## Returns true if a is in GT subgroup, i.e. a is an element of order r
|
||||||
|
## Warning ⚠: Assumes that a is in the cyclotomic subgroup
|
||||||
|
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||||
|
# A note on group membership tests for G1, G2 and GT
|
||||||
|
# on BLS pairing-friendly curves
|
||||||
|
# P is in the G1 subgroup iff a^p == a^u
|
||||||
|
var t0{.noInit.}, t1{.noInit.}: Fp12[BLS12_377]
|
||||||
|
t0.frobenius_map(a)
|
||||||
|
t1.pow_x(a)
|
||||||
|
|
||||||
|
return t0 == t1
|
|
@ -0,0 +1,212 @@
|
||||||
|
# Constantine
|
||||||
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||||
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||||
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import
|
||||||
|
# Internals
|
||||||
|
../config/[common, curves],
|
||||||
|
../arithmetic,
|
||||||
|
../primitives,
|
||||||
|
../towers,
|
||||||
|
../ec_shortweierstrass,
|
||||||
|
../io/io_bigints,
|
||||||
|
../isogeny/frobenius,
|
||||||
|
../curves/zoo_endomorphisms
|
||||||
|
|
||||||
|
func pow_bls12_377_abs_x[ECP: ECP_ShortW[Fp[BLS12_377], G1] or
|
||||||
|
ECP_ShortW[Fp2[BLS12_377], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) =
|
||||||
|
## Does the scalar multiplication [x]P
|
||||||
|
## with x the absolute value of the BLS12 curve parameter
|
||||||
|
## For BLS12_377 [0x8508c00000000001]P
|
||||||
|
## Requires r and P to not alias
|
||||||
|
r.double(P)
|
||||||
|
r += P
|
||||||
|
r.double()
|
||||||
|
r += P
|
||||||
|
let t111 = r
|
||||||
|
|
||||||
|
r.double_repeated(2)
|
||||||
|
let t111000 = r
|
||||||
|
|
||||||
|
r += t111
|
||||||
|
let t100011 = r
|
||||||
|
|
||||||
|
r.double()
|
||||||
|
r += t100011
|
||||||
|
r += t111000
|
||||||
|
|
||||||
|
r.double_repeated(10)
|
||||||
|
r += t100011
|
||||||
|
|
||||||
|
r.double_repeated(46)
|
||||||
|
r += P
|
||||||
|
|
||||||
|
func pow_bls12_377_x[ECP: ECP_ShortW[Fp[BLS12_377], G1] or
|
||||||
|
ECP_ShortW[Fp2[BLS12_377], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) {.inline.}=
|
||||||
|
## Does the scalar multiplication [x]P
|
||||||
|
## with x the BLS12 curve parameter
|
||||||
|
## For BLS12_377 [0x8508c00000000001]P
|
||||||
|
## Requires r and P to not alias
|
||||||
|
pow_bls12_377_abs_x(r, P)
|
||||||
|
|
||||||
|
func pow_bls12_377_minus_x[ECP: ECP_ShortW[Fp[BLS12_377], G1] or
|
||||||
|
ECP_ShortW[Fp2[BLS12_377], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) {.inline.}=
|
||||||
|
## Does the scalar multiplication [-x]P
|
||||||
|
## with x the BLS12 curve parameter
|
||||||
|
## For BLS12_377 [-0x8508c00000000001]P
|
||||||
|
## Requires r and P to not alias
|
||||||
|
pow_bls12_377_abs_x(r, P)
|
||||||
|
r.neg()
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Clear Cofactor - Naive
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
const Cofactor_Eff_BLS12_377_G1 = BigInt[64].fromHex"0x8508c00000000000"
|
||||||
|
## P -> (1 - x) P
|
||||||
|
const Cofactor_Eff_BLS12_377_G2 = BigInt[629].fromHex"0x1f60243677e30653648d3d9502abfba951764c46f4edd28f6ade35a5c7d769f7ee7c4b03103b45b85860aaaad2927678ba2796373885598e8e73ad8a538800cf664765b00000031e34800000000000"
|
||||||
|
## P -> (x^2 - x - 1) P + (x - 1) ψ(P) + ψ(ψ(2P))
|
||||||
|
##
|
||||||
|
## Effective cofactor from Budroni et al https://eprint.iacr.org/2017/419.pdf
|
||||||
|
## (3x² − 3)*cofactor
|
||||||
|
|
||||||
|
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BLS12_377], G1]) {.inline.} =
|
||||||
|
## Clear the cofactor of BLS12_377 G1
|
||||||
|
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
||||||
|
P.scalarMulGeneric(Cofactor_Eff_BLS12_377_G1)
|
||||||
|
P.neg()
|
||||||
|
|
||||||
|
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp2[BLS12_377], G2]) {.inline.} =
|
||||||
|
## Clear the cofactor of BLS12_377 G2
|
||||||
|
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
||||||
|
P.scalarMulGeneric(Cofactor_Eff_BLS12_377_G2)
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Clear Cofactor - Optimized
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
# BLS12 G1
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp[BLS12_377], G1]) =
|
||||||
|
## Clear the cofactor of BLS12_377 G1
|
||||||
|
##
|
||||||
|
## Wahby et al "Fast and simple constant-time hashing to the BLS12-377 elliptic curve", https://eprint.iacr.org/2019/403
|
||||||
|
## Optimized using endomorphisms
|
||||||
|
## P -> (1 - x) P
|
||||||
|
var t{.noInit.}: typeof(P)
|
||||||
|
t.pow_bls12_377_minus_x(P) # [-x]P
|
||||||
|
P += t # [1-x]P
|
||||||
|
|
||||||
|
# BLS12 G2
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# From any point on the elliptic curve E2 of a BLS12 curve
|
||||||
|
# Obtain a point in the G2 prime-order subgroup
|
||||||
|
#
|
||||||
|
# Described in https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-G.4
|
||||||
|
#
|
||||||
|
# Implementations, multiple implementations are possible in increasing order of speed:
|
||||||
|
#
|
||||||
|
# - The default, canonical, implementation is h_eff * P
|
||||||
|
# - Scott et al, "Fast Hashing to G2 on Pairing-Friendly Curves", https://doi.org/10.1007/978-3-642-03298-1_8
|
||||||
|
# - Fuentes-Castaneda et al, "Fast Hashing to G2 on Pairing-Friendly Curves", https://doi.org/10.1007/978-3-642-28496-0_25
|
||||||
|
# - Budroni et al, "Hashing to G2 on BLS pairing-friendly curves", https://doi.org/10.1145/3313880.3313884
|
||||||
|
# - Wahby et al "Fast and simple constant-time hashing to the BLS12-377 elliptic curve", https://eprint.iacr.org/2019/403
|
||||||
|
# - IETF "Hashing to Elliptic Curves", https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-G.4
|
||||||
|
#
|
||||||
|
# In summary, the elliptic curve point multiplication is very expensive,
|
||||||
|
# the fast methods uses endomorphism acceleration instead.
|
||||||
|
#
|
||||||
|
# The method described in Wahby et al is implemented by Riad Wahby
|
||||||
|
# in C at: https://github.com/kwantam/bls12-377_hash/blob/23c1930039f58606138459557677668fabc8ce39/src/curve2/ops2.c#L106-L204
|
||||||
|
# following Budroni et al, "Efficient hash maps to G2 on BLS curves"
|
||||||
|
# https://eprint.iacr.org/2017/419
|
||||||
|
#
|
||||||
|
# "P -> [x² - x - 1] P + [x - 1] ψ(P) + ψ(ψ([2]P))"
|
||||||
|
#
|
||||||
|
# with Psi (ψ) - untwist-Frobenius-Twist function
|
||||||
|
# and x the curve BLS parameter
|
||||||
|
|
||||||
|
func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp2[BLS12_377], G2]) =
|
||||||
|
## Clear the cofactor of BLS12_377 G2
|
||||||
|
## Optimized using endomorphisms
|
||||||
|
## P -> [x²-x-1]P + [x-1] ψ(P) + ψ²([2]P)
|
||||||
|
|
||||||
|
var xP{.noInit.}, x2P{.noInit.}: typeof(P)
|
||||||
|
|
||||||
|
xP.pow_bls12_377_x(P) # 1. xP = [x]P
|
||||||
|
x2P.pow_bls12_377_x(xP) # 2. x2P = [x²]P
|
||||||
|
|
||||||
|
x2P.diff(x2P, xP) # 3. x2P = [x²-x]P
|
||||||
|
x2P.diff(x2P, P) # 4. x2P = [x²-x-1]P
|
||||||
|
|
||||||
|
xP.diff(xP, P) # 5. xP = [x-1]P
|
||||||
|
xP.frobenius_psi(xP) # 6. xP = ψ([x-1]P) = [x-1] ψ(P)
|
||||||
|
|
||||||
|
P.double(P) # 7. P = [2]P
|
||||||
|
P.frobenius_psi(P, k=2) # 8. P = ψ²([2]P)
|
||||||
|
|
||||||
|
P.sum(P, x2P) # 9. P = [x²-x-1]P + ψ²([2]P)
|
||||||
|
P.sum(P, xP) # 10. P = [x²-x-1]P + [x-1] ψ(P) + ψ²([2]P)
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Subgroup checks
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
func isInSubgroup*(P: ECP_ShortW_Prj[Fp[BLS12_377], G1]): SecretBool =
|
||||||
|
## Returns true if P is in G1 subgroup, i.e. P is a point of order r.
|
||||||
|
## A point may be on a curve but not on the prime order r subgroup.
|
||||||
|
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||||
|
##
|
||||||
|
## Warning ⚠: Assumes that P is on curve
|
||||||
|
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||||
|
# A note on group membership tests for G1, G2 and GT
|
||||||
|
# on BLS pairing-friendly curves
|
||||||
|
# P is in the G1 subgroup iff phi(P) == [-u²](P)
|
||||||
|
var t0{.noInit.}, t1{.noInit.}: ECP_ShortW_Prj[Fp[BLS12_377], G1]
|
||||||
|
|
||||||
|
# [-u²]P
|
||||||
|
t0.pow_bls12_377_x(P)
|
||||||
|
t1.pow_bls12_377_minus_x(t0)
|
||||||
|
|
||||||
|
# phi(P)
|
||||||
|
t0.x.prod(P.x, BLS12_377.getCubicRootOfUnity_mod_p())
|
||||||
|
t0.y = P.y
|
||||||
|
t0.z = P.z
|
||||||
|
|
||||||
|
return t0 == t1
|
||||||
|
|
||||||
|
func isInSubgroup*(P: ECP_ShortW_Prj[Fp2[BLS12_377], G2]): SecretBool =
|
||||||
|
## Returns true if P is in G2 subgroup, i.e. P is a point of order r.
|
||||||
|
## A point may be on a curve but not on the prime order r subgroup.
|
||||||
|
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||||
|
##
|
||||||
|
## Warning ⚠: Assumes that P is on curve
|
||||||
|
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||||
|
# A note on group membership tests for G1, G2 and GT
|
||||||
|
# on BLS pairing-friendly curves
|
||||||
|
# P is in the G1 subgroup iff ψ(P) == [u](P)
|
||||||
|
var t0{.noInit.}, t1{.noInit.}: ECP_ShortW_Prj[Fp2[BLS12_377], G2]
|
||||||
|
t0.pow_bls12_377_x(P) # [u]P
|
||||||
|
t1.frobenius_psi(P) # ψ(P)
|
||||||
|
|
||||||
|
return t0 == t1
|
|
@ -7,11 +7,12 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../config/[curves, type_bigint, type_ff],
|
../config/[common, curves, type_bigint, type_ff],
|
||||||
../io/io_bigints,
|
../io/io_bigints,
|
||||||
../towers,
|
../towers,
|
||||||
../elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
|
../elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
|
||||||
../pairing/[cyclotomic_fp12, miller_loops]
|
../pairing/[cyclotomic_fp12, miller_loops],
|
||||||
|
../isogeny/frobenius
|
||||||
|
|
||||||
# Slow generic implementation
|
# Slow generic implementation
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
@ -105,3 +106,16 @@ func pow_x*(r: var Fp12[BLS12_381], a: Fp12[BLS12_381], invert = BLS12_381_pairi
|
||||||
## For BLS12_381 f^-0xd201000000010000
|
## For BLS12_381 f^-0xd201000000010000
|
||||||
r.pow_xdiv2(a, invert)
|
r.pow_xdiv2(a, invert)
|
||||||
r.cyclotomic_square()
|
r.cyclotomic_square()
|
||||||
|
|
||||||
|
func isInPairingSubgroup*(a: Fp12[BLS12_381]): SecretBool =
|
||||||
|
## Returns true if a is in GT subgroup, i.e. a is an element of order r
|
||||||
|
## Warning ⚠: Assumes that a is in the cyclotomic subgroup
|
||||||
|
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||||
|
# A note on group membership tests for G1, G2 and GT
|
||||||
|
# on BLS pairing-friendly curves
|
||||||
|
# P is in the G1 subgroup iff a^p == a^u
|
||||||
|
var t0{.noInit.}, t1{.noInit.}: Fp12[BLS12_381]
|
||||||
|
t0.frobenius_map(a)
|
||||||
|
t1.pow_x(a)
|
||||||
|
|
||||||
|
return t0 == t1
|
|
@ -8,14 +8,66 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
# Internals
|
# Internals
|
||||||
../config/common,
|
../config/[common, curves],
|
||||||
../arithmetic,
|
../arithmetic,
|
||||||
../primitives,
|
../primitives,
|
||||||
../towers,
|
../towers,
|
||||||
../config/curves,
|
../ec_shortweierstrass,
|
||||||
../io/io_bigints,
|
../io/io_bigints,
|
||||||
../elliptic/[ec_shortweierstrass_projective, ec_scalar_mul],
|
../isogeny/frobenius,
|
||||||
../isogeny/frobenius
|
../curves/zoo_endomorphisms
|
||||||
|
|
||||||
|
func pow_bls12_381_abs_x[ECP: ECP_ShortW[Fp[BLS12_381], G1] or
|
||||||
|
ECP_ShortW[Fp2[BLS12_381], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) =
|
||||||
|
## Does the scalar multiplication [x]P
|
||||||
|
## with x the absolute value of the BLS12 curve parameter
|
||||||
|
## For BLS12_381 [0xd201000000010000]P
|
||||||
|
## Requires r and P to not alias
|
||||||
|
|
||||||
|
# In binary
|
||||||
|
# 0b11
|
||||||
|
r.double(P)
|
||||||
|
r += P
|
||||||
|
# 0b1101
|
||||||
|
r.double_repeated(2)
|
||||||
|
r += P
|
||||||
|
# 0b1101001
|
||||||
|
r.double_repeated(3)
|
||||||
|
r += P
|
||||||
|
# 0b1101001000000001
|
||||||
|
r.double_repeated(9)
|
||||||
|
r += P
|
||||||
|
# 0b110100100000000100000000000000000000000000000001
|
||||||
|
r.double_repeated(32)
|
||||||
|
r += P
|
||||||
|
# 0b1101001000000001000000000000000000000000000000010000000000000000
|
||||||
|
r.double_repeated(16)
|
||||||
|
|
||||||
|
func pow_bls12_381_x[ECP: ECP_ShortW[Fp[BLS12_381], G1] or
|
||||||
|
ECP_ShortW[Fp2[BLS12_381], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) {.inline.}=
|
||||||
|
## Does the scalar multiplication [x]P
|
||||||
|
## with x the BLS12 curve parameter
|
||||||
|
## For BLS12_381 [-0xd201000000010000]P
|
||||||
|
## Requires r and P to not alias
|
||||||
|
pow_bls12_381_abs_x(r, P)
|
||||||
|
r.neg()
|
||||||
|
|
||||||
|
func pow_bls12_381_minus_x[ECP: ECP_ShortW[Fp[BLS12_381], G1] or
|
||||||
|
ECP_ShortW[Fp2[BLS12_381], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) {.inline.}=
|
||||||
|
## Does the scalar multiplication [-x]P
|
||||||
|
## with x the BLS12 curve parameter
|
||||||
|
## For BLS12_381 [0xd201000000010000]P
|
||||||
|
## Requires r and P to not alias
|
||||||
|
pow_bls12_381_abs_x(r, P)
|
||||||
|
|
||||||
# ############################################################
|
# ############################################################
|
||||||
#
|
#
|
||||||
|
@ -23,63 +75,12 @@ import
|
||||||
#
|
#
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
|
||||||
const Cofactor_Eff_BN254_Nogami_G1 = BigInt[1].fromHex"0x1"
|
|
||||||
const Cofactor_Eff_BN254_Nogami_G2 = BigInt[254].fromHex"0x2523648240000001ba344d8000000008c2a2800000000016ad00000000000019"
|
|
||||||
## G2.order // r
|
|
||||||
|
|
||||||
const Cofactor_Eff_BN254_Snarks_G1 = BigInt[1].fromHex"0x1"
|
|
||||||
const Cofactor_Eff_BN254_Snarks_G2 = BigInt[254].fromHex"0x30644e72e131a029b85045b68181585e06ceecda572a2489345f2299c0f9fa8d"
|
|
||||||
## G2.order // r
|
|
||||||
|
|
||||||
# TODO effective cofactors as per H2C draft like BLS12-381 curve
|
|
||||||
const Cofactor_Eff_BLS12_377_G1 = BigInt[125].fromHex"0x170b5d44300000000000000000000000"
|
|
||||||
## P -> (1 - x) P
|
|
||||||
const Cofactor_Eff_BLS12_377_G2 = BigInt[502].fromHex"0x26ba558ae9562addd88d99a6f6a829fbb36b00e1dcc40c8c505634fae2e189d693e8c36676bd09a0f3622fba094800452217cc900000000000000000000001"
|
|
||||||
## P -> (x^2 - x - 1) P + (x - 1) ψ(P) + ψ(ψ(2P))
|
|
||||||
|
|
||||||
# https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-09#section-8.8
|
# https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-09#section-8.8
|
||||||
const Cofactor_Eff_BLS12_381_G1 = BigInt[64].fromHex"0xd201000000010001"
|
const Cofactor_Eff_BLS12_381_G1 = BigInt[64].fromHex"0xd201000000010001"
|
||||||
## P -> (1 - x) P
|
## P -> (1 - x) P
|
||||||
const Cofactor_Eff_BLS12_381_G2 = BigInt[636].fromHex"0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551"
|
const Cofactor_Eff_BLS12_381_G2 = BigInt[636].fromHex"0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551"
|
||||||
## P -> (x^2 - x - 1) P + (x - 1) ψ(P) + ψ(ψ(2P))
|
## P -> (x^2 - x - 1) P + (x - 1) ψ(P) + ψ(ψ(2P))
|
||||||
|
|
||||||
# TODO https://eprint.iacr.org/2020/351.pdf p12
|
|
||||||
const Cofactor_Eff_BW6_761_G1 = BigInt[384].fromHex"0xad1972339049ce762c77d5ac34cb12efc856a0853c9db94cc61c554757551c0c832ba4061000003b3de580000000007c"
|
|
||||||
## P -> 103([u³]P)− 83([u²]P)−40([u]P)+136P + φ(7([u²]P)+89([u]P)+130P)
|
|
||||||
|
|
||||||
# TODO https://eprint.iacr.org/2020/351.pdf p13
|
|
||||||
const Cofactor_Eff_BW6_761_G2 = BigInt[384].fromHex"0xad1972339049ce762c77d5ac34cb12efc856a0853c9db94cc61c554757551c0c832ba4061000003b3de580000000007c"
|
|
||||||
## P -> (103([u³]P) − 83([u²]P) − 143([u]P) + 27P) + ψ(7([u²]P) − 117([u]P) − 109P)
|
|
||||||
|
|
||||||
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BN254_Nogami], G1]) {.inline.} =
|
|
||||||
## Clear the cofactor of BN254_Nogami G1
|
|
||||||
## BN curve have a G1 cofactor of 1 so this is a no-op
|
|
||||||
discard
|
|
||||||
|
|
||||||
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp2[BN254_Nogami], G2]) {.inline.} =
|
|
||||||
## Clear the cofactor of BN254_Snarks G2
|
|
||||||
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
|
||||||
P.scalarMulGeneric(Cofactor_Eff_BN254_Nogami_G2)
|
|
||||||
|
|
||||||
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BN254_Snarks], G1]) {.inline.} =
|
|
||||||
## Clear the cofactor of BN254_Snarks G1
|
|
||||||
## BN curve have a G1 cofactor of 1 so this is a no-op
|
|
||||||
discard
|
|
||||||
|
|
||||||
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp2[BN254_Snarks], G2]) {.inline.} =
|
|
||||||
## Clear the cofactor of BN254_Snarks G2
|
|
||||||
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
|
||||||
P.scalarMulGeneric(Cofactor_Eff_BN254_Snarks_G2)
|
|
||||||
|
|
||||||
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BLS12_377], G1]) {.inline.} =
|
|
||||||
## Clear the cofactor of BLS12_377 G1
|
|
||||||
P.scalarMulGeneric(Cofactor_Eff_BLS12_377_G1)
|
|
||||||
|
|
||||||
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp2[BLS12_377], G2]) {.inline.} =
|
|
||||||
## Clear the cofactor of BLS12_377 G2
|
|
||||||
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
|
||||||
P.scalarMulGeneric(Cofactor_Eff_BLS12_377_G2)
|
|
||||||
|
|
||||||
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BLS12_381], G1]) {.inline.} =
|
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BLS12_381], G1]) {.inline.} =
|
||||||
## Clear the cofactor of BLS12_381 G1
|
## Clear the cofactor of BLS12_381 G1
|
||||||
P.scalarMulGeneric(Cofactor_Eff_BLS12_381_G1)
|
P.scalarMulGeneric(Cofactor_Eff_BLS12_381_G1)
|
||||||
|
@ -89,21 +90,25 @@ func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp2[BLS12_381], G2]) {.inline
|
||||||
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
||||||
P.scalarMulGeneric(Cofactor_Eff_BLS12_381_G2)
|
P.scalarMulGeneric(Cofactor_Eff_BLS12_381_G2)
|
||||||
|
|
||||||
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BW6_761], G1]) {.inline.} =
|
|
||||||
## Clear the cofactor of BW6_761 G1
|
|
||||||
P.scalarMulGeneric(Cofactor_Eff_BW6_761_G1)
|
|
||||||
|
|
||||||
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BW6_761], G2]) {.inline.} =
|
|
||||||
## Clear the cofactor of BW6_761 G2
|
|
||||||
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
|
||||||
P.scalarMulGeneric(Cofactor_Eff_BW6_761_G2)
|
|
||||||
|
|
||||||
# ############################################################
|
# ############################################################
|
||||||
#
|
#
|
||||||
# Clear Cofactor - Optimized
|
# Clear Cofactor - Optimized
|
||||||
#
|
#
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
|
||||||
|
# BLS12 G1
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp[BLS12_381], G1]) =
|
||||||
|
## Clear the cofactor of BLS12_381 G1
|
||||||
|
##
|
||||||
|
## Wahby et al "Fast and simple constant-time hashing to the BLS12-381 elliptic curve", https://eprint.iacr.org/2019/403
|
||||||
|
## Optimized using endomorphisms
|
||||||
|
## P -> (1 - x) P
|
||||||
|
var t{.noInit.}: typeof(P)
|
||||||
|
t.pow_bls12_381_minus_x(P) # [-x]P
|
||||||
|
P += t # [1-x]P
|
||||||
|
|
||||||
# BLS12 G2
|
# BLS12 G2
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
# From any point on the elliptic curve E2 of a BLS12 curve
|
# From any point on the elliptic curve E2 of a BLS12 curve
|
||||||
|
@ -133,43 +138,6 @@ func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BW6_761], G2]) {.inline.}
|
||||||
# with Psi (ψ) - untwist-Frobenius-Twist function
|
# with Psi (ψ) - untwist-Frobenius-Twist function
|
||||||
# and x the curve BLS parameter
|
# and x the curve BLS parameter
|
||||||
|
|
||||||
func double_repeated*[EC](P: var EC, num: int) {.inline.} =
|
|
||||||
## Repeated doublings
|
|
||||||
for _ in 0 ..< num:
|
|
||||||
P.double()
|
|
||||||
|
|
||||||
func pow_x(
|
|
||||||
r{.noalias.}: var ECP_ShortW_Prj[Fp2[BLS12_381], G2],
|
|
||||||
P{.noalias.}: ECP_ShortW_Prj[Fp2[BLS12_381], G2],
|
|
||||||
) =
|
|
||||||
## Does the scalar multiplication [x]P
|
|
||||||
## with x the BLS12 curve parameter
|
|
||||||
## For BLS12_381 [-0xd201000000010000]P
|
|
||||||
## Requires r and P to not alias
|
|
||||||
|
|
||||||
# In binary
|
|
||||||
# 0b11
|
|
||||||
r.double(P)
|
|
||||||
r += P
|
|
||||||
# 0b1101
|
|
||||||
r.double_repeated(2)
|
|
||||||
r += P
|
|
||||||
# 0b1101001
|
|
||||||
r.double_repeated(3)
|
|
||||||
r += P
|
|
||||||
# 0b1101001000000001
|
|
||||||
r.double_repeated(9)
|
|
||||||
r += P
|
|
||||||
# 0b110100100000000100000000000000000000000000000001
|
|
||||||
r.double_repeated(32)
|
|
||||||
r += P
|
|
||||||
# 0b1101001000000001000000000000000000000000000000010000000000000000
|
|
||||||
r.double_repeated(16)
|
|
||||||
|
|
||||||
# Negative, x = -0xd201000000010000
|
|
||||||
r.neg(r)
|
|
||||||
|
|
||||||
|
|
||||||
func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp2[BLS12_381], G2]) =
|
func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp2[BLS12_381], G2]) =
|
||||||
## Clear the cofactor of BLS12_381 G2
|
## Clear the cofactor of BLS12_381 G2
|
||||||
## Optimized using endomorphisms
|
## Optimized using endomorphisms
|
||||||
|
@ -177,8 +145,8 @@ func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp2[BLS12_381], G2]) =
|
||||||
|
|
||||||
var xP{.noInit.}, x2P{.noInit.}: typeof(P)
|
var xP{.noInit.}, x2P{.noInit.}: typeof(P)
|
||||||
|
|
||||||
xP.pow_x(P) # 1. xP = [x]P
|
xP.pow_bls12_381_x(P) # 1. xP = [x]P
|
||||||
x2P.pow_x(xP) # 2. x2P = [x²]P
|
x2P.pow_bls12_381_x(xP) # 2. x2P = [x²]P
|
||||||
|
|
||||||
x2P.diff(x2P, xP) # 3. x2P = [x²-x]P
|
x2P.diff(x2P, xP) # 3. x2P = [x²-x]P
|
||||||
x2P.diff(x2P, P) # 4. x2P = [x²-x-1]P
|
x2P.diff(x2P, P) # 4. x2P = [x²-x-1]P
|
||||||
|
@ -191,3 +159,48 @@ func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp2[BLS12_381], G2]) =
|
||||||
|
|
||||||
P.sum(P, x2P) # 9. P = [x²-x-1]P + ψ²([2]P)
|
P.sum(P, x2P) # 9. P = [x²-x-1]P + ψ²([2]P)
|
||||||
P.sum(P, xP) # 10. P = [x²-x-1]P + [x-1] ψ(P) + ψ²([2]P)
|
P.sum(P, xP) # 10. P = [x²-x-1]P + [x-1] ψ(P) + ψ²([2]P)
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Subgroup checks
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
func isInSubgroup*(P: ECP_ShortW_Prj[Fp[BLS12_381], G1]): SecretBool =
|
||||||
|
## Returns true if P is in G1 subgroup, i.e. P is a point of order r.
|
||||||
|
## A point may be on a curve but not on the prime order r subgroup.
|
||||||
|
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||||
|
##
|
||||||
|
## Warning ⚠: Assumes that P is on curve
|
||||||
|
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||||
|
# A note on group membership tests for G1, G2 and GT
|
||||||
|
# on BLS pairing-friendly curves
|
||||||
|
# P is in the G1 subgroup iff phi(P) == [-u²](P)
|
||||||
|
var t0{.noInit.}, t1{.noInit.}: ECP_ShortW_Prj[Fp[BLS12_381], G1]
|
||||||
|
|
||||||
|
# [-u²]P
|
||||||
|
t0.pow_bls12_381_x(P)
|
||||||
|
t1.pow_bls12_381_minus_x(t0)
|
||||||
|
|
||||||
|
# phi(P)
|
||||||
|
t0.x.prod(P.x, BLS12_381.getCubicRootOfUnity_mod_p())
|
||||||
|
t0.y = P.y
|
||||||
|
t0.z = P.z
|
||||||
|
|
||||||
|
return t0 == t1
|
||||||
|
|
||||||
|
func isInSubgroup*(P: ECP_ShortW_Prj[Fp2[BLS12_381], G2]): SecretBool =
|
||||||
|
## Returns true if P is in G2 subgroup, i.e. P is a point of order r.
|
||||||
|
## A point may be on a curve but not on the prime order r subgroup.
|
||||||
|
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||||
|
##
|
||||||
|
## Warning ⚠: Assumes that P is on curve
|
||||||
|
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||||
|
# A note on group membership tests for G1, G2 and GT
|
||||||
|
# on BLS pairing-friendly curves
|
||||||
|
# P is in the G1 subgroup iff ψ(P) == [u](P)
|
||||||
|
var t0{.noInit.}, t1{.noInit.}: ECP_ShortW_Prj[Fp2[BLS12_381], G2]
|
||||||
|
t0.pow_bls12_381_x(P) # [u]P
|
||||||
|
t1.frobenius_psi(P) # ψ(P)
|
||||||
|
|
||||||
|
return t0 == t1
|
|
@ -7,11 +7,12 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../config/[curves, type_bigint, type_ff],
|
../config/[common, curves, type_bigint, type_ff],
|
||||||
../io/io_bigints,
|
../io/io_bigints,
|
||||||
../towers,
|
../towers,
|
||||||
../elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
|
../elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
|
||||||
../pairing/[cyclotomic_fp12, miller_loops]
|
../pairing/[cyclotomic_fp12, miller_loops],
|
||||||
|
../isogeny/frobenius
|
||||||
|
|
||||||
# Slow generic implementation
|
# Slow generic implementation
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
@ -68,3 +69,21 @@ func pow_u*(r: var Fp12[BN254_Nogami], a: Fp12[BN254_Nogami], invert = BN254_Nog
|
||||||
|
|
||||||
if invert:
|
if invert:
|
||||||
r.cyclotomic_inv()
|
r.cyclotomic_inv()
|
||||||
|
|
||||||
|
func isInPairingSubgroup*(a: Fp12[BN254_Nogami]): SecretBool =
|
||||||
|
## Returns true if a is in GT subgroup, i.e. a is an element of order r
|
||||||
|
## Warning ⚠: Assumes that a is in the cyclotomic subgroup
|
||||||
|
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||||
|
# A note on group membership tests for G1, G2 and GT
|
||||||
|
# on BLS pairing-friendly curves
|
||||||
|
# P is in the G1 subgroup iff a^p == a^(6u²)
|
||||||
|
var t0{.noInit.}, t1{.noInit.}: Fp12[BN254_Nogami]
|
||||||
|
t0.pow_u(a) # a^p
|
||||||
|
t1.pow_u(t0) # a^(p²)
|
||||||
|
t0.square(t1) # a^(2p²)
|
||||||
|
t0 *= t1 # a^(3p²)
|
||||||
|
t0.square() # a^(6p²)
|
||||||
|
|
||||||
|
t1.frobenius_map(a)
|
||||||
|
|
||||||
|
return t0 == t1
|
|
@ -0,0 +1,153 @@
|
||||||
|
# Constantine
|
||||||
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||||
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||||
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import
|
||||||
|
# Internals
|
||||||
|
../config/[common, curves],
|
||||||
|
../arithmetic,
|
||||||
|
../primitives,
|
||||||
|
../towers,
|
||||||
|
../ec_shortweierstrass,
|
||||||
|
../io/io_bigints,
|
||||||
|
../isogeny/frobenius
|
||||||
|
|
||||||
|
func pow_BN254_Nogami_abs_u*[ECP: ECP_ShortW[Fp[BN254_Nogami], G1] or
|
||||||
|
ECP_ShortW[Fp2[BN254_Nogami], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) =
|
||||||
|
## [u]P with u the curve parameter
|
||||||
|
## For BN254_Nogami [0x4080000000000001]P
|
||||||
|
r.double(P)
|
||||||
|
r.double_repeated(6)
|
||||||
|
r += P
|
||||||
|
r.double_repeated(55)
|
||||||
|
r += P
|
||||||
|
|
||||||
|
func pow_BN254_Nogami_u[ECP: ECP_ShortW[Fp[BN254_Nogami], G1] or
|
||||||
|
ECP_ShortW[Fp2[BN254_Nogami], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) {.inline.}=
|
||||||
|
## Does the scalar multiplication [u]P
|
||||||
|
## with u the BN curve parameter
|
||||||
|
pow_BN254_Nogami_abs_u(r, P)
|
||||||
|
r.neg()
|
||||||
|
|
||||||
|
func pow_BN254_Nogami_minus_u[ECP: ECP_ShortW[Fp[BN254_Nogami], G1] or
|
||||||
|
ECP_ShortW[Fp2[BN254_Nogami], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) {.inline.}=
|
||||||
|
## Does the scalar multiplication [-u]P
|
||||||
|
## with u the BN curve parameter
|
||||||
|
pow_BN254_Nogami_abs_u(r, P)
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Clear Cofactor - Naive
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
const Cofactor_Eff_BN254_Nogami_G1 = BigInt[1].fromHex"0x1"
|
||||||
|
const Cofactor_Eff_BN254_Nogami_G2 = BigInt[444].fromHex"0xab11da940a5bd10e25327cb22360008556b23c24080002d6845e3404000009a4f95b60000000145460100000000018544800000000000c8"
|
||||||
|
# r = 36x⁴ + 36x³ + 18x² + 6x + 1
|
||||||
|
# G2.order() = (36x⁴ + 36x³ + 18x² + 6x + 1)(36x⁴ + 36x³ + 30x² + 6x + 1)
|
||||||
|
# = r * cofactor
|
||||||
|
# Effective cofactor from Fuentes-Casteneda et al
|
||||||
|
# −(18x³ + 12x² + 3x + 1)*cofactor
|
||||||
|
|
||||||
|
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BN254_Nogami], G1]) {.inline.} =
|
||||||
|
## Clear the cofactor of BN254_Nogami G1
|
||||||
|
## BN curves have a G1 cofactor of 1 so this is a no-op
|
||||||
|
discard
|
||||||
|
|
||||||
|
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp2[BN254_Nogami], G2]) {.inline.} =
|
||||||
|
## Clear the cofactor of BN254_Nogami G2
|
||||||
|
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
||||||
|
P.scalarMulGeneric(Cofactor_Eff_BN254_Nogami_G2)
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Clear Cofactor - Naive
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
# BN G1
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp[BN254_Nogami], G1]) {.inline.} =
|
||||||
|
## Clear the cofactor of BN254_Nogami G1
|
||||||
|
## BN curves have a prime order r hence all points on curve are in G1
|
||||||
|
## Hence this is a no-op
|
||||||
|
discard
|
||||||
|
|
||||||
|
# BN G2
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Implementation
|
||||||
|
# Fuentes-Castaneda et al, "Fast Hashing to G2 on Pairing-Friendly Curves", https://doi.org/10.1007/978-3-642-28496-0_25*
|
||||||
|
|
||||||
|
func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp2[BN254_Nogami], G2]) {.inline.} =
|
||||||
|
## Clear the cofactor of BN254_Nogami G2
|
||||||
|
## Optimized using endomorphisms
|
||||||
|
## P' → [x]P + [3x]ψ(P) + [x]ψ²(P) + ψ³(P)
|
||||||
|
var xP{.noInit.}, t{.noInit.}: typeof(P)
|
||||||
|
|
||||||
|
xP.pow_BN254_Nogami_u(P) # xP = [x]P
|
||||||
|
t.frobenius_psi(P, 3) # t = ψ³(P)
|
||||||
|
P.double(xP)
|
||||||
|
P += xP
|
||||||
|
P.frobenius_psi(P) # P = [3x]ψ(P)
|
||||||
|
P += t # P = [3x]ψ(P) + ψ³(P)
|
||||||
|
t.frobenius_psi(xP, 2) # t = [x]ψ²(P)
|
||||||
|
P += xP # P = [x]P + [3x]ψ(P) + ψ³(P)
|
||||||
|
P += t # P = [x]P + [3x]ψ(P) + [x]ψ²(P) + ψ³(P)
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Subgroup checks
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
func isInSubgroup*(P: ECP_ShortW_Prj[Fp[BN254_Nogami], G1]): SecretBool {.inline.} =
|
||||||
|
## Returns true if P is in G1 subgroup, i.e. P is a point of order r.
|
||||||
|
## A point may be on a curve but not on the prime order r subgroup.
|
||||||
|
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||||
|
## This is a no-op as on G1, all points are in the correct subgroup.
|
||||||
|
##
|
||||||
|
## Warning ⚠: Assumes that P is on curve
|
||||||
|
return CtTrue
|
||||||
|
|
||||||
|
func isInSubgroup*(P: ECP_ShortW_Prj[Fp2[BN254_Nogami], G2]): SecretBool =
|
||||||
|
## Returns true if P is in G2 subgroup, i.e. P is a point of order r.
|
||||||
|
## A point may be on a curve but not on the prime order r subgroup.
|
||||||
|
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||||
|
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||||
|
# A note on group membership tests for G1, G2 and GT
|
||||||
|
# on BLS pairing-friendly curves
|
||||||
|
#
|
||||||
|
# The condition to apply the optimized endomorphism check on G₂
|
||||||
|
# is gcd(h₁, h₂) == 1 with h₁ and h₂ the cofactors on G₁ and G₂.
|
||||||
|
# In that case [p]Q == [t-1]Q as r = p+1-t and [r]Q = 0
|
||||||
|
# For BN curves h₁ = 1, hence Scott group membership tests can be used for BN curves
|
||||||
|
#
|
||||||
|
# p the prime modulus: 36u⁴ + 36u³ + 24u² + 6u + 1
|
||||||
|
# r the prime order: 36u⁴ + 36u³ + 18u² + 6u + 1
|
||||||
|
# t the trace: 6u² + 1
|
||||||
|
var t0{.noInit.}, t1{.noInit.}: ECP_ShortW_Prj[Fp2[BN254_Nogami], G2]
|
||||||
|
|
||||||
|
t0.pow_BN254_Nogami_u(P) # [u]P
|
||||||
|
t1.pow_BN254_Nogami_u(t0) # [u²]P
|
||||||
|
t0.double(t1) # [2u²]P
|
||||||
|
t0 += t1 # [3u²]P
|
||||||
|
t0.double() # [6u²]P
|
||||||
|
|
||||||
|
t1.frobenius_psi(P) # ψ(P)
|
||||||
|
|
||||||
|
return t0 == t1
|
|
@ -7,10 +7,12 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../config/[curves, type_bigint],
|
../config/[common, curves, type_bigint, type_ff],
|
||||||
../io/io_bigints,
|
../io/io_bigints,
|
||||||
../towers,
|
../towers,
|
||||||
../pairing/cyclotomic_fp12
|
../elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
|
||||||
|
../pairing/[cyclotomic_fp12, miller_loops],
|
||||||
|
../isogeny/frobenius
|
||||||
|
|
||||||
# Slow generic implementation
|
# Slow generic implementation
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
@ -121,3 +123,21 @@ func pow_u*(r: var Fp12[BN254_Snarks], a: Fp12[BN254_Snarks], invert = BN254_Sna
|
||||||
|
|
||||||
if invert:
|
if invert:
|
||||||
r.cyclotomic_inv()
|
r.cyclotomic_inv()
|
||||||
|
|
||||||
|
func isInPairingSubgroup*(a: Fp12[BN254_Snarks]): SecretBool =
|
||||||
|
## Returns true if a is in GT subgroup, i.e. a is an element of order r
|
||||||
|
## Warning ⚠: Assumes that a is in the cyclotomic subgroup
|
||||||
|
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||||
|
# A note on group membership tests for G1, G2 and GT
|
||||||
|
# on BLS pairing-friendly curves
|
||||||
|
# P is in the G1 subgroup iff a^p == a^(6u²)
|
||||||
|
var t0{.noInit.}, t1{.noInit.}: Fp12[BN254_Snarks]
|
||||||
|
t0.pow_u(a) # a^p
|
||||||
|
t1.pow_u(t0) # a^(p²)
|
||||||
|
t0.square(t1) # a^(2p²)
|
||||||
|
t0 *= t1 # a^(3p²)
|
||||||
|
t0.square() # a^(6p²)
|
||||||
|
|
||||||
|
t1.frobenius_map(a)
|
||||||
|
|
||||||
|
return t0 == t1
|
|
@ -0,0 +1,218 @@
|
||||||
|
# Constantine
|
||||||
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||||
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||||
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import
|
||||||
|
# Internals
|
||||||
|
../config/[common, curves],
|
||||||
|
../arithmetic,
|
||||||
|
../primitives,
|
||||||
|
../towers,
|
||||||
|
../ec_shortweierstrass,
|
||||||
|
../io/io_bigints,
|
||||||
|
../isogeny/frobenius
|
||||||
|
|
||||||
|
func pow_bn254_snarks_abs_u*[ECP: ECP_ShortW[Fp[BN254_Snarks], G1] or
|
||||||
|
ECP_ShortW[Fp2[BN254_Snarks], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) =
|
||||||
|
## [u]P with u the curve parameter
|
||||||
|
## For BN254_Snarks [0x44e992b44a6909f1]P
|
||||||
|
|
||||||
|
var # Hopefully the compiler optimizes away unused ECP as those are large
|
||||||
|
x10 {.noInit.}: ECP
|
||||||
|
x11 {.noInit.}: ECP
|
||||||
|
x100 {.noInit.}: ECP
|
||||||
|
x110 {.noInit.}: ECP
|
||||||
|
x1100 {.noInit.}: ECP
|
||||||
|
x1111 {.noInit.}: ECP
|
||||||
|
x10010 {.noInit.}: ECP
|
||||||
|
x10110 {.noInit.}: ECP
|
||||||
|
x11100 {.noInit.}: ECP
|
||||||
|
x101110 {.noInit.}: ECP
|
||||||
|
x1001010 {.noInit.}: ECP
|
||||||
|
x1111000 {.noInit.}: ECP
|
||||||
|
x10001110 {.noInit.}: ECP
|
||||||
|
|
||||||
|
x10 .double(P)
|
||||||
|
x11 .sum(x10, P)
|
||||||
|
x100 .sum(x11, P)
|
||||||
|
x110 .sum(x10, x100)
|
||||||
|
x1100 .double(x110)
|
||||||
|
x1111 .sum(x11, x1100)
|
||||||
|
x10010 .sum(x11, x1111)
|
||||||
|
x10110 .sum(x100, x10010)
|
||||||
|
x11100 .sum(x110, x10110)
|
||||||
|
x101110 .sum(x10010, x11100)
|
||||||
|
x1001010 .sum(x11100, x101110)
|
||||||
|
x1111000 .sum(x101110, x1001010)
|
||||||
|
x10001110 .sum(x10110, x1111000)
|
||||||
|
|
||||||
|
var
|
||||||
|
r15 {.noInit.}: ECP
|
||||||
|
r16 {.noInit.}: ECP
|
||||||
|
r17 {.noInit.}: ECP
|
||||||
|
r18 {.noInit.}: ECP
|
||||||
|
r20 {.noInit.}: ECP
|
||||||
|
r21 {.noInit.}: ECP
|
||||||
|
r22 {.noInit.}: ECP
|
||||||
|
r26 {.noInit.}: ECP
|
||||||
|
r27 {.noInit.}: ECP
|
||||||
|
r61 {.noInit.}: ECP
|
||||||
|
|
||||||
|
r15.double(x10001110)
|
||||||
|
r15 += x1001010
|
||||||
|
r16.sum(x10001110, r15)
|
||||||
|
r17.sum(x1111, r16)
|
||||||
|
r18.sum(r16, r17)
|
||||||
|
|
||||||
|
r20.double(r18)
|
||||||
|
r20 += r17
|
||||||
|
r21.sum(x1111000, r20)
|
||||||
|
r22.sum(r15, r21)
|
||||||
|
|
||||||
|
r26.double(r22)
|
||||||
|
r26.double()
|
||||||
|
r26 += r22
|
||||||
|
r26 += r18
|
||||||
|
|
||||||
|
r27.sum(r22, r26)
|
||||||
|
|
||||||
|
r61.sum(r26, r27)
|
||||||
|
r61.double_repeated(17)
|
||||||
|
r61 += r27
|
||||||
|
r61.double_repeated(14)
|
||||||
|
r61 += r21
|
||||||
|
|
||||||
|
r = r61
|
||||||
|
r.double_repeated(16)
|
||||||
|
r += r20
|
||||||
|
|
||||||
|
func pow_bn254_snarks_u[ECP: ECP_ShortW[Fp[BN254_Snarks], G1] or
|
||||||
|
ECP_ShortW[Fp2[BN254_Snarks], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) {.inline.}=
|
||||||
|
## Does the scalar multiplication [u]P
|
||||||
|
## with u the BN curve parameter
|
||||||
|
pow_bn254_snarks_abs_u(r, P)
|
||||||
|
|
||||||
|
func pow_bn254_snarks_minus_u[ECP: ECP_ShortW[Fp[BN254_Snarks], G1] or
|
||||||
|
ECP_ShortW[Fp2[BN254_Snarks], G2]](
|
||||||
|
r{.noalias.}: var ECP,
|
||||||
|
P{.noalias.}: ECP
|
||||||
|
) {.inline.}=
|
||||||
|
## Does the scalar multiplication [-u]P
|
||||||
|
## with the BN curve parameter
|
||||||
|
pow_bn254_snarks_abs_u(r, P)
|
||||||
|
r.neg()
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Clear Cofactor - Naive
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
const Cofactor_Eff_BN254_Snarks_G1 = BigInt[1].fromHex"0x1"
|
||||||
|
const Cofactor_Eff_BN254_Snarks_G2 = BigInt[445].fromHex"0x10fdac342d9d118eaade453b741519b8e1d63b3400132e99468a9c2b25de5b5f1bf35b43bcc5da2335a0d8a112d43476616edcfabef338ea"
|
||||||
|
# r = 36x⁴ + 36x³ + 18x² + 6x + 1
|
||||||
|
# G2.order() = (36x⁴ + 36x³ + 18x² + 6x + 1)(36x⁴ + 36x³ + 30x² + 6x + 1)
|
||||||
|
# = r * cofactor
|
||||||
|
# Effective cofactor from Fuentes-Casteneda et al
|
||||||
|
# -(18x³ + 12x² + 3x + 1)*cofactor
|
||||||
|
|
||||||
|
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BN254_Snarks], G1]) {.inline.} =
|
||||||
|
## Clear the cofactor of BN254_Snarks G1
|
||||||
|
## BN curves have a G1 cofactor of 1 so this is a no-op
|
||||||
|
discard
|
||||||
|
|
||||||
|
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp2[BN254_Snarks], G2]) {.inline.} =
|
||||||
|
## Clear the cofactor of BN254_Snarks G2
|
||||||
|
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
||||||
|
P.scalarMulGeneric(Cofactor_Eff_BN254_Snarks_G2)
|
||||||
|
P.neg()
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Clear Cofactor - Naive
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
# BN G1
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp[BN254_Snarks], G1]) {.inline.} =
|
||||||
|
## Clear the cofactor of BN254_Snarks G1
|
||||||
|
## BN curves have a prime order r hence all points on curve are in G1
|
||||||
|
## Hence this is a no-op
|
||||||
|
discard
|
||||||
|
|
||||||
|
# BN G2
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Implementation
|
||||||
|
# Fuentes-Castaneda et al, "Fast Hashing to G2 on Pairing-Friendly Curves", https://doi.org/10.1007/978-3-642-28496-0_25*
|
||||||
|
|
||||||
|
func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp2[BN254_Snarks], G2]) {.inline.} =
|
||||||
|
## Clear the cofactor of BN254_Snarks G2
|
||||||
|
## Optimized using endomorphisms
|
||||||
|
## P' → [x]P + [3x]ψ(P) + [x]ψ²(P) + ψ³(P)
|
||||||
|
var xP{.noInit.}, t{.noInit.}: typeof(P)
|
||||||
|
|
||||||
|
xP.pow_bn254_snarks_u(P) # xP = [x]P
|
||||||
|
t.frobenius_psi(P, 3) # t = ψ³(P)
|
||||||
|
P.double(xP)
|
||||||
|
P += xP
|
||||||
|
P.frobenius_psi(P) # P = [3x]ψ(P)
|
||||||
|
P += t # P = [3x]ψ(P) + ψ³(P)
|
||||||
|
t.frobenius_psi(xP, 2) # t = [x]ψ²(P)
|
||||||
|
P += xP # P = [x]P + [3x]ψ(P) + ψ³(P)
|
||||||
|
P += t # P = [x]P + [3x]ψ(P) + [x]ψ²(P) + ψ³(P)
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Subgroup checks
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
func isInSubgroup*(P: ECP_ShortW_Prj[Fp[BN254_Snarks], G1]): SecretBool {.inline.} =
|
||||||
|
## Returns true if P is in G1 subgroup, i.e. P is a point of order r.
|
||||||
|
## A point may be on a curve but not on the prime order r subgroup.
|
||||||
|
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||||
|
## This is a no-op as on G1, all points are in the correct subgroup.
|
||||||
|
##
|
||||||
|
## Warning ⚠: Assumes that P is on curve
|
||||||
|
return CtTrue
|
||||||
|
|
||||||
|
func isInSubgroup*(P: ECP_ShortW_Prj[Fp2[BN254_Snarks], G2]): SecretBool =
|
||||||
|
## Returns true if P is in G2 subgroup, i.e. P is a point of order r.
|
||||||
|
## A point may be on a curve but not on the prime order r subgroup.
|
||||||
|
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||||
|
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||||
|
# A note on group membership tests for G1, G2 and GT
|
||||||
|
# on BLS pairing-friendly curves
|
||||||
|
#
|
||||||
|
# The condition to apply the optimized endomorphism check on G₂
|
||||||
|
# is gcd(h₁, h₂) == 1 with h₁ and h₂ the cofactors on G₁ and G₂.
|
||||||
|
# In that case [p]Q == [t-1]Q as r = p+1-t and [r]Q = 0
|
||||||
|
# For BN curves h₁ = 1, hence Scott group membership tests can be used for BN curves
|
||||||
|
#
|
||||||
|
# p the prime modulus: 36u⁴ + 36u³ + 24u² + 6u + 1
|
||||||
|
# r the prime order: 36u⁴ + 36u³ + 18u² + 6u + 1
|
||||||
|
# t the trace: 6u² + 1
|
||||||
|
var t0{.noInit.}, t1{.noInit.}: ECP_ShortW_Prj[Fp2[BN254_Snarks], G2]
|
||||||
|
|
||||||
|
t0.pow_bn254_snarks_u(P) # [u]P
|
||||||
|
t1.pow_bn254_snarks_u(t0) # [u²]P
|
||||||
|
t0.double(t1) # [2u²]P
|
||||||
|
t0 += t1 # [3u²]P
|
||||||
|
t0.double() # [6u²]P
|
||||||
|
|
||||||
|
t1.frobenius_psi(P) # ψ(P)
|
||||||
|
|
||||||
|
return t0 == t1
|
|
@ -0,0 +1,40 @@
|
||||||
|
# Constantine
|
||||||
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||||
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||||
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import
|
||||||
|
# Internals
|
||||||
|
../config/[common, curves],
|
||||||
|
../arithmetic,
|
||||||
|
../primitives,
|
||||||
|
../towers,
|
||||||
|
../ec_shortweierstrass,
|
||||||
|
../io/io_bigints,
|
||||||
|
../isogeny/frobenius
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Clear Cofactor - Naive
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
# TODO https://eprint.iacr.org/2020/351.pdf p12
|
||||||
|
const Cofactor_Eff_BW6_761_G1 = BigInt[384].fromHex"0xad1972339049ce762c77d5ac34cb12efc856a0853c9db94cc61c554757551c0c832ba4061000003b3de580000000007c"
|
||||||
|
## P -> 103([u³]P)− 83([u²]P)−40([u]P)+136P + φ(7([u²]P)+89([u]P)+130P)
|
||||||
|
|
||||||
|
# TODO https://eprint.iacr.org/2020/351.pdf p13
|
||||||
|
const Cofactor_Eff_BW6_761_G2 = BigInt[384].fromHex"0xad1972339049ce762c77d5ac34cb12efc856a0853c9db94cc61c554757551c0c832ba4061000003b3de580000000007c"
|
||||||
|
## P -> (103([u³]P) − 83([u²]P) − 143([u]P) + 27P) + ψ(7([u²]P) − 117([u]P) − 109P)
|
||||||
|
|
||||||
|
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BW6_761], G1]) {.inline.} =
|
||||||
|
## Clear the cofactor of BW6_761 G1
|
||||||
|
P.scalarMulGeneric(Cofactor_Eff_BW6_761_G1)
|
||||||
|
|
||||||
|
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BW6_761], G2]) {.inline.} =
|
||||||
|
## Clear the cofactor of BW6_761 G2
|
||||||
|
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
||||||
|
P.scalarMulGeneric(Cofactor_Eff_BW6_761_G2)
|
|
@ -21,4 +21,4 @@ macro pairing*(C: static Curve, value: untyped): untyped =
|
||||||
## Get pairing related constants
|
## Get pairing related constants
|
||||||
return bindSym($C & "_pairing_" & $value)
|
return bindSym($C & "_pairing_" & $value)
|
||||||
|
|
||||||
export pow_x, pow_xdiv2, pow_u, millerLoopAddchain
|
export pow_x, pow_xdiv2, pow_u, millerLoopAddchain, isInPairingSubgroup
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Constantine
|
||||||
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||||
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||||
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import
|
||||||
|
# Internals
|
||||||
|
../config/curves,
|
||||||
|
./bls12_377_subgroups,
|
||||||
|
./bls12_381_subgroups,
|
||||||
|
./bn254_nogami_subgroups,
|
||||||
|
./bn254_snarks_subgroups,
|
||||||
|
./bw6_761_subgroups
|
||||||
|
|
||||||
|
export
|
||||||
|
bls12_377_subgroups,
|
||||||
|
bls12_381_subgroups,
|
||||||
|
bn254_nogami_subgroups,
|
||||||
|
bn254_snarks_subgroups,
|
||||||
|
bw6_761_subgroups
|
||||||
|
|
||||||
|
func clearCofactor*[ECP](P: var ECP) {.inline.} =
|
||||||
|
## Clear the cofactor of a point on the curve
|
||||||
|
## From a point on the curve, returns a point on the subgroup of order r
|
||||||
|
when ECP.F.C in {BLS12_381}:
|
||||||
|
P.clearCofactorFast()
|
||||||
|
else:
|
||||||
|
P.clearCofactorReference()
|
|
@ -22,6 +22,8 @@ import
|
||||||
|
|
||||||
export ec_shortweierstrass_affine, ec_shortweierstrass_jacobian, ec_shortweierstrass_projective, ec_scalar_mul
|
export ec_shortweierstrass_affine, ec_shortweierstrass_jacobian, ec_shortweierstrass_projective, ec_scalar_mul
|
||||||
|
|
||||||
|
type ECP_ShortW*[F; G: static Subgroup] = ECP_ShortW_Aff[F, G] | ECP_ShortW_Jac[F, G] | ECP_ShortW_Prj[F, G]
|
||||||
|
|
||||||
func projectiveFromJacobian*[F; G](
|
func projectiveFromJacobian*[F; G](
|
||||||
prj: var ECP_ShortW_Prj[F, G],
|
prj: var ECP_ShortW_Prj[F, G],
|
||||||
jac: ECP_ShortW_Jac[F, G]) {.inline.} =
|
jac: ECP_ShortW_Jac[F, G]) {.inline.} =
|
||||||
|
@ -30,3 +32,7 @@ func projectiveFromJacobian*[F; G](
|
||||||
prj.z.square(jac.z)
|
prj.z.square(jac.z)
|
||||||
prj.z *= jac.z
|
prj.z *= jac.z
|
||||||
|
|
||||||
|
func double_repeated*(P: var ECP_ShortW, num: int) {.inline.} =
|
||||||
|
## Repeated doublings
|
||||||
|
for _ in 0 ..< num:
|
||||||
|
P.double()
|
||||||
|
|
|
@ -10,11 +10,10 @@ import
|
||||||
# Internals
|
# Internals
|
||||||
../config/[common, curves],
|
../config/[common, curves],
|
||||||
../primitives, ../arithmetic, ../towers,
|
../primitives, ../arithmetic, ../towers,
|
||||||
../curves/zoo_hash_to_curve,
|
../curves/[zoo_hash_to_curve, zoo_subgroups],
|
||||||
../ec_shortweierstrass,
|
../ec_shortweierstrass,
|
||||||
./h2c_hash_to_field,
|
./h2c_hash_to_field,
|
||||||
./h2c_map_to_isocurve_swu,
|
./h2c_map_to_isocurve_swu,
|
||||||
./cofactors,
|
|
||||||
../isogeny/h2c_isogeny_maps,
|
../isogeny/h2c_isogeny_maps,
|
||||||
../hashes
|
../hashes
|
||||||
|
|
||||||
|
@ -166,4 +165,4 @@ func hashToCurve*[
|
||||||
Pjac.mapToCurve_fusedAdd(u[0], u[1])
|
Pjac.mapToCurve_fusedAdd(u[0], u[1])
|
||||||
output.projectiveFromJacobian(Pjac)
|
output.projectiveFromJacobian(Pjac)
|
||||||
|
|
||||||
output.clearCofactorFast()
|
output.clearCofactor()
|
||||||
|
|
|
@ -220,3 +220,14 @@ func cyclotomic_exp*[C](r: var Fp12[C], a: Fp12[C], exponent: BigInt, invert: bo
|
||||||
r *= a
|
r *= a
|
||||||
if invert:
|
if invert:
|
||||||
r.cyclotomic_inv()
|
r.cyclotomic_inv()
|
||||||
|
|
||||||
|
func isInCyclotomicSubgroup*[C](a: Fp12[C]): SecretBool =
|
||||||
|
## Check if a ∈ Fpⁿ: a^Φₙ(p) = 1
|
||||||
|
## Φ₁₂(p) = p⁴-p²+1
|
||||||
|
var t{.noInit.}, p2{.noInit.}: Fp12[C]
|
||||||
|
|
||||||
|
p2.frobenius_map(a, 2) # a^(p²)
|
||||||
|
t.frobenius_map(p2, 2) # a^(p⁴)
|
||||||
|
t *= a # a^(p⁴+1)
|
||||||
|
|
||||||
|
return t == p2
|
|
@ -12,6 +12,7 @@ import
|
||||||
../arithmetic/limbs_montgomery,
|
../arithmetic/limbs_montgomery,
|
||||||
../ec_shortweierstrass,
|
../ec_shortweierstrass,
|
||||||
../pairing/[pairing_bn, miller_loops, cyclotomic_fp12],
|
../pairing/[pairing_bn, miller_loops, cyclotomic_fp12],
|
||||||
|
../curves/zoo_subgroups,
|
||||||
../io/[io_bigints, io_fields]
|
../io/[io_bigints, io_fields]
|
||||||
|
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
@ -219,27 +220,9 @@ func subgroupCheck(P: ECP_ShortW_Aff[Fp2[BN254_Snarks], G2]): bool =
|
||||||
## A point may be on a curve but in case the curve has a cofactor != 1
|
## A point may be on a curve but in case the curve has a cofactor != 1
|
||||||
## that point may not be in the correct cyclic subgroup.
|
## that point may not be in the correct cyclic subgroup.
|
||||||
## If we are on the subgroup of order r then [r]P = 0
|
## If we are on the subgroup of order r then [r]P = 0
|
||||||
|
|
||||||
# TODO: Generic for any curve
|
|
||||||
|
|
||||||
var Q{.noInit.}: ECP_ShortW_Prj[Fp2[BN254_Snarks], G2]
|
var Q{.noInit.}: ECP_ShortW_Prj[Fp2[BN254_Snarks], G2]
|
||||||
|
|
||||||
# TODO: precompute up to the endomorphism decomposition
|
|
||||||
# or implement fixed base scalar mul
|
|
||||||
# as subgroup checks are a deserialization bottleneck
|
|
||||||
var rm1 = Fr[BN254_Snarks].fieldMod()
|
|
||||||
rm1 -= One
|
|
||||||
|
|
||||||
# We can't use endomorphism acceleration when multiplying
|
|
||||||
# by the curve order r to check [r]P == 0
|
|
||||||
# as it requires the scalar to be < r.
|
|
||||||
# But we can use it to multiply by [r-1].
|
|
||||||
Q.projectiveFromAffine(P)
|
Q.projectiveFromAffine(P)
|
||||||
let Q0 = Q
|
return bool(Q.isInSubgroup())
|
||||||
Q.scalarMul(rm1)
|
|
||||||
Q += Q0
|
|
||||||
|
|
||||||
return bool(Q.isInf())
|
|
||||||
|
|
||||||
func fromRawCoords(
|
func fromRawCoords(
|
||||||
dst: var ECP_ShortW_Aff[Fp[BN254_Snarks], G1],
|
dst: var ECP_ShortW_Aff[Fp[BN254_Snarks], G1],
|
||||||
|
|
|
@ -67,12 +67,12 @@ The optimizations can be of algebraic, algorithmic or "implementation details" n
|
||||||
- [x] FIPS (Finely Integrated Operand Scanning)
|
- [x] FIPS (Finely Integrated Operand Scanning)
|
||||||
|
|
||||||
- Montgomery Squaring
|
- Montgomery Squaring
|
||||||
- [ ] Dedicated squaring functions
|
- [x] Dedicated squaring functions
|
||||||
- [ ] Fused multiply + reduce
|
- [x] Fused multiply + reduce
|
||||||
- [ ] int128
|
- [ ] int128
|
||||||
- [ ] loop unrolling
|
- [ ] loop unrolling
|
||||||
- [ ] x86: Full Assembly implementation
|
- [x] x86: Full Assembly implementation
|
||||||
- [ ] x86: MULX, ADCX, ADOX instructions
|
- [x] x86: MULX, ADCX, ADOX instructions
|
||||||
- [ ] no-carry optimization for CIOS (Coarsely Integrated Operand Scanning)
|
- [ ] no-carry optimization for CIOS (Coarsely Integrated Operand Scanning)
|
||||||
|
|
||||||
- Addition chains
|
- Addition chains
|
||||||
|
@ -97,7 +97,7 @@ The optimizations can be of algebraic, algorithmic or "implementation details" n
|
||||||
|
|
||||||
- Square Root (constant-time)
|
- Square Root (constant-time)
|
||||||
- [x] baseline sqrt via Little-Fermat for `p ≡ 3 (mod 4)`
|
- [x] baseline sqrt via Little-Fermat for `p ≡ 3 (mod 4)`
|
||||||
- [ ] baseline sqrt via Little-Fermat for `p ≡ 5 (mod 8)`
|
- [x] baseline sqrt via Little-Fermat for `p ≡ 5 (mod 8)`
|
||||||
- [ ] baseline sqrt via Little-Fermat for `p ≡ 9 (mod 16)`
|
- [ ] baseline sqrt via Little-Fermat for `p ≡ 9 (mod 16)`
|
||||||
- [x] baseline sqrt via Tonelli-Shanks for any prime.
|
- [x] baseline sqrt via Tonelli-Shanks for any prime.
|
||||||
- [x] sqrt via addition-chain
|
- [x] sqrt via addition-chain
|
||||||
|
@ -211,3 +211,5 @@ The optimizations can be of algebraic, algorithmic or "implementation details" n
|
||||||
- Subgroup check
|
- Subgroup check
|
||||||
- [ ] BLS G1: Bowe, endomorphism accelerated
|
- [ ] BLS G1: Bowe, endomorphism accelerated
|
||||||
- [ ] BLS G2: Bowe, endomorphism accelerated
|
- [ ] BLS G2: Bowe, endomorphism accelerated
|
||||||
|
- [x] BLS G1: Scott, endomorphism accelerated
|
||||||
|
- [x] BLS G2: Scott, endomorphism accelerated
|
|
@ -30,7 +30,7 @@ echo "bench xoshiro512** seed: ", seed
|
||||||
|
|
||||||
func random_point*(rng: var RngState, EC: typedesc): EC {.noInit.} =
|
func random_point*(rng: var RngState, EC: typedesc): EC {.noInit.} =
|
||||||
result = rng.random_unsafe(EC)
|
result = rng.random_unsafe(EC)
|
||||||
result.clearCofactorReference()
|
result.clearCofactor()
|
||||||
|
|
||||||
proc pairingBLS12Meter*(C: static Curve) =
|
proc pairingBLS12Meter*(C: static Curve) =
|
||||||
let
|
let
|
||||||
|
|
|
@ -12,7 +12,7 @@ import
|
||||||
../constantine/config/[common, curves],
|
../constantine/config/[common, curves],
|
||||||
../constantine/[arithmetic, towers],
|
../constantine/[arithmetic, towers],
|
||||||
../constantine/elliptic/ec_shortweierstrass_projective,
|
../constantine/elliptic/ec_shortweierstrass_projective,
|
||||||
../constantine/hash_to_curve/cofactors,
|
../constantine/curves/zoo_subgroups,
|
||||||
../constantine/pairing/pairing_bls12,
|
../constantine/pairing/pairing_bls12,
|
||||||
# Helpers
|
# Helpers
|
||||||
../helpers/prng_unsafe
|
../helpers/prng_unsafe
|
||||||
|
@ -24,7 +24,7 @@ echo "bench xoshiro512** seed: ", seed
|
||||||
|
|
||||||
func random_point*(rng: var RngState, EC: typedesc): EC {.noInit.} =
|
func random_point*(rng: var RngState, EC: typedesc): EC {.noInit.} =
|
||||||
result = rng.random_unsafe(EC)
|
result = rng.random_unsafe(EC)
|
||||||
result.clearCofactorReference()
|
result.clearCofactor()
|
||||||
|
|
||||||
proc pairingBLS12Meter*(C: static Curve) =
|
proc pairingBLS12Meter*(C: static Curve) =
|
||||||
let
|
let
|
||||||
|
|
|
@ -33,14 +33,14 @@ import
|
||||||
|
|
||||||
func millerLoopBW6_761_naive[C](
|
func millerLoopBW6_761_naive[C](
|
||||||
f: var Fp6[C],
|
f: var Fp6[C],
|
||||||
P: ECP_ShortW_Aff[Fp[C], NotOnTwist],
|
P: ECP_ShortW_Aff[Fp[C], G1],
|
||||||
Q: ECP_ShortW_Aff[Fp[C], OnTwist]
|
Q: ECP_ShortW_Aff[Fp[C], G2]
|
||||||
) =
|
) =
|
||||||
## Miller Loop for BW6_761 curve
|
## Miller Loop for BW6_761 curve
|
||||||
## Computes f_{u+1,Q}(P)*Frobenius(f_{u*(u^2-u-1),Q}(P))
|
## Computes f_{u+1,Q}(P)*Frobenius(f_{u*(u^2-u-1),Q}(P))
|
||||||
|
|
||||||
var
|
var
|
||||||
T {.noInit.}: ECP_ShortW_Prj[Fp[C], OnTwist]
|
T {.noInit.}: ECP_ShortW_Prj[Fp[C], G2]
|
||||||
line {.noInit.}: Line[Fp[C]]
|
line {.noInit.}: Line[Fp[C]]
|
||||||
nQ{.noInit.}: typeof(Q)
|
nQ{.noInit.}: typeof(Q)
|
||||||
|
|
||||||
|
@ -76,15 +76,15 @@ func finalExpGeneric[C: static Curve](f: var Fp6[C]) =
|
||||||
|
|
||||||
func millerLoopBW6_761_opt_to_debug[C](
|
func millerLoopBW6_761_opt_to_debug[C](
|
||||||
f: var Fp6[C],
|
f: var Fp6[C],
|
||||||
P: ECP_ShortW_Aff[Fp[C], NotOnTwist],
|
P: ECP_ShortW_Aff[Fp[C], G1],
|
||||||
Q: ECP_ShortW_Aff[Fp[C], OnTwist]
|
Q: ECP_ShortW_Aff[Fp[C], G2]
|
||||||
) {.used.} =
|
) {.used.} =
|
||||||
## Miller Loop Otpimized for BW6_761 curve
|
## Miller Loop Otpimized for BW6_761 curve
|
||||||
|
|
||||||
# 1st part: f_{u,Q}(P)
|
# 1st part: f_{u,Q}(P)
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
var
|
var
|
||||||
T {.noInit.}: ECP_ShortW_Prj[Fp[C], OnTwist]
|
T {.noInit.}: ECP_ShortW_Prj[Fp[C], G2]
|
||||||
line {.noInit.}: Line[Fp[C]]
|
line {.noInit.}: Line[Fp[C]]
|
||||||
|
|
||||||
T.projectiveFromAffine(Q)
|
T.projectiveFromAffine(Q)
|
||||||
|
@ -150,15 +150,15 @@ func millerLoopBW6_761_opt_to_debug[C](
|
||||||
|
|
||||||
func pairing_bw6_761_reference*[C](
|
func pairing_bw6_761_reference*[C](
|
||||||
gt: var Fp6[C],
|
gt: var Fp6[C],
|
||||||
P: ECP_ShortW_Prj[Fp[C], NotOnTwist],
|
P: ECP_ShortW_Prj[Fp[C], G1],
|
||||||
Q: ECP_ShortW_Prj[Fp[C], OnTwist]) =
|
Q: ECP_ShortW_Prj[Fp[C], G2]) =
|
||||||
## Compute the optimal Ate Pairing for BW6 curves
|
## Compute the optimal Ate Pairing for BW6 curves
|
||||||
## Input: P ∈ G1, Q ∈ G2
|
## Input: P ∈ G1, Q ∈ G2
|
||||||
## Output: e(P, Q) ∈ Gt
|
## Output: e(P, Q) ∈ Gt
|
||||||
##
|
##
|
||||||
## Reference implementation
|
## Reference implementation
|
||||||
var Paff {.noInit.}: ECP_ShortW_Aff[Fp[C], NotOnTwist]
|
var Paff {.noInit.}: ECP_ShortW_Aff[Fp[C], G1]
|
||||||
var Qaff {.noInit.}: ECP_ShortW_Aff[Fp[C], OnTwist]
|
var Qaff {.noInit.}: ECP_ShortW_Aff[Fp[C], G2]
|
||||||
Paff.affineFromProjective(P)
|
Paff.affineFromProjective(P)
|
||||||
Qaff.affineFromProjective(Q)
|
Qaff.affineFromProjective(Q)
|
||||||
gt.millerLoopBW6_761_naive(Paff, Qaff)
|
gt.millerLoopBW6_761_naive(Paff, Qaff)
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Constantine
|
||||||
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||||
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||||
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import
|
||||||
|
# Internals
|
||||||
|
../constantine/config/[type_ff, curves],
|
||||||
|
../constantine/elliptic/ec_shortweierstrass_projective,
|
||||||
|
../constantine/towers,
|
||||||
|
# Test utilities
|
||||||
|
./t_ec_template
|
||||||
|
|
||||||
|
const
|
||||||
|
Iters = 12
|
||||||
|
ItersMul = Iters div 4
|
||||||
|
|
||||||
|
run_EC_subgroups_cofactors_impl(
|
||||||
|
ec = ECP_ShortW_Prj[Fp[BLS12_377], G1],
|
||||||
|
ItersMul = ItersMul,
|
||||||
|
moduleName = "test_ec_subgroups_g1_" & $BLS12_377
|
||||||
|
)
|
||||||
|
|
||||||
|
run_EC_subgroups_cofactors_impl(
|
||||||
|
ec = ECP_ShortW_Prj[Fp2[BLS12_377], G2],
|
||||||
|
ItersMul = ItersMul,
|
||||||
|
moduleName = "test_ec_subgroups_g2_" & $BLS12_377
|
||||||
|
)
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Constantine
|
||||||
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||||
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||||
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import
|
||||||
|
# Internals
|
||||||
|
../constantine/config/[type_ff, curves],
|
||||||
|
../constantine/elliptic/ec_shortweierstrass_projective,
|
||||||
|
../constantine/towers,
|
||||||
|
# Test utilities
|
||||||
|
./t_ec_template
|
||||||
|
|
||||||
|
const
|
||||||
|
Iters = 12
|
||||||
|
ItersMul = Iters div 4
|
||||||
|
|
||||||
|
run_EC_subgroups_cofactors_impl(
|
||||||
|
ec = ECP_ShortW_Prj[Fp[BLS12_381], G1],
|
||||||
|
ItersMul = ItersMul,
|
||||||
|
moduleName = "test_ec_subgroups_g1_" & $BLS12_381
|
||||||
|
)
|
||||||
|
|
||||||
|
run_EC_subgroups_cofactors_impl(
|
||||||
|
ec = ECP_ShortW_Prj[Fp2[BLS12_381], G2],
|
||||||
|
ItersMul = ItersMul,
|
||||||
|
moduleName = "test_ec_subgroups_g2_" & $BLS12_381
|
||||||
|
)
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Constantine
|
||||||
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||||
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||||
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import
|
||||||
|
# Internals
|
||||||
|
../constantine/config/[type_ff, curves],
|
||||||
|
../constantine/elliptic/ec_shortweierstrass_projective,
|
||||||
|
../constantine/towers,
|
||||||
|
# Test utilities
|
||||||
|
./t_ec_template
|
||||||
|
|
||||||
|
const
|
||||||
|
Iters = 12
|
||||||
|
ItersMul = Iters div 4
|
||||||
|
|
||||||
|
run_EC_subgroups_cofactors_impl(
|
||||||
|
ec = ECP_ShortW_Prj[Fp[BN254_Nogami], G1],
|
||||||
|
ItersMul = ItersMul,
|
||||||
|
moduleName = "test_ec_subgroups_g1_" & $BN254_Nogami
|
||||||
|
)
|
||||||
|
|
||||||
|
run_EC_subgroups_cofactors_impl(
|
||||||
|
ec = ECP_ShortW_Prj[Fp2[BN254_Nogami], G2],
|
||||||
|
ItersMul = ItersMul,
|
||||||
|
moduleName = "test_ec_subgroups_g2_" & $BN254_Nogami
|
||||||
|
)
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Constantine
|
||||||
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||||
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||||
|
# Licensed and distributed under either of
|
||||||
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||||
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import
|
||||||
|
# Internals
|
||||||
|
../constantine/config/[type_ff, curves],
|
||||||
|
../constantine/elliptic/ec_shortweierstrass_projective,
|
||||||
|
../constantine/towers,
|
||||||
|
# Test utilities
|
||||||
|
./t_ec_template
|
||||||
|
|
||||||
|
const
|
||||||
|
Iters = 12
|
||||||
|
ItersMul = Iters div 4
|
||||||
|
|
||||||
|
run_EC_subgroups_cofactors_impl(
|
||||||
|
ec = ECP_ShortW_Prj[Fp[BN254_Snarks], G1],
|
||||||
|
ItersMul = ItersMul,
|
||||||
|
moduleName = "test_ec_subgroups_g1_" & $BN254_Snarks
|
||||||
|
)
|
||||||
|
|
||||||
|
run_EC_subgroups_cofactors_impl(
|
||||||
|
ec = ECP_ShortW_Prj[Fp2[BN254_Snarks], G2],
|
||||||
|
ItersMul = ItersMul,
|
||||||
|
moduleName = "test_ec_subgroups_g2_" & $BN254_Snarks
|
||||||
|
)
|
|
@ -26,7 +26,8 @@ import
|
||||||
ec_twistededwards_affine,
|
ec_twistededwards_affine,
|
||||||
ec_twistededwards_projective,
|
ec_twistededwards_projective,
|
||||||
ec_scalar_mul],
|
ec_scalar_mul],
|
||||||
../constantine/io/[io_bigints, io_fields],
|
../constantine/io/[io_bigints, io_fields, io_ec],
|
||||||
|
../constantine/curves/zoo_subgroups,
|
||||||
# Test utilities
|
# Test utilities
|
||||||
../helpers/prng_unsafe,
|
../helpers/prng_unsafe,
|
||||||
./support/ec_reference_scalar_mult
|
./support/ec_reference_scalar_mult
|
||||||
|
@ -458,3 +459,80 @@ proc run_EC_mixed_add_impl*(
|
||||||
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = true, gen = HighHammingWeight)
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = true, gen = HighHammingWeight)
|
||||||
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = false, gen = Long01Sequence)
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = false, gen = Long01Sequence)
|
||||||
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = true, gen = Long01Sequence)
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = true, gen = Long01Sequence)
|
||||||
|
|
||||||
|
proc run_EC_subgroups_cofactors_impl*(
|
||||||
|
ec: typedesc,
|
||||||
|
ItersMul: static int,
|
||||||
|
moduleName: string
|
||||||
|
) =
|
||||||
|
# Random seed for reproducibility
|
||||||
|
var rng: RngState
|
||||||
|
let seed = uint32(getTime().toUnix() and (1'i64 shl 32 - 1)) # unixTime mod 2^32
|
||||||
|
rng.seed(seed)
|
||||||
|
echo "\n------------------------------------------------------\n"
|
||||||
|
echo moduleName, " xoshiro512** seed: ", seed
|
||||||
|
|
||||||
|
when ec.G == G1:
|
||||||
|
const G1_or_G2 = "G1"
|
||||||
|
else:
|
||||||
|
const G1_or_G2 = "G2"
|
||||||
|
|
||||||
|
const testSuiteDesc = "Elliptic curve subgroup check and cofactor clearing"
|
||||||
|
|
||||||
|
suite testSuiteDesc & " - " & $ec & " - [" & $WordBitwidth & "-bit mode]":
|
||||||
|
test "Effective cofactor matches accelerated cofactor clearing" & " - " & $ec & " - [" & $WordBitwidth & "-bit mode]":
|
||||||
|
proc test(EC: typedesc, bits: static int, randZ: bool, gen: RandomGen) =
|
||||||
|
for _ in 0 ..< Iters:
|
||||||
|
let P = rng.random_point(EC, randZ, gen)
|
||||||
|
var cPeff = P
|
||||||
|
var cPfast = P
|
||||||
|
|
||||||
|
cPeff.clearCofactorReference()
|
||||||
|
cPfast.clearCofactorFast()
|
||||||
|
|
||||||
|
check: bool(cPeff == cPfast)
|
||||||
|
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = false, gen = Uniform)
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = true, gen = Uniform)
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = false, gen = HighHammingWeight)
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = true, gen = HighHammingWeight)
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = false, gen = Long01Sequence)
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = true, gen = Long01Sequence)
|
||||||
|
|
||||||
|
test "Subgroup checks and cofactor clearing consistency":
|
||||||
|
var inSubgroup = 0
|
||||||
|
var offSubgroup = 0
|
||||||
|
proc test(EC: typedesc, bits: static int, randZ: bool, gen: RandomGen) =
|
||||||
|
stdout.write " "
|
||||||
|
for _ in 0 ..< Iters:
|
||||||
|
let P = rng.random_point(EC, randZ, gen)
|
||||||
|
var rP = P
|
||||||
|
rP.scalarMulGeneric(EC.F.C.getCurveOrder())
|
||||||
|
if bool rP.isInf():
|
||||||
|
inSubgroup += 1
|
||||||
|
doAssert bool P.isInSubgroup(), "Subgroup check issue on " & $EC & " with P: " & P.toHex()
|
||||||
|
else:
|
||||||
|
offSubgroup += 1
|
||||||
|
doAssert not bool P.isInSubgroup(), "Subgroup check issue on " & $EC & " with P: " & P.toHex()
|
||||||
|
|
||||||
|
var Q = P
|
||||||
|
var rQ: typeof(rP)
|
||||||
|
Q.clearCofactor()
|
||||||
|
rQ = Q
|
||||||
|
rQ.scalarMulGeneric(EC.F.C.getCurveOrder())
|
||||||
|
doAssert bool rQ.isInf(), "Cofactor clearing issue on " & $EC & " with Q: " & Q.toHex()
|
||||||
|
doAssert bool Q.isInSubgroup(), "Subgroup check issue on " & $EC & " with Q: " & Q.toHex()
|
||||||
|
|
||||||
|
stdout.write '.'
|
||||||
|
|
||||||
|
stdout.write '\n'
|
||||||
|
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = false, gen = Uniform)
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = true, gen = Uniform)
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = false, gen = HighHammingWeight)
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = true, gen = HighHammingWeight)
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = false, gen = Long01Sequence)
|
||||||
|
test(ec, bits = ec.F.C.getCurveOrderBitwidth(), randZ = true, gen = Long01Sequence)
|
||||||
|
|
||||||
|
echo " [SUCCESS] Test finished with ", inSubgroup, " points in ", G1_or_G2, " subgroup and ",
|
||||||
|
offSubgroup, " points on curve but not in subgroup (before cofactor clearing)"
|
|
@ -0,0 +1,19 @@
|
||||||
|
# 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
|
||||||
|
../constantine/config/common,
|
||||||
|
../constantine/config/curves,
|
||||||
|
../constantine/pairing/pairing_bls12,
|
||||||
|
# Test utilities
|
||||||
|
./t_pairing_template
|
||||||
|
|
||||||
|
runGTsubgroupTests(
|
||||||
|
Iters = 4,
|
||||||
|
GT = Fp12[BLS12_377],
|
||||||
|
finalExpHard_BLS12)
|
|
@ -0,0 +1,19 @@
|
||||||
|
# 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
|
||||||
|
../constantine/config/common,
|
||||||
|
../constantine/config/curves,
|
||||||
|
../constantine/pairing/pairing_bls12,
|
||||||
|
# Test utilities
|
||||||
|
./t_pairing_template
|
||||||
|
|
||||||
|
runGTsubgroupTests(
|
||||||
|
Iters = 4,
|
||||||
|
GT = Fp12[BLS12_381],
|
||||||
|
finalExpHard_BLS12)
|
|
@ -0,0 +1,19 @@
|
||||||
|
# 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
|
||||||
|
../constantine/config/common,
|
||||||
|
../constantine/config/curves,
|
||||||
|
../constantine/pairing/pairing_bn,
|
||||||
|
# Test utilities
|
||||||
|
./t_pairing_template
|
||||||
|
|
||||||
|
runGTsubgroupTests(
|
||||||
|
Iters = 4,
|
||||||
|
GT = Fp12[BN254_Nogami],
|
||||||
|
finalExpHard_BN)
|
|
@ -0,0 +1,19 @@
|
||||||
|
# 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
|
||||||
|
../constantine/config/common,
|
||||||
|
../constantine/config/curves,
|
||||||
|
../constantine/pairing/pairing_bn,
|
||||||
|
# Test utilities
|
||||||
|
./t_pairing_template
|
||||||
|
|
||||||
|
runGTsubgroupTests(
|
||||||
|
Iters = 4,
|
||||||
|
GT = Fp12[BN254_Snarks],
|
||||||
|
finalExpHard_BN)
|
|
@ -15,7 +15,10 @@ import
|
||||||
../constantine/towers,
|
../constantine/towers,
|
||||||
../constantine/config/curves,
|
../constantine/config/curves,
|
||||||
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
|
../constantine/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
|
||||||
../constantine/hash_to_curve/cofactors,
|
../constantine/curves/[zoo_subgroups, zoo_pairings],
|
||||||
|
../constantine/pairing/cyclotomic_fp12,
|
||||||
|
../constantine/io/io_towers,
|
||||||
|
|
||||||
# Test utilities
|
# Test utilities
|
||||||
../helpers/prng_unsafe
|
../helpers/prng_unsafe
|
||||||
|
|
||||||
|
@ -23,7 +26,8 @@ export
|
||||||
prng_unsafe, times, unittest,
|
prng_unsafe, times, unittest,
|
||||||
ec_shortweierstrass_affine, ec_shortweierstrass_projective,
|
ec_shortweierstrass_affine, ec_shortweierstrass_projective,
|
||||||
arithmetic, towers,
|
arithmetic, towers,
|
||||||
primitives
|
primitives, io_towers,
|
||||||
|
cyclotomic_fp12
|
||||||
|
|
||||||
type
|
type
|
||||||
RandomGen* = enum
|
RandomGen* = enum
|
||||||
|
@ -35,24 +39,24 @@ template affineType[F; G: static Subgroup](
|
||||||
ec: ECP_ShortW_Prj[F, G]): type =
|
ec: ECP_ShortW_Prj[F, G]): type =
|
||||||
ECP_ShortW_Aff[F, G]
|
ECP_ShortW_Aff[F, G]
|
||||||
|
|
||||||
func clearCofactorReference[F; G: static Subgroup](
|
func clearCofactor[F; G: static Subgroup](
|
||||||
ec: var ECP_ShortW_Aff[F, G]) =
|
ec: var ECP_ShortW_Aff[F, G]) =
|
||||||
# For now we don't have any affine operation defined
|
# For now we don't have any affine operation defined
|
||||||
var t {.noInit.}: ECP_ShortW_Prj[F, G]
|
var t {.noInit.}: ECP_ShortW_Prj[F, G]
|
||||||
t.projectiveFromAffine(ec)
|
t.projectiveFromAffine(ec)
|
||||||
t.clearCofactorReference()
|
t.clearCofactor()
|
||||||
ec.affineFromProjective(t)
|
ec.affineFromProjective(t)
|
||||||
|
|
||||||
func random_point*(rng: var RngState, EC: typedesc, randZ: bool, gen: RandomGen): EC {.noInit.} =
|
func random_point*(rng: var RngState, EC: typedesc, randZ: bool, gen: RandomGen): EC {.noInit.} =
|
||||||
if gen == Uniform:
|
if gen == Uniform:
|
||||||
result = rng.random_unsafe(EC)
|
result = rng.random_unsafe(EC)
|
||||||
result.clearCofactorReference()
|
result.clearCofactor()
|
||||||
elif gen == HighHammingWeight:
|
elif gen == HighHammingWeight:
|
||||||
result = rng.random_highHammingWeight(EC)
|
result = rng.random_highHammingWeight(EC)
|
||||||
result.clearCofactorReference()
|
result.clearCofactor()
|
||||||
else:
|
else:
|
||||||
result = rng.random_long01Seq(EC)
|
result = rng.random_long01Seq(EC)
|
||||||
result.clearCofactorReference()
|
result.clearCofactor()
|
||||||
|
|
||||||
template runPairingTests*(Iters: static int, C: static Curve, G1, G2, GT: typedesc, pairing_fn: untyped): untyped {.dirty.}=
|
template runPairingTests*(Iters: static int, C: static Curve, G1, G2, GT: typedesc, pairing_fn: untyped): untyped {.dirty.}=
|
||||||
bind affineType
|
bind affineType
|
||||||
|
@ -99,3 +103,43 @@ template runPairingTests*(Iters: static int, C: static Curve, G1, G2, GT: typede
|
||||||
test_bilinearity_double_impl(randZ = false, gen = Uniform)
|
test_bilinearity_double_impl(randZ = false, gen = Uniform)
|
||||||
test_bilinearity_double_impl(randZ = false, gen = HighHammingWeight)
|
test_bilinearity_double_impl(randZ = false, gen = HighHammingWeight)
|
||||||
test_bilinearity_double_impl(randZ = false, gen = Long01Sequence)
|
test_bilinearity_double_impl(randZ = false, gen = Long01Sequence)
|
||||||
|
|
||||||
|
func random_elem*(rng: var RngState, F: typedesc, gen: RandomGen): F {.inline, noInit.} =
|
||||||
|
if gen == Uniform:
|
||||||
|
result = rng.random_unsafe(F)
|
||||||
|
elif gen == HighHammingWeight:
|
||||||
|
result = rng.random_highHammingWeight(F)
|
||||||
|
else:
|
||||||
|
result = rng.random_long01Seq(F)
|
||||||
|
|
||||||
|
template runGTsubgroupTests*(Iters: static int, GT: typedesc, finalExpHard_fn: untyped): untyped {.dirty.}=
|
||||||
|
bind affineType
|
||||||
|
|
||||||
|
var rng: RngState
|
||||||
|
let timeseed = uint32(toUnix(getTime()) and (1'i64 shl 32 - 1)) # unixTime mod 2^32
|
||||||
|
seed(rng, timeseed)
|
||||||
|
echo "\n------------------------------------------------------\n"
|
||||||
|
echo "test_pairing_",$GT.C,"_gt xoshiro512** seed: ", timeseed
|
||||||
|
|
||||||
|
proc test_gt_impl(gen: RandomGen) =
|
||||||
|
stdout.write " "
|
||||||
|
for _ in 0 ..< Iters:
|
||||||
|
let a = rng.random_elem(GT, gen)
|
||||||
|
doAssert not bool a.isInCyclotomicSubgroup(), "The odds of generating randomly such an element are too low a: " & a.toHex()
|
||||||
|
var a2 = a
|
||||||
|
a2.finalExpEasy()
|
||||||
|
doAssert bool a2.isInCyclotomicSubgroup()
|
||||||
|
doAssert not bool a2.isInPairingSubgroup(), "The odds of generating randomly such an element are too low a2: " & a.toHex()
|
||||||
|
var a3 = a2
|
||||||
|
finalExpHard_fn(a3)
|
||||||
|
doAssert bool a3.isInCyclotomicSubgroup()
|
||||||
|
doAssert bool a3.isInPairingSubgroup()
|
||||||
|
stdout.write '.'
|
||||||
|
|
||||||
|
stdout.write '\n'
|
||||||
|
|
||||||
|
suite "Pairing - GT subgroup " & $GT.C & " [" & $WordBitwidth & "-bit mode]":
|
||||||
|
test "Final Exponentiation and GT-subgroup membership":
|
||||||
|
test_gt_impl(gen = Uniform)
|
||||||
|
test_gt_impl(gen = HighHammingWeight)
|
||||||
|
test_gt_impl(gen = Long01Sequence)
|
|
@ -19,7 +19,8 @@ import
|
||||||
../constantine/elliptic/ec_scalar_mul,
|
../constantine/elliptic/ec_scalar_mul,
|
||||||
../constantine/io/[io_fields, io_towers, io_ec],
|
../constantine/io/[io_fields, io_towers, io_ec],
|
||||||
../constantine/config/curves,
|
../constantine/config/curves,
|
||||||
../constantine/hash_to_curve/[hash_to_curve, cofactors],
|
../constantine/curves/zoo_subgroups,
|
||||||
|
../constantine/hash_to_curve/hash_to_curve,
|
||||||
../constantine/pairing/pairing_bls12,
|
../constantine/pairing/pairing_bls12,
|
||||||
# Test utilities
|
# Test utilities
|
||||||
../helpers/prng_unsafe
|
../helpers/prng_unsafe
|
||||||
|
|
Loading…
Reference in New Issue