mirror of
https://github.com/logos-storage/constantine.git
synced 2026-01-02 21:23:11 +00:00
* naive removal of out-of-place mul by non residue
* Use {.inline.} in a consistent manner across the codebase
* Handle aliasing for quadratic multiplication
* reorg optimization
* Handle aliasing for quadratic squaring
* handle aliasing in mul_sparse_complex_by_0y
* Rework multiplication by nonresidue, assume tower and twist use same non-residue
* continue rework
* continue on non-residues
* Remove "NonResidue *" calls
* handle aliasing in Chung-Hasan SQR2
* Handla aliasing in Chung-Hasan SQR3
* Use one less temporary in Chung Hasan sqr2
* handle aliasing in cubic extensions
* merge extension tower in the same file to reduce duplicate proc and allow better inlining
* handle aliasing in cubic inversion
* drop out-of-place proc from BigInt and finite fields as well
* less copies in line_projective
* remove a copy in fp12 by lines
318 lines
8.8 KiB
Nim
318 lines
8.8 KiB
Nim
# 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
|
||
../primitives,
|
||
../config/curves,
|
||
../arithmetic,
|
||
../towers,
|
||
../elliptic/[
|
||
ec_shortweierstrass_affine,
|
||
ec_shortweierstrass_projective
|
||
],
|
||
./lines_common
|
||
|
||
export lines_common
|
||
|
||
# ############################################################
|
||
#
|
||
# Miller Loop's Line Evaluation
|
||
# with projective coordinates
|
||
#
|
||
# ############################################################
|
||
#
|
||
# - Pairing Implementation Revisited
|
||
# Michael Scott, 2019
|
||
# https://eprint.iacr.org/2019/077
|
||
#
|
||
# - The Realm of the Pairings
|
||
# Diego F. Aranha and Paulo S. L. M. Barreto
|
||
# and Patrick Longa and Jefferson E. Ricardini, 2013
|
||
# https://eprint.iacr.org/2013/722.pdf
|
||
# http://sac2013.irmacs.sfu.ca/slides/s1.pdf
|
||
#
|
||
# - Efficient Implementation of Bilinear Pairings on ARM Processors
|
||
# Gurleen Grewal, Reza Azarderakhsh,
|
||
# Patrick Longa, Shi Hu, and David Jao, 2012
|
||
# https://eprint.iacr.org/2012/408.pdf
|
||
|
||
# Line evaluation only
|
||
# -----------------------------------------------------------------------------
|
||
|
||
func line_eval_double[F](
|
||
line: var Line[F],
|
||
T: ECP_ShortW_Proj[F, OnTwist]) =
|
||
## Evaluate the line function for doubling
|
||
## i.e. the tangent at T
|
||
##
|
||
## With T in homogenous projective coordinates (X, Y, Z)
|
||
## And ξ the sextic non residue to construct 𝔽p4 / 𝔽p6 / 𝔽p12
|
||
##
|
||
## M-Twist:
|
||
## A = -2ξ Y.Z
|
||
## B = 3bξ Z² - Y²
|
||
## C = 3 X²
|
||
##
|
||
## D-Twist are scaled by ξ to avoid dividing by ξ:
|
||
## A = -2ξ Y.Z
|
||
## B = 3b Z² - ξY²
|
||
## C = 3ξ X²
|
||
##
|
||
## Instead of
|
||
## - equation 10 from The Real of pairing, Aranha et al, 2013
|
||
## - or chapter 3 from pairing Implementation Revisited, Scott 2019
|
||
## A = -2 Y.Z
|
||
## B = 3b/ξ Z² - Y²
|
||
## C = 3 X²
|
||
##
|
||
## A constant factor will be wiped by the final exponentiation
|
||
## as for all non-zero α ∈ GF(pᵐ)
|
||
## with
|
||
## - p odd prime
|
||
## - and gcd(α,pᵐ) = 1 (i.e. the extension field pᵐ is using irreducible polynomials)
|
||
##
|
||
## Little Fermat holds and we have
|
||
## α^(pᵐ - 1) ≡ 1 (mod pᵐ)
|
||
##
|
||
## The final exponent is of the form
|
||
## (pᵏ-1)/r
|
||
##
|
||
## A constant factor on twisted coordinates pᵏᐟᵈ
|
||
## is a constant factor on pᵏ with d the twisting degree
|
||
## and so will be elminated. QED.
|
||
var v {.noInit.}: F
|
||
const b3 = 3 * F.C.getCoefB()
|
||
|
||
template A: untyped = line.x
|
||
template B: untyped = line.y
|
||
template C: untyped = line.z
|
||
|
||
A.prod(T.y, T.z) # A = Y.Z
|
||
C.square(T.x) # C = X²
|
||
v.square(T.y) # v = Y²
|
||
B.square(T.z) # B = Z²
|
||
|
||
A.double() # A = 2 Y.Z
|
||
A.neg() # A = -2 Y.Z
|
||
A *= SexticNonResidue # A = -2 ξ Y.Z
|
||
|
||
B *= b3 # B = 3b Z²
|
||
C *= 3 # C = 3X²
|
||
when F.C.getSexticTwist() == M_Twist:
|
||
B *= SexticNonResidue # B = 3b' Z² = 3bξ Z²
|
||
elif F.C.getSexticTwist() == D_Twist:
|
||
v *= SexticNonResidue # v = ξ Y²
|
||
C *= SexticNonResidue # C = 3ξ X²
|
||
else:
|
||
{.error: "unreachable".}
|
||
|
||
B -= v # B = 3bξ Z² - Y² (M-twist)
|
||
# B = 3b Z² - ξ Y² (D-twist)
|
||
|
||
func line_eval_add[F](
|
||
line: var Line[F],
|
||
T: ECP_ShortW_Proj[F, OnTwist],
|
||
Q: ECP_ShortW_Aff[F, OnTwist]) =
|
||
## Evaluate the line function for addition
|
||
## i.e. the line between T and Q
|
||
##
|
||
## With T in homogenous projective coordinates (X, Y, Z)
|
||
## And ξ the sextic non residue to construct 𝔽p4 / 𝔽p6 / 𝔽p12
|
||
##
|
||
## M-Twist:
|
||
## A = ξ (X₁ - Z₁X₂)
|
||
## B = (Y₁ - Z₁Y₂) X₂ - (X₁ - Z₁X₂) Y₂
|
||
## C = - (Y₁ - Z₁Y₂)
|
||
##
|
||
## D-Twist:
|
||
## A = X₁ - Z₁X₂
|
||
## B = (Y₁ - Z₁Y₂) X₂ - (X₁ - Z₁X₂) Y₂
|
||
## C = - (Y₁ - Z₁Y₂)
|
||
##
|
||
## Note: There is no need for complete formula as
|
||
## we have T ∉ [Q, -Q] in the Miller loop doubling-and-add
|
||
## i.e. the line cannot be vertical
|
||
var v {.noInit.}: F
|
||
|
||
template A: untyped = line.x
|
||
template B: untyped = line.y
|
||
template C: untyped = line.z
|
||
|
||
v.prod(T.z, Q.y) # v = Z₁Y₂
|
||
B.prod(T.z, Q.x) # B = Z₁X₂
|
||
|
||
A.diff(T.x, B) # A = X₁-Z₁X₂
|
||
C.diff(T.y, v) # C = Y₁-Z₁Y₂
|
||
|
||
v.prod(A, Q.y) # v = (X₁-Z₁X₂) Y₂
|
||
B.prod(C, Q.x) # B = (Y₁-Z₁Y₂) X₂
|
||
B -= v # B = (Y₁-Z₁Y₂) X₂ - (X₁-Z₁X₂) Y₂
|
||
|
||
C.neg() # C = -(Y₁-Z₁Y₂)
|
||
|
||
when F.C.getSexticTwist() == M_Twist:
|
||
A *= SexticNonResidue # A = ξ (X₁ - Z₁X₂)
|
||
|
||
func line_eval_fused_double[F](
|
||
line: var Line[F],
|
||
T: var ECP_ShortW_Proj[F, OnTwist]) =
|
||
## Fused line evaluation and elliptic point doubling
|
||
# Grewal et al, 2012 adapted to Scott 2019 line notation
|
||
var A {.noInit.}, B {.noInit.}, C {.noInit.}: F
|
||
var E {.noInit.}, F {.noInit.}, G {.noInit.}: F
|
||
template H: untyped = line.x
|
||
const b3 = 3*F.C.getCoefB()
|
||
|
||
var snrY = T.y
|
||
when F.C.getSexticTwist() == D_Twist:
|
||
snrY *= SexticNonResidue
|
||
|
||
A.prod(T.x, snrY)
|
||
A.div2() # A = XY/2
|
||
B.square(T.y) # B = Y²
|
||
C.square(T.z) # C = Z²
|
||
|
||
var snrB = B
|
||
when F.C.getSexticTwist() == D_Twist:
|
||
snrB *= SexticNonResidue
|
||
|
||
E.prod(C, b3)
|
||
when F.C.getSexticTwist() == M_Twist:
|
||
E *= SexticNonResidue # E = 3b'Z² = 3bξ Z²
|
||
|
||
F.prod(E, 3) # F = 3E = 9bZ²
|
||
G.sum(snrB, F)
|
||
G.div2() # G = (B+F)/2
|
||
H.sum(T.y, T.z)
|
||
H.square()
|
||
H -= B
|
||
H -= C # lx = H = (Y+Z)²-(B+C)= 2YZ
|
||
|
||
line.z.square(T.x)
|
||
line.z *= 3 # lz = 3X²
|
||
when F.C.getSexticTwist() == D_Twist:
|
||
line.z *= SexticNonResidue
|
||
|
||
line.y.diff(E, snrB) # ly = E-B = 3b'Z² - Y²
|
||
|
||
# In-place modification: invalidates `T.` calls
|
||
T.x.diff(snrB, F)
|
||
T.x *= A # X₃ = A(B-F) = XY/2.(Y²-9b'Z²)
|
||
# M-twist: XY/2.(Y²-9bξZ²)
|
||
# D-Twist: ξXY/2.(Y²ξ-9bZ²)
|
||
|
||
T.y.square(G)
|
||
E.square()
|
||
E *= 3
|
||
T.y -= E # Y₃ = G² - 3E² = (Y²+9b'Z²)²/4 - 3*(3b'Z²)²
|
||
# M-twist: (Y²+9bξZ²)²/4 - 3*(3bξZ²)²
|
||
# D-Twist: (ξY²+9bZ²)²/4 - 3*(3bZ²)²
|
||
|
||
when F.C.getSexticTwist() == D_Twist:
|
||
H *= SexticNonResidue
|
||
T.z.prod(snrB, H) # Z₃ = BH = Y²((Y+Z)² - (Y²+Z²)) = 2Y³Z
|
||
# M-twist: 2Y³Z
|
||
# D-twist: 2ξ²Y³Z
|
||
|
||
# Correction for Fp4 towering
|
||
H.neg() # lx = -H
|
||
when F.C.getSexticTwist() == M_Twist:
|
||
H *= SexticNonResidue
|
||
# else: the SNR is already integrated in H
|
||
|
||
func line_eval_fused_add[F](
|
||
line: var Line[F],
|
||
T: var ECP_ShortW_Proj[F, OnTwist],
|
||
Q: ECP_ShortW_Aff[F, OnTwist]) =
|
||
## Fused line evaluation and elliptic point addition
|
||
# Grewal et al, 2012 adapted to Scott 2019 line notation
|
||
var
|
||
A {.noInit.}: F
|
||
B {.noInit.}: F
|
||
C {.noInit.}: F
|
||
D {.noInit.}: F
|
||
E {.noInit.}: F
|
||
F {.noInit.}: F
|
||
G {.noInit.}: F
|
||
H {.noInit.}: F
|
||
I {.noInit.}: F
|
||
|
||
template lambda: untyped = line.x
|
||
template theta: untyped = line.z
|
||
template J: untyped = line.y
|
||
|
||
A.prod(Q.y, T.z)
|
||
B.prod(Q.x, T.z)
|
||
theta.diff(T.y, A) # θ = Y₁ - Z₁X₂
|
||
lambda.diff(T.x, B) # λ = X₁ - Z₁X₂
|
||
C.square(theta)
|
||
D.square(lambda)
|
||
E.prod(D, lambda)
|
||
F.prod(T.z, C)
|
||
G.prod(T.x, D)
|
||
H.double(G)
|
||
H.diff(F, H)
|
||
H += E
|
||
I.prod(T.y, E)
|
||
|
||
T.x.prod(theta, Q.x)
|
||
T.y.prod(lambda, Q.y)
|
||
J.diff(T.x, T.y)
|
||
|
||
# EC addition
|
||
T.x.prod(lambda, H)
|
||
|
||
T.y.diff(G, H)
|
||
T.y *= theta
|
||
T.y -= I
|
||
|
||
T.z *= E
|
||
|
||
# Line evaluation
|
||
theta.neg()
|
||
when F.C.getSexticTwist() == M_Twist:
|
||
lambda *= SexticNonResidue # A = ξ (X₁ - Z₁X₂)
|
||
|
||
# Public proc
|
||
# -----------------------------------------------------------------------------
|
||
|
||
func line_double*[F1, F2](
|
||
line: var Line[F2],
|
||
T: var ECP_ShortW_Proj[F2, OnTwist],
|
||
P: ECP_ShortW_Aff[F1, NotOnTwist]) =
|
||
## Doubling step of the Miller loop
|
||
## T in G2, P in G1
|
||
##
|
||
## Compute lt,t(P)
|
||
static: doAssert F1.C == F2.C
|
||
when true:
|
||
line_eval_fused_double(line, T)
|
||
line.line_update(P)
|
||
else:
|
||
line_eval_double(line, T)
|
||
line.line_update(P)
|
||
T.double()
|
||
|
||
func line_add*[F1, F2](
|
||
line: var Line[F2],
|
||
T: var ECP_ShortW_Proj[F2, OnTwist],
|
||
Q: ECP_ShortW_Aff[F2, OnTwist],
|
||
P: ECP_ShortW_Aff[F1, NotOnTwist]) =
|
||
## Addition step of the Miller loop
|
||
## T and Q in G2, P in G1
|
||
##
|
||
## Compute lt,q(P)
|
||
static: doAssert F1.C == F2.C
|
||
when true:
|
||
line_eval_fused_add(line, T, Q)
|
||
line.line_update(P)
|
||
else:
|
||
line_eval_add(line, T, Q)
|
||
line.line_update(P)
|
||
T += Q
|