For finite fields, we will use the Montgomery n-residue form by default
This commit is contained in:
parent
f6b229b19c
commit
f418e08746
|
@ -27,6 +27,7 @@ func montyMagic(M: static BigInt): static Word {.inline.} =
|
|||
# Test vectors: https://www.researchgate.net/publication/4107322_Montgomery_modular_multiplication_architecture_for_public_key_cryptosystems
|
||||
# on p354
|
||||
# Reference C impl: http://www.hackersdelight.org/hdcodetxt/mont64.c.txt
|
||||
# Explanation: https://eprint.iacr.org/2017/1057.pdf
|
||||
|
||||
# ######################################################################
|
||||
# Implementation of modular multiplicative inverse
|
||||
|
|
|
@ -60,7 +60,7 @@ macro declareCurves*(curves: untyped): untyped =
|
|||
var curveModStmts = newStmtList()
|
||||
var curveModWhenStmt = nnkWhenStmt.newTree()
|
||||
|
||||
let Fp = ident"Fp"
|
||||
let Fq = ident"Fq"
|
||||
|
||||
for curveDesc in curves:
|
||||
curveDesc.expectKind(nnkCommand)
|
||||
|
@ -88,14 +88,14 @@ macro declareCurves*(curves: untyped): untyped =
|
|||
curve, bitSize
|
||||
)
|
||||
|
||||
# const BN254_Modulus = Fp[BN254](value: fromHex(BigInt[254], "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"))
|
||||
# const BN254_Modulus = Fq[BN254](value: fromHex(BigInt[254], "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"))
|
||||
let modulusID = ident($curve & "_Modulus")
|
||||
curveModStmts.add newConstStmt(
|
||||
modulusID,
|
||||
nnkObjConstr.newTree(
|
||||
nnkBracketExpr.newTree(Fp, curve),
|
||||
nnkBracketExpr.newTree(Fq, curve),
|
||||
nnkExprColonExpr.newTree(
|
||||
ident"value",
|
||||
ident"nres",
|
||||
newCall(
|
||||
bindSym"fromHex",
|
||||
nnkBracketExpr.newTree(bindSym"BigInt", bitSize),
|
||||
|
@ -146,13 +146,15 @@ macro declareCurves*(curves: untyped): untyped =
|
|||
)
|
||||
|
||||
# type
|
||||
# `Fp`*[C: static Curve] = object
|
||||
# `Fq`*[C: static Curve] = object
|
||||
# ## All operations on a field are modulo P
|
||||
# ## P being the prime modulus of the Curve C
|
||||
# value*: matchingBigInt(C)
|
||||
# ## Internally, data is stored in Montgomery n-residue form
|
||||
# ## with the magic constant chosen for convenient division (a power of 2 depending on P bitsize)
|
||||
# nres*: matchingBigInt(C)
|
||||
result.add nnkTypeSection.newTree(
|
||||
nnkTypeDef.newTree(
|
||||
nnkPostfix.newTree(ident"*", Fp),
|
||||
nnkPostfix.newTree(ident"*", Fq),
|
||||
nnkGenericParams.newTree(newIdentDefs(
|
||||
C, nnkStaticTy.newTree(Curve), newEmptyNode()
|
||||
)),
|
||||
|
@ -160,6 +162,10 @@ macro declareCurves*(curves: untyped): untyped =
|
|||
newEmptyNode(),
|
||||
newEmptyNode(),
|
||||
nnkRecList.newTree(
|
||||
nnkCommentStmt.newTree "All operations on a field are modulo P",
|
||||
nnkCommentStmt.newTree "P being the prime modulus of the Curve C",
|
||||
nnkCommentStmt.newTree "Internally, data is stored in Montgomery n-residue form",
|
||||
nnkCommentStmt.newTree "with the magic constant chosen for convenient division (a power of 2 depending on P bitsize)"
|
||||
newIdentDefs(
|
||||
nnkPostfix.newTree(ident"*", ident"value"),
|
||||
newCall(matchingBigInt, C)
|
||||
|
|
|
@ -8,12 +8,17 @@
|
|||
|
||||
# ############################################################
|
||||
#
|
||||
# Field arithmetic over Fp
|
||||
# Fq: Finite Field arithmetic over Q
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
# We assume that p is prime known at compile-time
|
||||
# We assume that p is not even (requirement for Montgomery form)
|
||||
# We assume that q is known at compile-time
|
||||
# We assume that q is not even:
|
||||
# - Operations are done in the Montgomery domain
|
||||
# - The Montgomery domain introduce a Montgomery constant that must be coprime
|
||||
# with the field modulus.
|
||||
# - The constant is chosen a power of 2
|
||||
# => to be coprime with a power of 2, q must be odd
|
||||
|
||||
import
|
||||
../primitives/constant_time,
|
||||
|
@ -21,16 +26,32 @@ import
|
|||
./bigints_checked
|
||||
|
||||
# type
|
||||
# Fp*[C: static Curve] = object
|
||||
# ## P is the prime modulus of the Curve C
|
||||
# `Fq`*[C: static Curve] = object
|
||||
# ## All operations on a field are modulo P
|
||||
# value*: BigInt[CurveBitSize[C]]
|
||||
export Fp # defined in ../config/curves to avoid recursive module dependencies
|
||||
# ## P being the prime modulus of the Curve C
|
||||
# ## Internally, data is stored in Montgomery n-residue form
|
||||
# ## with the magic constant chosen for convenient division (a power of 2 depending on P bitsize)
|
||||
# nres*: matchingBigInt(C)
|
||||
export Fq # defined in ../config/curves to avoid recursive module dependencies
|
||||
|
||||
debug:
|
||||
func `==`*(a, b: Fp): CTBool[Word] =
|
||||
func `==`*(a, b: Fq): CTBool[Word] =
|
||||
## Returns true if 2 big ints are equal
|
||||
a.value == b.value
|
||||
a.nres == b.nres
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [].}
|
||||
|
||||
func toMonty*[C: static Curve](a: Fq[C]): Montgomery[C] =
|
||||
## Convert a big integer over Fq to its montgomery representation
|
||||
## over Fq.
|
||||
## i.e. Does "a * (2^LimbSize)^W (mod p), where W is the number
|
||||
## of words needed to represent p in base 2^LimbSize
|
||||
|
||||
result = a
|
||||
for i in static(countdown(C.Mod.limbs.high, 1)):
|
||||
shiftAdd(result, 0)
|
||||
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
|
@ -38,7 +59,7 @@ debug:
|
|||
#
|
||||
# ############################################################
|
||||
|
||||
template add(a: var Fp, b: Fp, ctl: CTBool[Word]): CTBool[Word] =
|
||||
template add(a: var Fq, b: Fq, ctl: CTBool[Word]): CTBool[Word] =
|
||||
## Constant-time big integer in-place optional addition
|
||||
## The addition is only performed if ctl is "true"
|
||||
## The result carry is always computed.
|
||||
|
@ -47,7 +68,7 @@ template add(a: var Fp, b: Fp, ctl: CTBool[Word]): CTBool[Word] =
|
|||
## a and b MUST have the same announced bitlength (i.e. `bits` static parameters)
|
||||
add(a.value, b.value, ctl)
|
||||
|
||||
template sub(a: var Fp, b: Fp, ctl: CTBool[Word]): CTBool[Word] =
|
||||
template sub(a: var Fq, b: Fq, ctl: CTBool[Word]): CTBool[Word] =
|
||||
## Constant-time big integer in-place optional substraction
|
||||
## The substraction is only performed if ctl is "true"
|
||||
## The result carry is always computed.
|
||||
|
@ -65,13 +86,13 @@ template sub(a: var Fp, b: Fp, ctl: CTBool[Word]): CTBool[Word] =
|
|||
# No exceptions allowed
|
||||
{.push raises: [].}
|
||||
|
||||
func `+=`*(a: var Fp, b: Fp) =
|
||||
## Addition over Fp
|
||||
func `+=`*(a: var Fq, b: Fq) =
|
||||
## Addition over Fq
|
||||
var ctl = add(a, b, CtTrue)
|
||||
ctl = ctl or not sub(a, Fp.C.Mod, CtFalse)
|
||||
discard sub(a, Fp.C.Mod, ctl)
|
||||
ctl = ctl or not sub(a, Fq.C.Mod, CtFalse)
|
||||
discard sub(a, Fq.C.Mod, ctl)
|
||||
|
||||
func `-=`*(a: var Fp, b: Fp) =
|
||||
## Substraction over Fp
|
||||
func `-=`*(a: var Fq, b: Fq) =
|
||||
## Substraction over Fq
|
||||
let ctl = sub(a, b, CtTrue)
|
||||
discard add(a, Fp.C.Mod, ctl)
|
||||
discard add(a, Fq.C.Mod, ctl)
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
# 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.
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Compute the Montgomery Magic Number
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
import
|
||||
./primitives, ./bigints, ./primitives
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [].}
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Montgomery domain primitives
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [].}
|
||||
|
||||
func toMonty*[C: static Curve](a: Fp[C]): Montgomery[C] =
|
||||
## Convert a big integer over Fp to it's montgomery representation
|
||||
## over Fp.
|
||||
## i.e. Does "a * (2^LimbSize)^W (mod p), where W is the number
|
||||
## of words needed to represent p in base 2^LimbSize
|
||||
|
||||
result = a
|
||||
for i in static(countdown(C.Mod.limbs.high, 1)):
|
||||
shiftAdd(result, 0)
|
|
@ -1,7 +0,0 @@
|
|||
# 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.
|
|
@ -17,7 +17,7 @@ proc main() =
|
|||
suite "Basic arithmetic over finite fields":
|
||||
test "Addition mod 101":
|
||||
block:
|
||||
var x, y, z: Fp[Fake101]
|
||||
var x, y, z: Fq[Fake101]
|
||||
|
||||
x.fromUint(80'u32)
|
||||
y.fromUint(10'u32)
|
||||
|
@ -27,7 +27,7 @@ proc main() =
|
|||
check: bool(z == x)
|
||||
|
||||
block:
|
||||
var x, y, z: Fp[Fake101]
|
||||
var x, y, z: Fq[Fake101]
|
||||
|
||||
x.fromUint(80'u32)
|
||||
y.fromUint(21'u32)
|
||||
|
@ -37,7 +37,7 @@ proc main() =
|
|||
check: bool(z == x)
|
||||
|
||||
block:
|
||||
var x, y, z: Fp[Fake101]
|
||||
var x, y, z: Fq[Fake101]
|
||||
|
||||
x.fromUint(80'u32)
|
||||
y.fromUint(22'u32)
|
||||
|
@ -48,7 +48,7 @@ proc main() =
|
|||
|
||||
test "Substraction mod 101":
|
||||
block:
|
||||
var x, y, z: Fp[Fake101]
|
||||
var x, y, z: Fq[Fake101]
|
||||
|
||||
x.fromUint(80'u32)
|
||||
y.fromUint(10'u32)
|
||||
|
@ -58,7 +58,7 @@ proc main() =
|
|||
check: bool(z == x)
|
||||
|
||||
block:
|
||||
var x, y, z: Fp[Fake101]
|
||||
var x, y, z: Fq[Fake101]
|
||||
|
||||
x.fromUint(80'u32)
|
||||
y.fromUint(80'u32)
|
||||
|
@ -68,7 +68,7 @@ proc main() =
|
|||
check: bool(z == x)
|
||||
|
||||
block:
|
||||
var x, y, z: Fp[Fake101]
|
||||
var x, y, z: Fq[Fake101]
|
||||
|
||||
x.fromUint(80'u32)
|
||||
y.fromUint(81'u32)
|
||||
|
|
Loading…
Reference in New Issue