constantine/constantine/elliptic/ec_endomorphism_params.nim
Mamy Ratsimbazafy d41c653c8a
Double-width tower extension part 1 (#72)
* Implement double-width field multiplication for double-width towering

* Fp2 mul acceleration via double-width lazy reduction (pure Nim)

* Inline assembly for basic add and sub

* Use 2 registers instead of 12+ for ASM conditional copy

* Prepare assembly for extended multiprecision multiplication support

* Add assembly for mul

* initial implementation of assembly reduction

* stash current progress of assembly reduction

* Fix clobbering issue, only P256 comparison remain buggy

* Fix asm montgomery reduction for NIST P256 as well

* MULX/ADCX/ADOX multi-precision multiplication

* MULX/ADCX/ADOX reduction v1

* Add (deactivated) assembly for double-width substraction + rework benches

* Add bench to nimble and deactivate double-width for now. slower than classic

* Fix x86-32 running out of registers for mul

* Clang needs to be at v9 to support flag output constraints (Xcode 11.4.2 / OSX Catalina)

* 32-bit doesn't have enough registers for ASM mul

* Fix again Travis Clang 9 issues

* LLVM 9 is not whitelisted in travis

* deactivated assembler with travis clang

* syntax error

* another

* ...

* missing space, yeah ...
2020-08-20 10:21:39 +02:00

135 lines
5.3 KiB
Nim
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
# Internal
../primitives,
../config/[common, curves, type_bigint],
../arithmetic,
../io/io_bigints,
../towers,
./ec_weierstrass_projective
# Parameters for GLV endomorphisms acceleration
# ----------------------------------------------------------------------------------------
# TODO: cleanup, those should be derived in the config folder
# and stored in a constant
type
MultiScalar*[M, LengthInBits: static int] = array[M, BigInt[LengthInBits]]
## Decomposition of a secret scalar in multiple scalars
# Chapter 6.3.1 - Guide to Pairing-based Cryptography
const Lattice_BN254_Snarks_G1: array[2, array[2, tuple[b: BigInt[127], isNeg: bool]]] = [
# Curve of order 254 -> mini scalars of size 127
# u = 0x44E992B44A6909F1
[(BigInt[127].fromHex"0x89d3256894d213e3", false), # 2u + 1
(BigInt[127].fromHex"0x6f4d8248eeb859fd0be4e1541221250b", false)], # 6u² + 4u + 1
[(BigInt[127].fromHex"0x6f4d8248eeb859fc8211bbeb7d4f1128", false), # 6u² + 2u
(BigInt[127].fromHex"0x89d3256894d213e3", true)] # -2u - 1
]
const Babai_BN254_Snarks_G1 = [
# Vector for Babai rounding
BigInt[127].fromHex"0x89d3256894d213e3", # 2u + 1
BigInt[127].fromHex"0x6f4d8248eeb859fd0be4e1541221250b" # 6u² + 4u + 1
]
func decomposeScalar_BN254_Snarks_G1*[M, scalBits, L: static int](
scalar: BigInt[scalBits],
miniScalars: var MultiScalar[M, L]
) =
## Decompose a secret scalar into mini-scalar exploiting
## BN254_Snarks specificities.
##
## TODO: Generalize to all BN curves
## - needs a Lattice type
## - needs to better support negative bigints, (extra bit for sign?)
static: doAssert L == (scalBits + M - 1) div M + 1
# 𝛼0 = (0x2d91d232ec7e0b3d7 * s) >> 256
# 𝛼1 = (0x24ccef014a773d2d25398fd0300ff6565 * s) >> 256
const
w = BN254_Snarks.getCurveOrderBitwidth().wordsRequired()
alphaHats = (BigInt[66].fromHex"0x2d91d232ec7e0b3d7",
BigInt[130].fromHex"0x24ccef014a773d2d25398fd0300ff6565")
var alphas{.noInit.}: array[M, BigInt[scalBits]] # TODO size 66+254 and 130+254
staticFor i, 0, M:
alphas[i].prod_high_words(alphaHats[i], scalar, w)
# We have k0 = s - 𝛼0 b00 - 𝛼1 b10
# and kj = 0 - 𝛼j b0j - 𝛼1 b1j
var k: array[M, BigInt[scalBits]]
k[0] = scalar
for miniScalarIdx in 0 ..< M:
for basisIdx in 0 ..< M:
var alphaB {.noInit.}: BigInt[scalBits]
alphaB.prod(alphas[basisIdx], Lattice_BN254_Snarks_G1[basisIdx][miniScalarIdx].b) # TODO small lattice size
if Lattice_BN254_Snarks_G1[basisIdx][miniScalarIdx].isNeg:
k[miniScalarIdx] += alphaB
else:
k[miniScalarIdx] -= alphaB
miniScalars[miniScalarIdx].copyTruncatedFrom(k[miniScalarIdx])
const Lattice_BLS12_381_G1: array[2, array[2, tuple[b: BigInt[128], isNeg: bool]]] = [
# Curve of order 254 -> mini scalars of size 127
# u = 0x44E992B44A6909F1
[(BigInt[128].fromHex"0xac45a4010001a40200000000ffffffff", false), # u² - 1
(BigInt[128].fromHex"0x1", true)], # -1
[(BigInt[128].fromHex"0x1", false), # 1
(BigInt[128].fromHex"0xac45a4010001a4020000000100000000", false)] # u²
]
const Babai_BLS12_381_G1 = [
# Vector for Babai rounding
BigInt[128].fromHex"0xac45a4010001a4020000000100000000",
BigInt[128].fromHex"0x1"
]
func decomposeScalar_BLS12_381_G1*[M, scalBits, L: static int](
scalar: BigInt[scalBits],
miniScalars: var MultiScalar[M, L]
) =
## Decompose a secret scalar into mini-scalar exploiting
## BLS12_381 specificities.
##
## TODO: Generalize to all BLS curves
## - needs a Lattice type
## - needs to better support negative bigints, (extra bit for sign?)
static: doAssert L == (scalBits + M - 1) div M + 1
# 𝛼0 = (0x2d91d232ec7e0b3d7 * s) >> 256
# 𝛼1 = (0x24ccef014a773d2d25398fd0300ff6565 * s) >> 256
const
w = BLS12_381.getCurveOrderBitwidth().wordsRequired()
alphaHats = (BigInt[129].fromHex"0x17c6becf1e01faadd63f6e522f6cfee30",
BigInt[2].fromHex"0x2")
var alphas{.noInit.}: array[M, BigInt[scalBits]] # TODO size 256+255 and 132+255
staticFor i, 0, M:
alphas[i].prod_high_words(alphaHats[i], scalar, w)
# We have k0 = s - 𝛼0 b00 - 𝛼1 b10
# and kj = 0 - 𝛼j b0j - 𝛼1 b1j
var k: array[M, BigInt[scalBits]]
k[0] = scalar
for miniScalarIdx in 0 ..< M:
for basisIdx in 0 ..< M:
var alphaB {.noInit.}: BigInt[scalBits]
alphaB.prod(alphas[basisIdx], Lattice_BLS12_381_G1[basisIdx][miniScalarIdx].b) # TODO small lattice size
if Lattice_BLS12_381_G1[basisIdx][miniScalarIdx].isNeg:
k[miniScalarIdx] += alphaB
else:
k[miniScalarIdx] -= alphaB
miniScalars[miniScalarIdx].copyTruncatedFrom(k[miniScalarIdx])