mirror of
https://github.com/status-im/constantine.git
synced 2025-02-23 17:38:09 +00:00
reorganize the repo
This commit is contained in:
parent
28c9c472b3
commit
fe59efb8d8
42
README.md
42
README.md
@ -1,13 +1,13 @@
|
||||
# Constantine - Constant time finite field primitives for Elliptic Curve Cryptography
|
||||
# Constantine - Constant Time Elliptic Curve Cryptography
|
||||
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||

|
||||
|
||||
This library provides constant time finite field primitives for implementation of elliptic curve cryptography.
|
||||
This library provides constant-time implementation of elliptic curve cryptography.
|
||||
|
||||
Warning ⚠️: The library is in development state and cannot be used at the moment
|
||||
except as a showcase or to start a discussion on modular big integers internals.
|
||||
> Warning ⚠️: The library is in development state and cannot be used at the moment
|
||||
> except as a showcase or to start a discussion on modular big integers internals.
|
||||
|
||||
## Installation
|
||||
|
||||
@ -16,6 +16,40 @@ You can install the developement version of the library through nimble with the
|
||||
nimble install https://github.com/mratsim/constantine@#master
|
||||
```
|
||||
|
||||
## Target audience
|
||||
|
||||
The library aims to be a portable, compact and hardened library for elliptic curve cryptography needs, in particular for blockchain protocols and zero-knowledge proofs system.
|
||||
|
||||
The library focuses on following properties:
|
||||
- constant-time (not leaking secret data via side-channels)
|
||||
- generated code size, datatype size and stack usage
|
||||
- performance
|
||||
in this order
|
||||
|
||||
## Security
|
||||
|
||||
Hardening an implementation against all existing and upcoming attack vectors is an extremely complex task.
|
||||
The library is provided as is, without any guarantees at least until:
|
||||
- it gets audited
|
||||
- formal proofs of correctness are produced
|
||||
- formal verification of constant-time implementation is possible
|
||||
|
||||
Defense against common attack vectors are provided on a best effort basis
|
||||
attackers may go to great lengths to retrieve secret data including:
|
||||
- Timing the time taken to multiply on an elliptic curve
|
||||
- Analysing the power usage of embedded devices
|
||||
- Detecting cache misses when using lookup tables
|
||||
- Memory attacks like page-faults, allocators, memory retention attacks
|
||||
|
||||
This is would be incomplete without mentioning that the hardware, OS and compiler
|
||||
actively hinder you by:
|
||||
- Hardware: sometimes not implementing multiplication in constant-time.
|
||||
- OS: not providing a way to prevent memory paging to disk, core dumps, a debugger attaching to your process or a context switch (coroutines) leaking register data.
|
||||
- Compiler: optimizing away your carefully crafted branchless code and leaking server secrets or optimizing away your secure erasure routine which is "useless" because at the end of the function the data is not used anymore.
|
||||
|
||||
A growing number of attack vectors is being collected for your viewing pleasure
|
||||
at https://github.com/mratsim/constantine/wiki/Constant-time-arithmetics
|
||||
|
||||
## License
|
||||
|
||||
Licensed and distributed under either of
|
||||
|
@ -1,54 +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.
|
||||
|
||||
import
|
||||
./bigints_raw,
|
||||
./primitives
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# BigInts Public API
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
# The "public" API, exported for finite field computations
|
||||
# enforced compile-time checking of BigInt bitsize
|
||||
#
|
||||
# The "raw" compute API, uses views to avoid code duplication due to generic/static monomorphization.
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [].}
|
||||
{.push inline.}
|
||||
|
||||
func isZero*(a: BigInt): CTBool[Word] =
|
||||
## Returns true if a big int is equal to zero
|
||||
a.view.isZero
|
||||
|
||||
func add*[bits](a: var BigInt[bits], b: BigInt[bits], 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.
|
||||
add(a.view, b.view, ctl)
|
||||
|
||||
func sub*[bits](a: var BigInt[bits], b: BigInt[bits], 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.
|
||||
sub(a.view, b.view, ctl)
|
||||
|
||||
func reduce*[aBits, mBits](r: var BigInt[mBits], a: BigInt[aBits], M: BigInt[mBits]) =
|
||||
## Reduce `a` modulo `M` and store the result in `r`
|
||||
##
|
||||
## The modulus `M` **must** use `mBits` bits (bits at position mBits-1 must be set)
|
||||
##
|
||||
## CT: Depends only on the length of the modulus `M`
|
||||
|
||||
# Note: for all cryptographic intents and purposes the modulus is known at compile-time
|
||||
# but we don't want to inline it as it would increase codesize, better have Nim
|
||||
# pass a pointer+length to a fixed session of the BSS.
|
||||
reduce(r.view, a.view, M.view)
|
48
constantine/config/common.nim
Normal file
48
constantine/config/common.nim
Normal file
@ -0,0 +1,48 @@
|
||||
# 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.
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Common configuration
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
import ../primitives/constant_time
|
||||
|
||||
type Word* = Ct[uint32]
|
||||
## Logical BigInt word
|
||||
## A logical BigInt word is of size physical MachineWord-1
|
||||
type DoubleWord* = Ct[uint64]
|
||||
|
||||
type BaseType* = uint32
|
||||
## Physical BigInt for conversion in "normal integers"
|
||||
|
||||
const
|
||||
WordPhysBitSize* = sizeof(Word) * 8
|
||||
WordBitSize* = WordPhysBitSize - 1
|
||||
|
||||
CtTrue* = ctrue(Word)
|
||||
CtFalse* = cfalse(Word)
|
||||
|
||||
Zero* = Word(0)
|
||||
One* = Word(1)
|
||||
MaxWord* = (not Zero) shr 1
|
||||
## This represents 0x7F_FF_FF_FF__FF_FF_FF_FF
|
||||
## also 0b0111...1111
|
||||
## This biggest representable number in our limbs.
|
||||
## i.e. The most significant bit is never set at the end of each function
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Instrumentation
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
template debug*(body: untyped): untyped =
|
||||
when defined(debugConstantine):
|
||||
body
|
7
constantine/elliptic/README.md
Normal file
7
constantine/elliptic/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Elliptic Curves
|
||||
|
||||
This folder will hold the implementation of elliptic curves.
|
||||
|
||||
## References
|
||||
|
||||
- Pairing-Friendly Curves https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-00#section-2.1
|
1
constantine/io/README.md
Normal file
1
constantine/io/README.md
Normal file
@ -0,0 +1 @@
|
||||
# I/O and serialization
|
@ -12,7 +12,9 @@
|
||||
|
||||
import
|
||||
endians,
|
||||
./primitives, ./bigints_raw
|
||||
../primitives/constant_time,
|
||||
../math/bigints_checked,
|
||||
../config/common
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
@ -133,7 +135,7 @@ func dumpRawUintLE(
|
||||
|
||||
var tail = dst.len
|
||||
while tail > 0:
|
||||
let w = if src_idx < src.limbs.len: src.limbs[src_idx].BaseType
|
||||
let w = if src_idx < src.limbs.len: BaseType(src.limbs[src_idx])
|
||||
else: 0
|
||||
inc src_idx
|
||||
|
5
constantine/math/README.md
Normal file
5
constantine/math/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# BigInt and Finite Field Arithmetic
|
||||
|
||||
This folder contains the implementation of
|
||||
- big integer
|
||||
- finite field arithmetic (i.e. modular arithmetic)
|
112
constantine/math/bigints_checked.nim
Normal file
112
constantine/math/bigints_checked.nim
Normal file
@ -0,0 +1,112 @@
|
||||
# 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
|
||||
./bigints_raw,
|
||||
../primitives/constant_time,
|
||||
../config/common
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# BigInts type-checked API
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
# The "checked" API is exported as a building blocks
|
||||
# with enforced compile-time checking of BigInt bitsize
|
||||
# and memory ownership.
|
||||
#
|
||||
# The "raw" compute API uses views to avoid code duplication
|
||||
# due to generic/static monomorphization.
|
||||
#
|
||||
# The "checked" API is a thin wrapper above the "raw" API to get the best of both world:
|
||||
# - small code footprint
|
||||
# - compiler enforced checks: types, bitsizes (dependant types)
|
||||
# - compiler enforced memory: stack allocation and buffer ownership
|
||||
|
||||
func wordsRequired(bits: int): int {.compileTime.} =
|
||||
## Compute the number of limbs required
|
||||
# from the **announced** bit length
|
||||
(bits + WordBitSize - 1) div WordBitSize
|
||||
|
||||
type
|
||||
BigInt*[bits: static int] = object
|
||||
## Fixed-precision big integer
|
||||
##
|
||||
## - "bits" is the announced bit-length of the BigInt
|
||||
## This is public data, usually equal to the curve prime bitlength.
|
||||
##
|
||||
## - "bitLength" is the internal bitlength of the integer
|
||||
## This differs from the canonical bit-length as
|
||||
## Constantine word-size is smaller than a machine word.
|
||||
## This value should never be used as-is to prevent leaking secret data.
|
||||
## Computing this value requires constant-time operations.
|
||||
## Using this value requires converting it to the # of limbs in constant-time
|
||||
##
|
||||
## - "limbs" is an internal field that holds the internal representation
|
||||
## of the big integer. Least-significant limb first. Within limbs words are native-endian.
|
||||
##
|
||||
## This internal representation can be changed
|
||||
## without notice and should not be used by external applications or libraries.
|
||||
bitLength: uint32
|
||||
limbs*: array[bits.wordsRequired, Word]
|
||||
|
||||
template view*(a: BigInt): BigIntViewConst =
|
||||
## Returns a borrowed type-erased immutable view to a bigint
|
||||
BigIntViewConst(cast[BigIntView](a.unsafeAddr))
|
||||
|
||||
template view*(a: var BigInt): BigIntViewMut =
|
||||
## Returns a borrowed type-erased mutable view to a mutable bigint
|
||||
BigIntViewMut(cast[BigIntView](a.addr))
|
||||
|
||||
debug:
|
||||
func `==`*(a, b: BigInt): CTBool[Word] =
|
||||
## Returns true if 2 big ints are equal
|
||||
var accum: Word
|
||||
for i in static(0 ..< a.limbs.len):
|
||||
accum = accum or (a.limbs[i] xor b.limbs[i])
|
||||
result = accum.isZero
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [].}
|
||||
{.push inline.}
|
||||
|
||||
func setInternalBitLength*(a: var BigInt) {.inline.} =
|
||||
## Derive the actual bitsize used internally of a BigInt
|
||||
## from the announced BigInt bitsize
|
||||
## and set the bitLength field of that BigInt
|
||||
## to that computed value.
|
||||
a.bitLength = static(a.bits + a.bits div WordBitSize)
|
||||
|
||||
func isZero*(a: BigInt): CTBool[Word] =
|
||||
## Returns true if a big int is equal to zero
|
||||
a.view.isZero
|
||||
|
||||
func add*[bits](a: var BigInt[bits], b: BigInt[bits], 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.
|
||||
add(a.view, b.view, ctl)
|
||||
|
||||
func sub*[bits](a: var BigInt[bits], b: BigInt[bits], 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.
|
||||
sub(a.view, b.view, ctl)
|
||||
|
||||
func reduce*[aBits, mBits](r: var BigInt[mBits], a: BigInt[aBits], M: BigInt[mBits]) =
|
||||
## Reduce `a` modulo `M` and store the result in `r`
|
||||
##
|
||||
## The modulus `M` **must** use `mBits` bits (bits at position mBits-1 must be set)
|
||||
##
|
||||
## CT: Depends only on the length of the modulus `M`
|
||||
|
||||
# Note: for all cryptographic intents and purposes the modulus is known at compile-time
|
||||
# but we don't want to inline it as it would increase codesize, better have Nim
|
||||
# pass a pointer+length to a fixed session of the BSS.
|
||||
reduce(r.view, a.view, M.view)
|
@ -50,58 +50,30 @@
|
||||
# actual computation is deferred to type-erased routines.
|
||||
|
||||
import
|
||||
./primitives, ./common,
|
||||
./primitives_extprecision
|
||||
../primitives/constant_time,
|
||||
../primitives/extended_precision,
|
||||
../config/common
|
||||
from sugar import distinctBase
|
||||
|
||||
type Word* = Ct[uint32]
|
||||
## Logical BigInt word
|
||||
## A logical BigInt word is of size physical MachineWord-1
|
||||
type DoubleWord = Ct[uint64]
|
||||
# ############################################################
|
||||
#
|
||||
# BigInts type-erased API
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
type BaseType* = uint32
|
||||
## Physical BigInt for conversion in "normal integers"
|
||||
|
||||
const
|
||||
WordPhysBitSize = sizeof(Word) * 8
|
||||
WordBitSize* = WordPhysBitSize - 1
|
||||
|
||||
const
|
||||
Zero* = Word(0)
|
||||
One* = Word(1)
|
||||
MaxWord* = (not Zero) shr 1
|
||||
## This represents 0x7F_FF_FF_FF__FF_FF_FF_FF
|
||||
## also 0b0111...1111
|
||||
## This biggest representable number in our limbs.
|
||||
## i.e. The most significant bit is never set at the end of each function
|
||||
|
||||
func wordsRequired(bits: int): int {.compileTime.} =
|
||||
## Compute the number of limbs required
|
||||
# from the **announced** bit length
|
||||
(bits + WordBitSize - 1) div WordBitSize
|
||||
# The "checked" API is exported as a building blocks
|
||||
# with enforced compile-time checking of BigInt bitsize
|
||||
# and memory ownership.
|
||||
#
|
||||
# The "raw" compute API uses views to avoid code duplication
|
||||
# due to generic/static monomorphization.
|
||||
#
|
||||
# The "checked" API is a thin wrapper above the "raw" API to get the best of both world:
|
||||
# - small code footprint
|
||||
# - compiler enforced checks: types, bitsizes
|
||||
# - compiler enforced memory: stack allocation and buffer ownership
|
||||
|
||||
type
|
||||
BigInt*[bits: static int] = object
|
||||
## Fixed-precision big integer
|
||||
##
|
||||
## - "bits" is the announced bit-length of the BigInt
|
||||
## This is public data, usually equal to the curve prime bitlength.
|
||||
##
|
||||
## - "bitLength" is the internal bitlength of the integer
|
||||
## This differs from the canonical bit-length as
|
||||
## Constantine word-size is smaller than a machine word.
|
||||
## This value should never be used as-is to prevent leaking secret data.
|
||||
## Computing this value requires constant-time operations.
|
||||
## Using this value requires converting it to the # of limbs in constant-time
|
||||
##
|
||||
## - "limbs" is an internal field that holds the internal representation
|
||||
## of the big integer. Least-significant limb first. Within limbs words are native-endian.
|
||||
##
|
||||
## This internal representation can be changed
|
||||
## without notice and should not be used by external applications or libraries.
|
||||
bitLength: uint32
|
||||
limbs*: array[bits.wordsRequired, Word]
|
||||
|
||||
BigIntView* = ptr object
|
||||
## Type-erased fixed-precision big integer
|
||||
##
|
||||
@ -145,18 +117,10 @@ type
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Mutability safety
|
||||
# Deep Mutability safety
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
template view*(a: BigInt): BigIntViewConst =
|
||||
## Returns a borrowed type-erased immutable view to a bigint
|
||||
BigIntViewConst(cast[BigIntView](a.unsafeAddr))
|
||||
|
||||
template view*(a: var BigInt): BigIntViewMut =
|
||||
## Returns a borrowed type-erased mutable view to a mutable bigint
|
||||
BigIntViewMut(cast[BigIntView](a.addr))
|
||||
|
||||
template `[]`*(v: BigIntViewConst, limbIdx: int): Word =
|
||||
distinctBase(type v)(v).limbs[limbIdx]
|
||||
|
||||
@ -181,13 +145,13 @@ template setBitLength(v: BigIntViewMut, internalBitLength: uint32) =
|
||||
# TODO: Check if repeated v.numLimbs calls are optimized away
|
||||
|
||||
template `[]`*(v: BigIntViewConst, limbIdxFromEnd: BackwardsIndex): Word =
|
||||
distinctBase(type v)(v).limbs[v.numLimbs.int - int limbIdxFromEnd]
|
||||
distinctBase(type v)(v).limbs[numLimbs(v).int - int limbIdxFromEnd]
|
||||
|
||||
template `[]`*(v: BigIntViewMut, limbIdxFromEnd: BackwardsIndex): var Word =
|
||||
distinctBase(type v)(v).limbs[v.numLimbs.int - int limbIdxFromEnd]
|
||||
distinctBase(type v)(v).limbs[numLimbs(v).int - int limbIdxFromEnd]
|
||||
|
||||
template `[]=`*(v: BigIntViewMut, limbIdxFromEnd: BackwardsIndex, val: Word) =
|
||||
distinctBase(type v)(v).limbs[v.numLimbs.int - int limbIdxFromEnd] = val
|
||||
distinctBase(type v)(v).limbs[numLimbs(v).int - int limbIdxFromEnd] = val
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
@ -214,13 +178,6 @@ template checkValidModulus(m: BigIntViewConst) =
|
||||
assert not m[^1].isZero.bool, "Internal Error: the modulus must use all declared bits"
|
||||
|
||||
debug:
|
||||
func `==`*(a, b: BigInt): CTBool[Word] =
|
||||
## Returns true if 2 big ints are equal
|
||||
var accum: Word
|
||||
for i in static(0 ..< a.limbs.len):
|
||||
accum = accum or (a.limbs[i] xor b.limbs[i])
|
||||
result = accum.isZero
|
||||
|
||||
func `$`*(a: BigIntViewAny): string =
|
||||
let len = a.numLimbs()
|
||||
result = "["
|
||||
@ -238,13 +195,6 @@ debug:
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
func setInternalBitLength*(a: var BigInt) {.inline.} =
|
||||
## Derive the actual bitsize used internally of a BigInt
|
||||
## from the announced BigInt bitsize
|
||||
## and set the bitLength field of that BigInt
|
||||
## to that computed value.
|
||||
a.bitLength = static(a.bits + a.bits div WordBitSize)
|
||||
|
||||
func isZero*(a: BigIntViewAny): CTBool[Word] =
|
||||
## Returns true if a big int is equal to zero
|
||||
var accum: Word
|
||||
@ -353,7 +303,7 @@ func shlAddMod(a: BigIntViewMut, c: Word, M: BigIntViewConst) =
|
||||
|
||||
# Now substract a*2^63 - q*p
|
||||
var carry = Zero
|
||||
var over_p = ctrue(Word) # Track if quotient greater than the modulus
|
||||
var over_p = CtTrue # Track if quotient greater than the modulus
|
||||
|
||||
for i in 0 ..< M.numLimbs():
|
||||
var qp_lo: Word
|
@ -13,6 +13,7 @@
|
||||
# ############################################################
|
||||
|
||||
# We assume that p is prime known at compile-time
|
||||
# We assume that p is not even (requirement for Montgomery form)
|
||||
|
||||
import ./primitives, ./bigints, ./curves_config
|
||||
|
||||
@ -22,22 +23,12 @@ type
|
||||
## All operations on a field are modulo P
|
||||
value: BigInt[CurveBitSize[C]]
|
||||
|
||||
Montgomery*[C: static Curve] = object
|
||||
## P is the prime modulus of the Curve C
|
||||
## All operations in the Montgomery domain are modulo P
|
||||
## P **must** be odd
|
||||
value: BigInt[CurveBitSize[C]]
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Aliases
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
const
|
||||
CtTrue* = ctrue(Word)
|
||||
CtFalse* = cfalse(Word)
|
||||
|
||||
template add(a: var Fp, b: Fp, ctl: CTBool[Word]): CTBool[Word] =
|
||||
add(a.value, b.value, ctl)
|
||||
|
@ -13,17 +13,13 @@
|
||||
# ############################################################
|
||||
|
||||
import
|
||||
./primitives, ./bigints
|
||||
|
||||
from bitops import fastLog2
|
||||
# This will only be used at compile-time
|
||||
# so no constant-time worries (it is constant-time if using the De Bruijn multiplication)
|
||||
./primitives, ./bigints, ./primitives
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [].}
|
||||
|
||||
func montyMagic*(M: static BigInt): static Word {.inline.} =
|
||||
## Returns the Montgomery domain magic number for the input modulus:
|
||||
## Returns the Montgomery domain magic constant for the input modulus:
|
||||
## -1/M[0] mod LimbSize
|
||||
## M[0] is the least significant limb of M
|
||||
## M must be odd and greater than 2.
|
||||
@ -67,8 +63,27 @@ func montyMagic*(M: static BigInt): static Word {.inline.} =
|
||||
|
||||
const
|
||||
M0 = M.limbs[0]
|
||||
k = fastLog2(WordBitSize)
|
||||
k = log2(WordBitSize)
|
||||
|
||||
result = M0 # Start from an inverse of M0 modulo 2, M0 is odd and it's own inverse
|
||||
for _ in static(0 ..< k):
|
||||
result *= 2 + M * result # x' = x(2 + ax) (`+` to avoid negating at the end)
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# 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)
|
@ -5,9 +5,3 @@
|
||||
# * 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.
|
||||
|
||||
# Common configuration
|
||||
|
||||
template debug*(body: untyped): untyped =
|
||||
when defined(debugConstantine):
|
||||
body
|
@ -1,29 +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.
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Montgomery domain primitives
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
import
|
||||
./primitives, ./bigints, ./field_fp, ./curves_config
|
||||
|
||||
# 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)
|
3
constantine/primitives/README.md
Normal file
3
constantine/primitives/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Constant-time primitives
|
||||
|
||||
This folder holds the constant-time primitives
|
@ -12,7 +12,7 @@
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
import ./primitives
|
||||
import ./constant_time
|
||||
|
||||
func asm_x86_64_extMul(hi, lo: var uint64, a, b: uint64) {.inline.}=
|
||||
## Extended precision multiplication uint64 * uint64 --> uint128
|
||||
@ -115,6 +115,9 @@ func unsafeDiv2n1n*(q, r: var Ct[uint64], n_hi, n_lo, d: Ct[uint64]) {.inline.}=
|
||||
# with a fast path that may have branches. It might also
|
||||
# be the same at the hardware level.
|
||||
|
||||
# TODO !!! - Replace by constant-time, portable, non-assembly version
|
||||
# -> use uint128? Compiler might add unwanted branches
|
||||
|
||||
type T = uint64
|
||||
|
||||
when not defined(amd64):
|
||||
@ -131,6 +134,8 @@ func unsafeDiv2n1n*(q, r: var Ct[uint32], n_hi, n_lo, d: Ct[uint32]) {.inline.}=
|
||||
## To avoid issues, n_hi, n_lo, d should be normalized.
|
||||
## i.e. shifted (== multiplied by the same power of 2)
|
||||
## so that the most significant bit in d is set.
|
||||
# TODO !!! - Replace by constant-time, portable, non-assembly version
|
||||
# -> use uint128? Compiler might add unwanted branches
|
||||
let dividend = (uint64(n_hi) shl 32) or uint64(n_lo)
|
||||
let divisor = uint64(d)
|
||||
q = (Ct[uint32])(dividend div divisor)
|
16
constantine/signatures/README.md
Normal file
16
constantine/signatures/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Signature schemes
|
||||
|
||||
This folder will hold the implementations of signature schemes.
|
||||
|
||||
In particular:
|
||||
- BLS (Boneh-Lynn-Shacham)
|
||||
- ECDSA (Elliptic Curve Digital Signature Algorithm)
|
||||
|
||||
Note: The BLS signature scheme should not be confused
|
||||
with the BLS family of elliptic curve (Barreto-Lynn-Scott)
|
||||
|
||||
## References
|
||||
|
||||
### ECDSA
|
||||
|
||||
-
|
@ -7,7 +7,10 @@
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import unittest, random, strutils,
|
||||
../constantine/[io, bigints_public, bigints_raw, primitives]
|
||||
../constantine/io/io,
|
||||
../constantine/math/bigints_checked,
|
||||
../constantine/config/common,
|
||||
../constantine/primitives/constant_time
|
||||
|
||||
suite "isZero":
|
||||
test "isZero for zero":
|
||||
|
@ -10,7 +10,9 @@ import
|
||||
# Standard library
|
||||
unittest, random, strutils,
|
||||
# Third-party
|
||||
../constantine/[io, bigints_raw, bigints_public, primitives]
|
||||
../constantine/io/io,
|
||||
../constantine/math/[bigints_raw, bigints_checked],
|
||||
../constantine/primitives/constant_time
|
||||
|
||||
suite "Bigints - Multiprecision modulo":
|
||||
test "bitsize 237 mod bitsize 192":
|
||||
@ -62,26 +64,26 @@ suite "Bigints - Multiprecision modulo":
|
||||
check:
|
||||
bool(r == expected)
|
||||
|
||||
# test "bitsize 1955 mod bitsize 459":
|
||||
# let a = BigInt[1955].fromHex("0x4f688e286a7c6e2b64663d8925c2f686994f2b90d58e7a843087c676c2c614ebab3eef9c765a88fe597b23b0e1fb28c812627366020edeafeefd0bf67a95215b4335412e2bd623b4cf7b69e669e1a8e782ab9a3e5fd443f10f459eed4ec9bd61821d94da82e937989245d481612b83b75d6d393e5de2258ac92aec7cd6e4f12c6b035e1fac3ef22851a8e211232b57db7551c03a88e9272411eea86e15c989be9d2962d5ae32ca35b18060212aaf6599b5a5f2416e436f009728b4017f87f70f4e528c9a33042b6810040c1e64457d56695d03b701540a5537c8cf781ff2ea4be2aa6daf1a5f2f0874a1cf495485a01254c2e2f4a")
|
||||
# let m = BigInt[459].fromHex("0x47304803a4a8c31e18287ad51c1ac7546c42e23206e9dc43e51eff5fa003f44bd08e542ec2659c405bfa4c9eb518ada943412767361029a902b")
|
||||
test "bitsize 1955 mod bitsize 459":
|
||||
let a = BigInt[1955].fromHex("0x4f688e286a7c6e2b64663d8925c2f686994f2b90d58e7a843087c676c2c614ebab3eef9c765a88fe597b23b0e1fb28c812627366020edeafeefd0bf67a95215b4335412e2bd623b4cf7b69e669e1a8e782ab9a3e5fd443f10f459eed4ec9bd61821d94da82e937989245d481612b83b75d6d393e5de2258ac92aec7cd6e4f12c6b035e1fac3ef22851a8e211232b57db7551c03a88e9272411eea86e15c989be9d2962d5ae32ca35b18060212aaf6599b5a5f2416e436f009728b4017f87f70f4e528c9a33042b6810040c1e64457d56695d03b701540a5537c8cf781ff2ea4be2aa6daf1a5f2f0874a1cf495485a01254c2e2f4a")
|
||||
let m = BigInt[459].fromHex("0x47304803a4a8c31e18287ad51c1ac7546c42e23206e9dc43e51eff5fa003f44bd08e542ec2659c405bfa4c9eb518ada943412767361029a902b")
|
||||
|
||||
# let expected = BigInt[459].fromHex("0x1f039dfe7c9da071d578b3b852db3916f4d79f6169818085994cbc41610abb7abb96e10d1126313cc281a87c309c2dd43bed745a9603f3c606c")
|
||||
let expected = BigInt[459].fromHex("0x1f039dfe7c9da071d578b3b852db3916f4d79f6169818085994cbc41610abb7abb96e10d1126313cc281a87c309c2dd43bed745a9603f3c606c")
|
||||
|
||||
# var r: BigInt[97]
|
||||
# r.reduce(a, m)
|
||||
var r: BigInt[459]
|
||||
r.reduce(a, m)
|
||||
|
||||
# check:
|
||||
# bool(r == expected)
|
||||
check:
|
||||
bool(r == expected)
|
||||
|
||||
# test "bitsize 2346 mod bitsize 97":
|
||||
# let a = BigInt[2346].fromHex("0x1b5efa688e4124a71edd035f106c6ea81bafd78f610cd59d46fc6cda548fd970dde6b91c6fa10ab6d198026dea3c46c41495294082f2acc8210fd7ebfb25fdc6ce8131676ab0d749c5a4a83dd08172b3849df30304685192708ff0b510600cbf87be3179ce704adc43f2c9b22ba28c77f0a364fa1a96344d7f338227a8f346c0e721bc1312f53cebfc20fd0763ec039aa83a77ba489056ebee2a462058f1daffec9b5df29474f638185c6684729482a29764b46a5487e159fc4eedda5018d3d18ae1c0c6503ebbbd859b4dff3e09b6567b752d51c9733fc822b2758b69ffd65974a8fbf4ad25a40761bb9b9b6a1f886928fe08f9c1571fe3e3987b15e37208a22f64e2c3ff75a36815b7906fc2a52f7bd32d15e8b0441e8c39ae9127d80946e146db5cd2738")
|
||||
# let m = BigInt[97].fromHex("0x1100d0717f9fff44c6cc7442e")
|
||||
test "bitsize 2346 mod bitsize 97":
|
||||
let a = BigInt[2346].fromHex("0x1b5efa688e4124a71edd035f106c6ea81bafd78f610cd59d46fc6cda548fd970dde6b91c6fa10ab6d198026dea3c46c41495294082f2acc8210fd7ebfb25fdc6ce8131676ab0d749c5a4a83dd08172b3849df30304685192708ff0b510600cbf87be3179ce704adc43f2c9b22ba28c77f0a364fa1a96344d7f338227a8f346c0e721bc1312f53cebfc20fd0763ec039aa83a77ba489056ebee2a462058f1daffec9b5df29474f638185c6684729482a29764b46a5487e159fc4eedda5018d3d18ae1c0c6503ebbbd859b4dff3e09b6567b752d51c9733fc822b2758b69ffd65974a8fbf4ad25a40761bb9b9b6a1f886928fe08f9c1571fe3e3987b15e37208a22f64e2c3ff75a36815b7906fc2a52f7bd32d15e8b0441e8c39ae9127d80946e146db5cd2738")
|
||||
let m = BigInt[97].fromHex("0x1100d0717f9fff44c6cc7442e")
|
||||
|
||||
# let expected = BigInt[97].fromHex("0x0104ea05300eeb05cd374197b6")
|
||||
let expected = BigInt[97].fromHex("0x0104ea05300eeb05cd374197b6")
|
||||
|
||||
# var r: BigInt[97]
|
||||
# r.reduce(a, m)
|
||||
var r: BigInt[97]
|
||||
r.reduce(a, m)
|
||||
|
||||
# check:
|
||||
# bool(r == expected)
|
||||
check:
|
||||
bool(r == expected)
|
||||
|
@ -12,7 +12,9 @@ import
|
||||
# Third-party
|
||||
gmp, stew/byteutils,
|
||||
# Internal
|
||||
../constantine/[io, bigints_raw, bigints_public, primitives]
|
||||
../constantine/io/io,
|
||||
../constantine/math/[bigints_raw, bigints_checked],
|
||||
../constantine/primitives/constant_time
|
||||
|
||||
# We test up to 1024-bit, more is really slow
|
||||
|
||||
|
@ -7,7 +7,9 @@
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import unittest, random,
|
||||
../constantine/[io, bigints_raw]
|
||||
../constantine/io/io,
|
||||
../constantine/config/common,
|
||||
../constantine/math/bigints_checked
|
||||
|
||||
randomize(0xDEADBEEF) # Random seed for reproducibility
|
||||
type T = BaseType
|
||||
|
@ -7,7 +7,7 @@
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import unittest, random, math,
|
||||
../constantine/primitives
|
||||
../constantine/primitives/constant_time
|
||||
|
||||
# Random seed for reproducibility
|
||||
randomize(0xDEADBEEF)
|
||||
|
Loading…
x
Reference in New Issue
Block a user