357 lines
12 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
# Standard library
macros,
# Internal
./curves_parser, ./common,
../arithmetic/[precomputed, bigints]
{.push used.}
# ############################################################
#
# Configuration of finite fields
#
# ############################################################
# Curves & their corresponding finite fields are preconfigured in this file
# Note, in the past the convention was to name a curve by its conjectured security level.
# as this might change with advances in research, the new convention is
# to name curves according to the length of the prime bit length.
# i.e. the BN254 was previously named BN128.
# Curves security level were significantly impacted by
# advances in the Tower Number Field Sieve.
# in particular BN254 curve security dropped
# from estimated 128-bit to estimated 100-bit
# Barbulescu, R. and S. Duquesne, "Updating Key Size Estimations for Pairings",
# Journal of Cryptology, DOI 10.1007/s00145-018-9280-5, January 2018.
# Generates public:
# - type Curve* = enum
# - proc Mod*(curve: static Curve): auto
# which returns the field modulus of the curve
declareCurves:
# -----------------------------------------------------------------------------
# Curves added when passed "-d:testingCurves"
curve Fake101:
testingCurve: true
bitsize: 7
modulus: "0x65" # 101 in hex
curve Mersenne61:
testingCurve: true
bitsize: 61
modulus: "0x1fffffffffffffff" # 2^61 - 1
curve Mersenne127:
testingCurve: true
bitsize: 127
modulus: "0x7fffffffffffffffffffffffffffffff" # 2^127 - 1
# -----------------------------------------------------------------------------
curve P224: # NIST P-224
bitsize: 224
modulus: "0xffffffff_ffffffff_ffffffff_ffffffff_00000000_00000000_00000001"
curve BN254: # Zero-Knowledge proofs curve (SNARKS, STARKS)
bitsize: 254
modulus: "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"
# Equation: Y^2 = X^3 + 3
curve Curve25519: # Bernstein curve
bitsize: 255
modulus: "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed"
curve P256: # secp256r1 / NIST P-256
bitsize: 256
modulus: "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff"
curve Secp256k1: # Bitcoin curve
bitsize: 256
modulus: "0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F"
curve BLS12_377:
# Zexe curve
# (p41) https://eprint.iacr.org/2018/962.pdf
# https://github.com/ethereum/EIPs/blob/41dea9615/EIPS/eip-2539.md
bitsize: 377
modulus: "0x01ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001"
curve BLS12_381:
bitsize: 381
modulus: "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"
# Equation: y^2 = x^3 + 4
curve BN446:
bitsize: 446
modulus: "0x2400000000000000002400000002d00000000d800000021c0000001800000000870000000b0400000057c00000015c000000132000000067"
# u = 2^110 + 2^36 + 1
curve FKM12_447: # Fotiadis-Konstantinou-Martindale
bitsize: 447
modulus: "0x4ce300001338c00001c08180000f20cfffffe5a8bffffd08a000000f228000007e8ffffffaddfffffffdc00000009efffffffca000000007"
# TNFS Resistant Families of Pairing-Friendly Elliptic Curves
# Georgios Fotiadis and Elisavet Konstantinou, 2018
# https://eprint.iacr.org/2018/1017
#
# Family 17 choice b of
# Optimal TNFS-secure pairings on elliptic curves with composite embedding degree
# Georgios Fotiadis and Chloe Martindale, 2019
# https://eprint.iacr.org/2019/555
#
# A short-list of pairing-friendly curves resistant toSpecial TNFS at the 128-bit security level
# Aurore Guillevic
# https://hal.inria.fr/hal-02396352v2/document
#
# p(x) = 1728x^6 + 2160x^5 + 1548x^4 + 756x^3 + 240x^2 + 54x + 7
# t(x) = 6x² + 1, r(x) = 36x^4 + 36x^3 + 18x^2 + 6x + 1.
# Choice (b):u=2^72 2^71 2^36
#
# Note the paper mentions 446-bit but it's 447
curve BLS12_461:
# Updating Key Size Estimations for Pairings
# Barbulescu, R. and S. Duquesne, 2018
# https://hal.archives-ouvertes.fr/hal-01534101/file/main.pdf
bitsize: 461
modulus: "0x15555545554d5a555a55d69414935fbd6f1e32d8bacca47b14848b42a8dffa5c1cc00f26aa91557f00400020000555554aaaaaac0000aaaaaaab"
# u = 2^77 + 2^50 + 2^33
# p = (u - 1)^2 (u^4 - u^2 + 1)/3 + u
curve BN462:
# Pairing-Friendly Curves
# IETF Draft
# https://tools.ietf.org/id/draft-irtf-cfrg-pairing-friendly-curves-02.html
# Updating Key Size Estimations for Pairings
# Barbulescu, R. and S. Duquesne, 2018
# https://hal.archives-ouvertes.fr/hal-01534101/file/main.pdf
bitsize: 462
modulus: "0x240480360120023ffffffffff6ff0cf6b7d9bfca0000000000d812908f41c8020ffffffffff6ff66fc6ff687f640000000002401b00840138013"
# u = 2^114 + 2^101 2^14 1
# ############################################################
#
# Curve Families
#
# ############################################################
type CurveFamily = enum
None
BN # Barreto-Naehrig
BLS # Barreto-Lynn-Scott
func family*(curve: Curve): CurveFamily =
case curve
of BN254:
BN
of BLS12_381:
BLS
else:
None
# ############################################################
#
# Curve Specific Parameters
#
# ############################################################
#
# In the form CurveXXX_ParameterName where CurveXXX is the curve name + number of bits
# of the field modulus
# BN Curves
# ------------------------------------------------------------
# See https://tools.ietf.org/id/draft-yonezawa-pairing-friendly-curves-00.html
#
# The prime p and order r are primes and of the form
# p = 36u^4 + 36u^3 + 24u^2 + 6u + 1
# r = 36u^4 + 36u^3 + 18u^2 + 6u + 1
#
# https://eprint.iacr.org/2010/429.pdf
# https://eprint.iacr.org/2013/879.pdf
# Usage: Zero-Knowledge Proofs / zkSNARKs in ZCash and Ethereum 1
# https://eips.ethereum.org/EIPS/eip-196
# BLS Curves
# ------------------------------------------------------------
# See https://tools.ietf.org/id/draft-yonezawa-pairing-friendly-curves-00.html
#
# BLS12 curves
# The prime p and order r are primes and of the form
# p = (u - 1)^2 (u^4 - u^2 + 1)/3 + u
# r = u^4 - u^2 + 1
#
# BLS48 curves
# The prime p and order r are primes and of the form
# p = (u - 1)^2 (u^16 - u^8 + 1)/3 + u
# r = u^16 - u^8 + 1
# ############################################################
#
# Curve Modulus Accessor
#
# ############################################################
{.experimental: "dynamicBindSym".}
macro Mod*(C: static Curve): untyped =
## Get the Modulus associated to a curve
result = bindSym($C & "_Modulus")
# ############################################################
#
# Autogeneration of precomputed Montgomery constants in ROM
#
# ############################################################
macro genMontyMagics(T: typed): untyped =
## Store
## - the Montgomery magic constant "R^2 mod N" in ROM
## For each curve under the private symbol "MyCurve_R2modP"
## - the Montgomery magic constant -1/P mod 2^WordBitSize
## For each curve under the private symbol "MyCurve_NegInvModWord
T.getImpl.expectKind(nnkTypeDef)
T.getImpl[2].expectKind(nnkEnumTy)
result = newStmtList()
let E = T.getImpl[2]
for i in 1 ..< E.len:
let curve = E[i]
# const MyCurve_CanUseNoCarryMontyMul = useNoCarryMontyMul(MyCurve_Modulus)
result.add newConstStmt(
ident($curve & "_CanUseNoCarryMontyMul"), newCall(
bindSym"useNoCarryMontyMul",
nnkDotExpr.newTree(
bindSym($curve & "_Modulus"),
ident"mres"
)
)
)
# const MyCurve_CanUseNoCarryMontySquare = useNoCarryMontySquare(MyCurve_Modulus)
result.add newConstStmt(
ident($curve & "_CanUseNoCarryMontySquare"), newCall(
bindSym"useNoCarryMontySquare",
nnkDotExpr.newTree(
bindSym($curve & "_Modulus"),
ident"mres"
)
)
)
# const MyCurve_R2modP = r2mod(MyCurve_Modulus)
result.add newConstStmt(
ident($curve & "_R2modP"), newCall(
bindSym"r2mod",
nnkDotExpr.newTree(
bindSym($curve & "_Modulus"),
ident"mres"
)
)
)
# const MyCurve_NegInvModWord = negInvModWord(MyCurve_Modulus)
result.add newConstStmt(
ident($curve & "_NegInvModWord"), newCall(
bindSym"negInvModWord",
nnkDotExpr.newTree(
bindSym($curve & "_Modulus"),
ident"mres"
)
)
)
# const MyCurve_montyOne = montyOne(MyCurve_Modulus)
result.add newConstStmt(
ident($curve & "_MontyOne"), newCall(
bindSym"montyOne",
nnkDotExpr.newTree(
bindSym($curve & "_Modulus"),
ident"mres"
)
)
)
# const MyCurve_InvModExponent = primeMinus2_BE(MyCurve_Modulus)
result.add newConstStmt(
ident($curve & "_InvModExponent"), newCall(
bindSym"primeMinus2_BE",
nnkDotExpr.newTree(
bindSym($curve & "_Modulus"),
ident"mres"
)
)
)
# const MyCurve_PrimePlus1div2 = primePlus1div2(MyCurve_Modulus)
result.add newConstStmt(
ident($curve & "_PrimePlus1div2"), newCall(
bindSym"primePlus1div2",
nnkDotExpr.newTree(
bindSym($curve & "_Modulus"),
ident"mres"
)
)
)
# echo result.toStrLit
genMontyMagics(Curve)
func getCurveBitSize*(C: static Curve): static int =
## Returns the number of bits taken by the curve modulus
result = static(CurveBitSize[C])
macro canUseNoCarryMontyMul*(C: static Curve): untyped =
## Returns true if the Modulus is compatible with a fast
## Montgomery multiplication that avoids many carries
result = bindSym($C & "_CanUseNoCarryMontyMul")
macro canUseNoCarryMontySquare*(C: static Curve): untyped =
## Returns true if the Modulus is compatible with a fast
## Montgomery squaring that avoids many carries
result = bindSym($C & "_CanUseNoCarryMontySquare")
macro getR2modP*(C: static Curve): untyped =
## Get the Montgomery "R^2 mod P" constant associated to a curve field modulus
result = bindSym($C & "_R2modP")
macro getNegInvModWord*(C: static Curve): untyped =
## Get the Montgomery "-1/P[0] mod 2^WordBitSize" constant associated to a curve field modulus
result = bindSym($C & "_NegInvModWord")
macro getMontyOne*(C: static Curve): untyped =
## Get one in Montgomery representation (i.e. R mod P)
result = bindSym($C & "_MontyOne")
macro getInvModExponent*(C: static Curve): untyped =
## Get modular inversion exponent (Modulus-2 in canonical representation)
result = bindSym($C & "_InvModExponent")
macro getPrimePlus1div2*(C: static Curve): untyped =
## Get (P+1) / 2 for an odd prime
result = bindSym($C & "_PrimePlus1div2")
# ############################################################
#
# Debug info printed at compile-time
#
# ############################################################
macro debugConsts(): untyped =
let curves = bindSym("Curve")
let E = curves.getImpl[2]
result = newStmtList()
for i in 1 ..< E.len:
let curve = E[i]
let curveName = $curve
let modulus = bindSym(curveName & "_Modulus")
let r2modp = bindSym(curveName & "_R2modP")
let negInvModWord = bindSym(curveName & "_NegInvModWord")
result.add quote do:
echo "Curve ", `curveName`,':'
echo " Field Modulus: ", `modulus`
echo " Montgomery R² (mod P): ", `r2modp`
echo " Montgomery -1/P[0] (mod 2^", WordBitWidth, "): ", `negInvModWord`
result.add quote do:
echo "----------------------------------------------------------------------------"
# debug:
# debugConsts()