Do less in curve generator macro:

- no more monty magic "negInvModWord"
- no public "matchingBigInt"

Improve comment on Montgomery procedures
This commit is contained in:
Mamy André-Ratsimbazafy 2020-02-15 13:56:13 +01:00
parent 398b871c4f
commit d3ad4acb3a
No known key found for this signature in database
GPG Key ID: 7B88AD1FE79492E1
5 changed files with 30 additions and 42 deletions

View File

@ -32,14 +32,10 @@ import
# Barbulescu, R. and S. Duquesne, "Updating Key Size Estimations for Pairings", # Barbulescu, R. and S. Duquesne, "Updating Key Size Estimations for Pairings",
# Journal of Cryptology, DOI 10.1007/s00145-018-9280-5, January 2018. # Journal of Cryptology, DOI 10.1007/s00145-018-9280-5, January 2018.
# Generates: # Generates public:
# - type Curve = enum # - type Curve* = enum
# - const CurveBitSize: array[Curve, int] # - proc Mod*(curve: static Curve): auto
# - proc Mod(curve: static Curve): auto
# which returns the field modulus of the curve # which returns the field modulus of the curve
# - proc negInvModWord(curve: static Curve): static Word =
# which returns the Montgomery magic constant
# associated with the curve modulus
when not defined(testingCurves): when not defined(testingCurves):
declareCurves: declareCurves:
# Barreto-Naehrig curve, pairing-friendly, Prime 254 bit, ~100-bit security # Barreto-Naehrig curve, pairing-friendly, Prime 254 bit, ~100-bit security

View File

@ -127,7 +127,7 @@ macro declareCurves*(curves: untyped): untyped =
pure = false pure = false
) )
# const CurveBitSize*: array[Curve, int] = ... # const CurveBitSize: array[Curve, int] = ...
let cbs = ident("CurveBitSize") let cbs = ident("CurveBitSize")
result.add newConstStmt( result.add newConstStmt(
cbs, CurveBitSize cbs, CurveBitSize
@ -137,9 +137,9 @@ macro declareCurves*(curves: untyped): untyped =
# template matchingBigInt(C: static Curve): untyped = # template matchingBigInt(C: static Curve): untyped =
# BigInt[CurveBitSize[C]] # BigInt[CurveBitSize[C]]
let C = ident"C" let C = ident"C"
let matchingBigInt = ident"matchingBigInt" let matchingBigInt = genSym(nskTemplate, "matchingBigInt")
result.add newProc( result.add newProc(
name = nnkPostFix.newTree(ident"*", matchingBigInt), name = matchingBigInt,
params = [ident"untyped", newIdentDefs(C, nnkStaticTy.newTree(Curve))], params = [ident"untyped", newIdentDefs(C, nnkStaticTy.newTree(Curve))],
body = nnkBracketExpr.newTree(bindSym"BigInt", nnkBracketExpr.newTree(cbs, C)), body = nnkBracketExpr.newTree(bindSym"BigInt", nnkBracketExpr.newTree(cbs, C)),
procType = nnkTemplateDef procType = nnkTemplateDef
@ -198,26 +198,4 @@ macro declareCurves*(curves: untyped): untyped =
procType = nnkFuncDef procType = nnkFuncDef
) )
# proc negInvModWord(curve: static Curve): static Word
result.add newProc(
name = nnkPostfix.newTree(ident"*", ident"negInvModWord"),
params = [
ident"auto",
newIdentDefs(
name = ident"curve",
kind = nnkStaticTy.newTree(ident"Curve")
)
],
body = newCall(
ident"negInvModWord",
# curve.Mod().nres
nnkDotExpr.newTree(
newCall(ident"Mod", ident"curve"),
ident"nres"
)
),
procType = nnkFuncDef
)
# echo result.toStrLit() # echo result.toStrLit()

View File

@ -396,8 +396,11 @@ func reduce*(r: BigIntViewMut, a: BigIntViewAny, M: BigIntViewConst) =
func montgomeryResidue*(a: BigIntViewMut, N: BigIntViewConst) = func montgomeryResidue*(a: BigIntViewMut, N: BigIntViewConst) =
## Transform a bigint ``a`` from it's natural representation (mod N) ## Transform a bigint ``a`` from it's natural representation (mod N)
## to a the Montgomery n-residue representation ## to a the Montgomery n-residue representation
## i.e. Does "a * (2^LimbSize)^W (mod N), where W is the number ##
## of words needed to represent n in base 2^LimbSize ## with W = N.numLimbs()
## and R = (2^WordBitSize)^W
##
## Does "a * R (mod N)"
## ##
## `a`: The source BigInt in the natural representation. `a` in [0, N) range ## `a`: The source BigInt in the natural representation. `a` in [0, N) range
## `N`: The field modulus. N must be odd. ## `N`: The field modulus. N must be odd.
@ -419,8 +422,10 @@ func redc*(a: BigIntViewMut, N: BigIntViewConst, negInvModWord: Word) =
## Transform a bigint ``a`` from it's Montgomery N-residue representation (mod N) ## Transform a bigint ``a`` from it's Montgomery N-residue representation (mod N)
## to the regular natural representation (mod N) ## to the regular natural representation (mod N)
## ##
## i.e. Does "a * ((2^LimbSize)^W)^-1 (mod N), where W is the number ## with W = N.numLimbs()
## of words needed to represent n in base 2^LimbSize ## and R = (2^WordBitSize)^W
##
## Does "a * R^-1 (mod N)"
## ##
## This is called a Montgomery Reduction ## This is called a Montgomery Reduction
## The Montgomery Magic Constant is µ = -1/N mod N ## The Montgomery Magic Constant is µ = -1/N mod N

View File

@ -23,7 +23,7 @@
import import
../primitives/constant_time, ../primitives/constant_time,
../config/[common, curves], ../config/[common, curves],
./bigints_checked ./bigints_checked, ./precomputed
# type # type
# `Fq`*[C: static Curve] = object # `Fq`*[C: static Curve] = object
@ -54,10 +54,10 @@ func fromBig*(T: type Fq, src: BigInt): T =
result.nres = src result.nres = src
result.nres.unsafeMontgomeryResidue(Fq.C.Mod) result.nres.unsafeMontgomeryResidue(Fq.C.Mod)
func toBig*[C: static Curve](src: Fq[C]): auto = func toBig*(src: Fq): auto =
## Convert a finite-field element to a BigInt in natral representation ## Convert a finite-field element to a BigInt in natral representation
result = src.nres result = src.nres
result.unsafeRedC(C.Mod.nres, negInvModWord(C)) result.unsafeRedC(Fq.C.Mod.nres, Fq.C.Mod.nres.negInvModWord())
# ############################################################ # ############################################################
# #
@ -88,6 +88,14 @@ template sub(a: var Fq, b: Fq, ctl: CTBool[Word]): CTBool[Word] =
# Field arithmetic primitives # Field arithmetic primitives
# #
# ############################################################ # ############################################################
#
# Note: the library currently implements generic routine for odd field modulus.
# Routines for special field modulus form:
# - Mersenne Prime (2^k - 1),
# - Generalized Mersenne Prime (NIST Prime P256: 2^256 - 2^224 + 2^192 + 2^96 - 1)
# - Pseudo-Mersenne Prime (2^m - k for example Curve25519: 2^255 - 19)
# - Golden Primes (φ^2 - φ - 1 with φ = 2^k for example Ed448-Goldilocks: 2^448 - 2^224 - 1)
# exist and can be implemented with compile-time specialization.
func `+=`*(a: var Fq, b: Fq) = func `+=`*(a: var Fq, b: Fq) =
## Addition over Fq ## Addition over Fq
@ -107,4 +115,4 @@ func `*`*(a, b: Fq): Fq {.noInit.} =
## as Fq elements are usually large and this ## as Fq elements are usually large and this
## routine will zero init internally the result. ## routine will zero init internally the result.
result.nres.setInternalBitLength() result.nres.setInternalBitLength()
result.nres.montyMul(a.nres, b.nres, Fq.C.Mod.nres, negInvModWord(Fq.C)) result.nres.montyMul(a.nres, b.nres, Fq.C.Mod.nres, Fq.C.Mod.nres.negInvModWord())

View File

@ -20,10 +20,11 @@ import
# #
# ############################################################ # ############################################################
# Note: The declareCurve macro builds an exported negInvModWord*(C: static Curve) on top of the one below
func negInvModWord*(M: BigInt): BaseType = func negInvModWord*(M: BigInt): BaseType =
## Returns the Montgomery domain magic constant for the input modulus: ## Returns the Montgomery domain magic constant for the input modulus:
## -1/M[0] mod LimbSize ##
## µ = -1/M[0] mod M
##
## M[0] is the least significant limb of M ## M[0] is the least significant limb of M
## M must be odd and greater than 2. ## M must be odd and greater than 2.
# We use BaseType for return value because static distinct type # We use BaseType for return value because static distinct type