From d3ad4acb3acb4ec76da86a797415e09908df1bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mamy=20Andr=C3=A9-Ratsimbazafy?= Date: Sat, 15 Feb 2020 13:56:13 +0100 Subject: [PATCH] Do less in curve generator macro: - no more monty magic "negInvModWord" - no public "matchingBigInt" Improve comment on Montgomery procedures --- constantine/config/curves.nim | 10 +++------- constantine/config/curves_parser.nim | 28 +++------------------------- constantine/math/bigints_raw.nim | 13 +++++++++---- constantine/math/finite_fields.nim | 16 ++++++++++++---- constantine/math/precomputed.nim | 5 +++-- 5 files changed, 30 insertions(+), 42 deletions(-) diff --git a/constantine/config/curves.nim b/constantine/config/curves.nim index eb3aeb5..214f9ca 100644 --- a/constantine/config/curves.nim +++ b/constantine/config/curves.nim @@ -32,14 +32,10 @@ import # Barbulescu, R. and S. Duquesne, "Updating Key Size Estimations for Pairings", # Journal of Cryptology, DOI 10.1007/s00145-018-9280-5, January 2018. -# Generates: -# - type Curve = enum -# - const CurveBitSize: array[Curve, int] -# - proc Mod(curve: static Curve): auto +# Generates public: +# - type Curve* = enum +# - proc Mod*(curve: static Curve): auto # 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): declareCurves: # Barreto-Naehrig curve, pairing-friendly, Prime 254 bit, ~100-bit security diff --git a/constantine/config/curves_parser.nim b/constantine/config/curves_parser.nim index 9f6ad66..0fa15bc 100644 --- a/constantine/config/curves_parser.nim +++ b/constantine/config/curves_parser.nim @@ -127,7 +127,7 @@ macro declareCurves*(curves: untyped): untyped = pure = false ) - # const CurveBitSize*: array[Curve, int] = ... + # const CurveBitSize: array[Curve, int] = ... let cbs = ident("CurveBitSize") result.add newConstStmt( cbs, CurveBitSize @@ -137,9 +137,9 @@ macro declareCurves*(curves: untyped): untyped = # template matchingBigInt(C: static Curve): untyped = # BigInt[CurveBitSize[C]] let C = ident"C" - let matchingBigInt = ident"matchingBigInt" + let matchingBigInt = genSym(nskTemplate, "matchingBigInt") result.add newProc( - name = nnkPostFix.newTree(ident"*", matchingBigInt), + name = matchingBigInt, params = [ident"untyped", newIdentDefs(C, nnkStaticTy.newTree(Curve))], body = nnkBracketExpr.newTree(bindSym"BigInt", nnkBracketExpr.newTree(cbs, C)), procType = nnkTemplateDef @@ -198,26 +198,4 @@ macro declareCurves*(curves: untyped): untyped = 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() diff --git a/constantine/math/bigints_raw.nim b/constantine/math/bigints_raw.nim index 94572f9..309fd27 100644 --- a/constantine/math/bigints_raw.nim +++ b/constantine/math/bigints_raw.nim @@ -396,8 +396,11 @@ func reduce*(r: BigIntViewMut, a: BigIntViewAny, M: BigIntViewConst) = func montgomeryResidue*(a: BigIntViewMut, N: BigIntViewConst) = ## Transform a bigint ``a`` from it's natural representation (mod N) ## 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 ## `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) ## to the regular natural representation (mod N) ## - ## i.e. Does "a * ((2^LimbSize)^W)^-1 (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^-1 (mod N)" ## ## This is called a Montgomery Reduction ## The Montgomery Magic Constant is µ = -1/N mod N diff --git a/constantine/math/finite_fields.nim b/constantine/math/finite_fields.nim index 1cd8727..8e69871 100644 --- a/constantine/math/finite_fields.nim +++ b/constantine/math/finite_fields.nim @@ -23,7 +23,7 @@ import ../primitives/constant_time, ../config/[common, curves], - ./bigints_checked + ./bigints_checked, ./precomputed # type # `Fq`*[C: static Curve] = object @@ -54,10 +54,10 @@ func fromBig*(T: type Fq, src: BigInt): T = result.nres = src 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 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 # # ############################################################ +# +# 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) = ## Addition over Fq @@ -107,4 +115,4 @@ func `*`*(a, b: Fq): Fq {.noInit.} = ## as Fq elements are usually large and this ## routine will zero init internally the result. 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()) diff --git a/constantine/math/precomputed.nim b/constantine/math/precomputed.nim index 6b88974..1a5c8a5 100644 --- a/constantine/math/precomputed.nim +++ b/constantine/math/precomputed.nim @@ -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 = ## 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 must be odd and greater than 2. # We use BaseType for return value because static distinct type