From 34eb6fcfbd60b0dd9b8f60b53111f992eb47b6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mamy=20Andr=C3=A9-Ratsimbazafy?= Date: Sun, 27 Sep 2020 15:39:12 +0200 Subject: [PATCH] Move GLV constants --- constantine/curves/bls12_377_glv.nim | 66 ++++ constantine/curves/bls12_381_glv.nim | 66 ++++ constantine/curves/bn254_snarks_glv.nim | 69 +++++ constantine/curves/constants_glv.nim | 31 ++ constantine/elliptic/README.md | 6 + .../elliptic/ec_endomorphism_accel.nim | 82 ++++- .../elliptic/ec_endomorphism_params.nim | 289 ------------------ constantine/isogeny/frobenius.nim | 1 - 8 files changed, 318 insertions(+), 292 deletions(-) create mode 100644 constantine/curves/bls12_377_glv.nim create mode 100644 constantine/curves/bls12_381_glv.nim create mode 100644 constantine/curves/bn254_snarks_glv.nim create mode 100644 constantine/curves/constants_glv.nim delete mode 100644 constantine/elliptic/ec_endomorphism_params.nim diff --git a/constantine/curves/bls12_377_glv.nim b/constantine/curves/bls12_377_glv.nim new file mode 100644 index 0000000..e7bc97b --- /dev/null +++ b/constantine/curves/bls12_377_glv.nim @@ -0,0 +1,66 @@ +# 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/type_bigint, + ../io/io_bigints + +# 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-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) +) diff --git a/constantine/curves/bls12_381_glv.nim b/constantine/curves/bls12_381_glv.nim new file mode 100644 index 0000000..0fe92ee --- /dev/null +++ b/constantine/curves/bls12_381_glv.nim @@ -0,0 +1,66 @@ +# 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/type_bigint, + ../io/io_bigints + +# 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) +) + +# 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) +) diff --git a/constantine/curves/bn254_snarks_glv.nim b/constantine/curves/bn254_snarks_glv.nim new file mode 100644 index 0000000..1e7157c --- /dev/null +++ b/constantine/curves/bn254_snarks_glv.nim @@ -0,0 +1,69 @@ +# Constantine +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Copyright (c) 2020-Present Mamy André-Ratsimbazafy +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + ../config/type_bigint, + ../io/io_bigints + +# 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 +) + +# 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 +) diff --git a/constantine/curves/constants_glv.nim b/constantine/curves/constants_glv.nim new file mode 100644 index 0000000..4216af2 --- /dev/null +++ b/constantine/curves/constants_glv.nim @@ -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 + std/macros, + ../config/[curves, type_fp], + ../towers, + ./bls12_377_glv, + ./bls12_381_glv, + # ./bn254_nogami_glv, + ./bn254_snarks_glv + +{.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) diff --git a/constantine/elliptic/README.md b/constantine/elliptic/README.md index 82c345d..a0d5021 100644 --- a/constantine/elliptic/README.md +++ b/constantine/elliptic/README.md @@ -117,6 +117,12 @@ We use the complete addition law from Bos2014 for Jacobian coordinates, note tha https://eprint.iacr.org/2014/130 https://www.imsc.res.in/~ecc14/slides/costello.pdf +- Efficient and Secure Algorithms for GLV-Based Scalar\ + Multiplication and their Implementation\ + on GLV-GLSCurves (Extended Version)\ + Armando Faz-Hernández, Patrick Longa, Ana H. Sánchez, 2013\ + https://eprint.iacr.org/2013/158.pdf + - Remote Timing Attacks are Still Practical\ Billy Bob Brumley and Nicola Tuveri\ https://eprint.iacr.org/2011/232 diff --git a/constantine/elliptic/ec_endomorphism_accel.nim b/constantine/elliptic/ec_endomorphism_accel.nim index 058fd46..7b730c5 100644 --- a/constantine/elliptic/ec_endomorphism_accel.nim +++ b/constantine/elliptic/ec_endomorphism_accel.nim @@ -12,13 +12,13 @@ import # Internal ../primitives, ../config/[common, curves, type_bigint], + ../curves/constants_glv, ../arithmetic, ../io/io_bigints, ../towers, ../isogeny/frobenius, ./ec_weierstrass_affine, - ./ec_weierstrass_projective, - ./ec_endomorphism_params + ./ec_weierstrass_projective # ############################################################ # @@ -33,6 +33,84 @@ import # - GLV and GLS endomorphisms on G2 (Galbraith-Lin-Scott) # - NAF recoding (windowed Non-Adjacent-Form) +# Decomposition into scalars -> miniscalars +# ---------------------------------------------------------------------------------------- + +type + MultiScalar[M, LengthInBits: static int] = array[M, BigInt[LengthInBits]] + ## Decomposition of a secret scalar in multiple scalars + +func decomposeEndo*[M, scalBits, L: static int]( + miniScalars: var MultiScalar[M, L], + scalar: BigInt[scalBits], + F: typedesc[Fp or Fp2] + ) = + ## Decompose a secret scalar into M mini-scalars + ## using a curve endomorphism(s) characteristics. + ## + ## A scalar decomposition might lead to negative miniscalar(s). + ## For proper handling it requires either: + ## 1. Negating it and then negating the corresponding curve point P + ## 2. Adding an extra bit to the recoding, which will do the right thing™ + ## + ## For implementation solution 1 is faster: + ## - Double + Add is about 5000~8000 cycles on 6 64-bits limbs (BLS12-381) + ## - Conditional negate is about 10 cycles per Fp, on G2 projective we have 3 (coords) * 2 (Fp2) * 10 (cycles) ~= 60 cycles + ## We need to test the mini scalar, which is 65 bits so 2 Fp so about 2 cycles + ## and negate it as well. + ## + ## However solution 1 seems to cause issues (TODO) + ## with some of the BLS12-381 test cases (6 and 9) + ## - 0x5668a2332db27199dcfb7cbdfca6317c2ff128db26d7df68483e0a095ec8e88f + ## - 0x644dc62869683f0c93f38eaef2ba6912569dc91ec2806e46b4a3dd6a4421dad1 + + # Equal when no window or no negative handling, greater otherwise + static: doAssert L >= (scalBits + M - 1) div M + 1 + const w = F.C.getCurveOrderBitwidth().wordsRequired() + + when F is Fp: + var alphas{.noInit.}: ( + BigInt[scalBits + babai(F)[0][0].bits], + BigInt[scalBits + babai(F)[1][0].bits] + ) + else: + var alphas{.noInit.}: ( + BigInt[scalBits + babai(F)[0][0].bits], + BigInt[scalBits + babai(F)[1][0].bits], + BigInt[scalBits + babai(F)[2][0].bits], + BigInt[scalBits + babai(F)[3][0].bits] + ) + + staticFor i, 0, M: + when bool babai(F)[i][0].isZero(): + alphas[i].setZero() + else: + alphas[i].prod_high_words(babai(F)[i][0], scalar, w) + when babai(F)[i][1]: + # prod_high_words works like logical right shift + # When negative, we should add 1 to properly round toward -infinity + alphas[i] += SecretWord(1) + + # We have k0 = s - 𝛼0 b00 - 𝛼1 b10 ... - 𝛼m bm0 + # and kj = 0 - 𝛼j b0j - 𝛼1 b1j ... - 𝛼m bmj + var + k: array[M, BigInt[scalBits]] # zero-init required + alphaB {.noInit.}: BigInt[scalBits] + k[0] = scalar + staticFor miniScalarIdx, 0, M: + staticFor basisIdx, 0, M: + when not bool lattice(F)[basisIdx][miniScalarIdx][0].isZero(): + when bool lattice(F)[basisIdx][miniScalarIdx][0].isOne(): + alphaB.copyTruncatedFrom(alphas[basisIdx]) + else: + alphaB.prod(alphas[basisIdx], lattice(F)[basisIdx][miniScalarIdx][0]) + + when lattice(F)[basisIdx][miniScalarIdx][1] xor babai(F)[basisIdx][1]: + k[miniScalarIdx] += alphaB + else: + k[miniScalarIdx] -= alphaB + + miniScalars[miniScalarIdx].copyTruncatedFrom(k[miniScalarIdx]) # Secret scalar + dynamic point # ---------------------------------------------------------------- diff --git a/constantine/elliptic/ec_endomorphism_params.nim b/constantine/elliptic/ec_endomorphism_params.nim deleted file mode 100644 index a19d079..0000000 --- a/constantine/elliptic/ec_endomorphism_params.nim +++ /dev/null @@ -1,289 +0,0 @@ -# Constantine -# Copyright (c) 2018-2019 Status Research & Development GmbH -# Copyright (c) 2020-Present Mamy André-Ratsimbazafy -# Licensed and distributed under either of -# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). -# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import - std/macros, - # Internal - ../primitives, - ../config/[common, curves, type_bigint], - ../arithmetic, - ../io/io_bigints, - ../towers, - ./ec_weierstrass_projective - -# ############################################################ -# -# Endomorphism acceleration decomposition parameters -# for Scalar Multiplication -# -# ############################################################ -# -# TODO: cleanup, those should be derived in the config folder -# and stored in a constant -# or generated from sage into a config file read at compile-time - -type - MultiScalar*[M, LengthInBits: static int] = array[M, BigInt[LengthInBits]] - ## Decomposition of a secret scalar in multiple scalars - -# BN254 Snarks G1 -# ---------------------------------------------------------------------------------------- - -# Chapter 6.3.1 - Guide to Pairing-based Cryptography -const Lattice_BN254_Snarks_G1 = ( - # Curve of order 254 -> mini scalars of size 127 - # u = 0x44E992B44A6909F1 - # (BigInt, isNeg) - ((BigInt[64].fromHex"0x89d3256894d213e3", false), # 2u + 1 - (BigInt[127].fromHex"0x6f4d8248eeb859fd0be4e1541221250b", false)), # 6u² + 4u + 1 - ((BigInt[127].fromHex"0x6f4d8248eeb859fc8211bbeb7d4f1128", false), # 6u² + 2u - (BigInt[64].fromHex"0x89d3256894d213e3", true)) # -2u - 1 -) - -const Babai_BN254_Snarks_G1 = ( - # Vector for Babai rounding - # (BigInt, isNeg) - (BigInt[66].fromHex"0x2d91d232ec7e0b3d7", false), # (2u + 1) << 2^256 // r - (BigInt[130].fromHex"0x24ccef014a773d2d25398fd0300ff6565", false) # (6u² + 4u + 1) << 2^256 // r -) - -# BLS12-377 G1 -# ---------------------------------------------------------------------------------------- - -const Lattice_BLS12_377_G1 = ( - # (BigInt, isNeg) - ((BigInt[127].fromHex"0x452217cc900000010a11800000000000", false), # u² - 1 - (BigInt[1].fromHex"0x1", true)), # -1 - ((BigInt[1].fromHex"0x1", false), # 1 - (BigInt[127].fromHex"0x452217cc900000010a11800000000001", false)) # u² -) - -const Babai_BLS12_377_G1 = ( - # Vector for Babai rounding - # (BigInt, isNeg) - (BigInt[130].fromHex"0x3b3f7aa969fd371607f72ed32af90182c", false), - (BigInt[4].fromHex"0xd", false) -) - -# BLS12-381 G1 -# ---------------------------------------------------------------------------------------- - -const Lattice_BLS12_381_G1 = ( - # (BigInt, isNeg) - ((BigInt[128].fromHex"0xac45a4010001a40200000000ffffffff", false), # u² - 1 - (BigInt[1].fromHex"0x1", true)), # -1 - ((BigInt[1].fromHex"0x1", false), # 1 - (BigInt[128].fromHex"0xac45a4010001a4020000000100000000", false)) # u² -) - -const Babai_BLS12_381_G1 = ( - # Vector for Babai rounding - # (BigInt, isNeg) - (BigInt[129].fromHex"0x17c6becf1e01faadd63f6e522f6cfee30", false), - (BigInt[2].fromHex"0x2", false) -) - -# BN254 Snarks G2 -# ---------------------------------------------------------------------------------------- - -const Lattice_BN254_Snarks_G2 = ( - # Curve of order 254 -> mini scalars of size 65 - # x = 0x44E992B44A6909F1 - # Value, isNeg - ((BigInt[63].fromHex"0x44e992b44a6909f2", false), # x+1 - (BigInt[63].fromHex"0x44e992b44a6909f1", false), # x - (BigInt[63].fromHex"0x44e992b44a6909f1", false), # x - (BigInt[64].fromHex"0x89d3256894d213e2", true)), # -2x - - ((BigInt[64].fromHex"0x89d3256894d213e3", false), # 2x+1 - (BigInt[63].fromHex"0x44e992b44a6909f1", true), # -x - (BigInt[63].fromHex"0x44e992b44a6909f2", true), # -x-1 - (BigInt[63].fromHex"0x44e992b44a6909f1", true)), # -x - - ((BigInt[64].fromHex"0x89d3256894d213e2", false), # 2x - (BigInt[64].fromHex"0x89d3256894d213e3", false), # 2x+1 - (BigInt[64].fromHex"0x89d3256894d213e3", false), # 2x+1 - (BigInt[64].fromHex"0x89d3256894d213e3", false)), # 2x+1 - - ((BigInt[63].fromHex"0x44e992b44a6909f0", false), # x-1 - (BigInt[65].fromHex"0x113a64ad129a427c6", false), # 4x+2 - (BigInt[64].fromHex"0x89d3256894d213e1", true), # -2x+1 - (BigInt[63].fromHex"0x44e992b44a6909f0", false)), # x-1 - ) - -const Babai_BN254_Snarks_G2 = ( - # Vector for Babai rounding - # Value, isNeg - (BigInt[128].fromHex"0xc444fab18d269b9dd0cb46fd51906254", false), # 2x²+3x+1 << 2^256 // r - (BigInt[193].fromHex"0x13d00631561b2572922df9f942d7d77c7001378f5ee78976d", false), # 3x³+8x²+x << 2^256 // r - (BigInt[192].fromhex"0x9e80318ab0d92b94916fcfca16bebbe436510546a93478ab", false), # 6x³+4x²+x << 2^256 // r - (BigInt[128].fromhex"0xc444fab18d269b9af7ae23ce89afae7d", true) # -2x²-x << 2^256 // r -) - -# BLS12-377 G2 -# ---------------------------------------------------------------------------------------- - -const Lattice_BLS12_377_G2 = ( - # Curve of order 254 -> mini scalars of size 65 - # x = -0xd201000000010000 - # Value, isNeg - ((BigInt[64].fromHex"0x8508c00000000001", true), # -x - (BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x0", false)), # 0 - - ((BigInt[1].fromHex"0x0", false), # 0 - (BigInt[64].fromHex"0x8508c00000000001", true), # -x - (BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false)), # 0 - - ((BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[64].fromHex"0x8508c00000000001", true), # -x - (BigInt[1].fromHex"0x1", false)), # 1 - - ((BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x1", true), # -1 - (BigInt[64].fromHex"0x8508c00000000001", true)) # -x -) - -const Babai_BLS12_377_G2 = ( - # Vector for Babai rounding - # Value, isNeg - (BigInt[193].fromHex"0x1eca0125755aed064f63abaff9084ce152979759b442f60d1", true), - (BigInt[130].fromHex"0x3b3f7aa969fd371607f72ed32af90181f", true), - (BigInt[67].fromhex"0x72030ba8ee9c06415", true), - (BigInt[1].fromhex"0x0", false) -) - -# BLS12-381 G2 -# ---------------------------------------------------------------------------------------- - -const Lattice_BLS12_381_G2 = ( - # Curve of order 254 -> mini scalars of size 65 - # x = -0xd201000000010000 - # Value, isNeg - ((BigInt[64].fromHex"0xd201000000010000", false), # -x - (BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x0", false)), # 0 - - ((BigInt[1].fromHex"0x0", false), # 0 - (BigInt[64].fromHex"0xd201000000010000", false), # -x - (BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false)), # 0 - - ((BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[64].fromHex"0xd201000000010000", false), # -x - (BigInt[1].fromHex"0x1", false)), # 1 - - ((BigInt[1].fromHex"0x1", false), # 1 - (BigInt[1].fromHex"0x0", false), # 0 - (BigInt[1].fromHex"0x1", true), # -1 - (BigInt[64].fromHex"0xd201000000010000", false)) # -x -) - -const Babai_BLS12_381_G2 = ( - # Vector for Babai rounding - # Value, isNeg - (BigInt[193].fromHex"0x1381204ca56cd56b533cfcc0d3e76ec2892078a5e8573b29c", false), - (BigInt[129].fromHex"0x17c6becf1e01faadd63f6e522f6cfee2f", true), - (BigInt[65].fromhex"0x1cfbe4f7bd0027db0", false), - (BigInt[1].fromhex"0x0", false) -) - -# Decomposition routine -# ---------------------------------------------------------------------------------------- - -{.experimental: "dynamicbindsym".} -macro dispatch(prefix: static string, C: static Curve, G: static string): untyped = - result = bindSym(prefix & $C & "_" & G) - -template babai(F: typedesc[Fp or Fp2]): untyped = - const G = if F is Fp: "G1" - else: "G2" - dispatch("Babai_", F.C, G) - -template lattice(F: typedesc[Fp or Fp2]): untyped = - const G = if F is Fp: "G1" - else: "G2" - dispatch("Lattice_", F.C, G) - -func decomposeEndo*[M, scalBits, L: static int]( - miniScalars: var MultiScalar[M, L], - scalar: BigInt[scalBits], - F: typedesc[Fp or Fp2] - ) = - ## Decompose a secret scalar into M mini-scalars - ## using a curve endomorphism(s) characteristics. - ## - ## A scalar decomposition might lead to negative miniscalar(s). - ## For proper handling it requires either: - ## 1. Negating it and then negating the corresponding curve point P - ## 2. Adding an extra bit to the recoding, which will do the right thing™ - ## - ## For implementation solution 1 is faster: - ## - Double + Add is about 5000~8000 cycles on 6 64-bits limbs (BLS12-381) - ## - Conditional negate is about 10 cycles per Fp, on G2 projective we have 3 (coords) * 2 (Fp2) * 10 (cycles) ~= 60 cycles - ## We need to test the mini scalar, which is 65 bits so 2 Fp so about 2 cycles - ## and negate it as well. - ## - ## However solution 1 seems to cause issues (TODO) - ## with some of the BLS12-381 test cases (6 and 9) - ## - 0x5668a2332db27199dcfb7cbdfca6317c2ff128db26d7df68483e0a095ec8e88f - ## - 0x644dc62869683f0c93f38eaef2ba6912569dc91ec2806e46b4a3dd6a4421dad1 - - # Equal when no window or no negative handling, greater otherwise - static: doAssert L >= (scalBits + M - 1) div M + 1 - const w = F.C.getCurveOrderBitwidth().wordsRequired() - - when F is Fp: - var alphas{.noInit.}: ( - BigInt[scalBits + babai(F)[0][0].bits], - BigInt[scalBits + babai(F)[1][0].bits] - ) - else: - var alphas{.noInit.}: ( - BigInt[scalBits + babai(F)[0][0].bits], - BigInt[scalBits + babai(F)[1][0].bits], - BigInt[scalBits + babai(F)[2][0].bits], - BigInt[scalBits + babai(F)[3][0].bits] - ) - - staticFor i, 0, M: - when bool babai(F)[i][0].isZero(): - alphas[i].setZero() - else: - alphas[i].prod_high_words(babai(F)[i][0], scalar, w) - when babai(F)[i][1]: - # prod_high_words works like logical right shift - # When negative, we should add 1 to properly round toward -infinity - alphas[i] += SecretWord(1) - - # We have k0 = s - 𝛼0 b00 - 𝛼1 b10 ... - 𝛼m bm0 - # and kj = 0 - 𝛼j b0j - 𝛼1 b1j ... - 𝛼m bmj - var - k: array[M, BigInt[scalBits]] # zero-init required - alphaB {.noInit.}: BigInt[scalBits] - k[0] = scalar - staticFor miniScalarIdx, 0, M: - staticFor basisIdx, 0, M: - when not bool lattice(F)[basisIdx][miniScalarIdx][0].isZero(): - when bool lattice(F)[basisIdx][miniScalarIdx][0].isOne(): - alphaB.copyTruncatedFrom(alphas[basisIdx]) - else: - alphaB.prod(alphas[basisIdx], lattice(F)[basisIdx][miniScalarIdx][0]) - - when lattice(F)[basisIdx][miniScalarIdx][1] xor babai(F)[basisIdx][1]: - k[miniScalarIdx] += alphaB - else: - k[miniScalarIdx] -= alphaB - - miniScalars[miniScalarIdx].copyTruncatedFrom(k[miniScalarIdx]) diff --git a/constantine/isogeny/frobenius.nim b/constantine/isogeny/frobenius.nim index 3c8e91d..6288159 100644 --- a/constantine/isogeny/frobenius.nim +++ b/constantine/isogeny/frobenius.nim @@ -8,7 +8,6 @@ import std/macros, - ../config/curves, ../arithmetic, ../towers, ../curves/constants_frobenius