Add modular addition over Fp

This commit is contained in:
mratsim 2018-12-02 00:35:55 +01:00
parent 463b8a4fcb
commit befbf30319
4 changed files with 82 additions and 15 deletions

View File

@ -5,8 +5,13 @@
# * 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.
# Big int internal representation.
# ############################################################
#
# BigInt representation
#
# ############################################################
# To avoid carry issues we don't use the
# most significant bit of each word.
# i.e. for a uint64 base we only use 63-bit.
@ -16,6 +21,10 @@
# - https://cryptojedi.org/peter/data/pairing-20131122.pdf
# - http://docs.milagro.io/en/amcl/milagro-crypto-library-white-paper.html
#
# Note that this might also be beneficial in terms of performance.
# Due to opcode latency, on Nehalem ADC is 6x times slower than ADD
# if it has dependencies (i.e the ADC depends on a previous ADC result)
# Control flow should only depends on the static maximum number of bits
# This number is defined per Finite Field/Prime/Elliptic Curve
#
@ -58,8 +67,11 @@ const highLimb* = (not Ct[uint64](0)) shr 1
# if it is a placebo operation. It stills performs the
# same memory accesses to be side-channel attack resistant
# For efficiency we define templates and will create functions
# specialized for runtime and compile-time inputs
# For efficiency we can define templates and will create functions
# specialised for runtime and compile-time inputs.
#
# We don't specialise for the control word, any optimizing compiler
# will keep it in registers.
template addImpl[bits](result: CTBool[Limb], a: var BigInt[bits], b: BigInt[bits], ctl: CTBool[Limb]) =
## Constant-time big integer in-place addition

View File

@ -1,8 +0,0 @@
# Constantine
# Copyright (c) 2018 Status Research & Development GmbH
# 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.

60
constantine/field_fp.nim Normal file
View File

@ -0,0 +1,60 @@
# Constantine
# Copyright (c) 2018 Status Research & Development GmbH
# 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.
# ############################################################
#
# Field arithmetic over Fp
#
# ############################################################
# We assume that p is prime known at compile-time
import
./word_types, ./bigints
type
Fp[P: static BigInt] = object
## P is a prime number
## All operations on a field are modulo P
value: type(P)
# ############################################################
#
# Aliases
#
# ############################################################
const
True = ctrue(Limb)
False = cfalse(Limb)
template add(a: var Fp, b: Fp, ctl: CTBool[Limb]): CTBool[Limb] =
add(a.value, b.value, ctl)
template sub(a: var Fp, b: Fp, ctl: CTBool[Limb]): CTBool[Limb] =
sub(a.value, b.value, ctl)
# ############################################################
#
# Field arithmetic primitives
#
# ############################################################
func `+`*(a, b: Fp): Fp =
## Addition over Fp
# Non-CT implementation from Stint
#
# let b_from_p = p - b # Don't do a + b directly to avoid overflows
# if a >= b_from_p:
# return a - b_from_p
# return m - b_from_p + a
result = a
var ctl = add(result, b, True)
ctl = ctl or not sub(result, Fp.P, False)
sub(result, Fp.P, ctl)

View File

@ -15,11 +15,11 @@ type
## by conditional branches, we don't use booleans.
## We use an int to prevent compiler "optimization" and introduction of branches
func ctrue*(T: type(BaseUint)): auto {.inline.}=
(CTBool[Ct[T]])(true)
func ctrue*(T: type(Ct)): auto {.inline.}=
(CTBool[T])(true)
func cfalse*(T: type(BaseUint)): auto {.inline.}=
(CTBool[Ct[T]])(false)
func cfalse*(T: type(Ct)): auto {.inline.}=
(CTBool[T])(false)
func ct*[T: BaseUint](x: T): Ct[T] {.inline.}=
(Ct[T])(x)
@ -103,6 +103,9 @@ func `not`*(ctl: CTBool): CTBool {.inline.}=
## Negate a constant-time boolean
(type result)(ctl.undistinct xor (type ctl.undistinct)(1))
func `and`*(x, y: CTBool): CTBool {.magic: "BitandI".}
func `or`*(x, y: CTBool): CTBool {.magic: "BitorI".}
template mux*[T: Ct](ctl: CTBool[T], x, y: T): T =
## Multiplexer / selector
## Returns x if ctl == 1