Add modular addition over Fp
This commit is contained in:
parent
463b8a4fcb
commit
befbf30319
|
@ -5,8 +5,13 @@
|
||||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
# * 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.
|
# 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
|
# To avoid carry issues we don't use the
|
||||||
# most significant bit of each word.
|
# most significant bit of each word.
|
||||||
# i.e. for a uint64 base we only use 63-bit.
|
# i.e. for a uint64 base we only use 63-bit.
|
||||||
|
@ -16,6 +21,10 @@
|
||||||
# - https://cryptojedi.org/peter/data/pairing-20131122.pdf
|
# - https://cryptojedi.org/peter/data/pairing-20131122.pdf
|
||||||
# - http://docs.milagro.io/en/amcl/milagro-crypto-library-white-paper.html
|
# - 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
|
# Control flow should only depends on the static maximum number of bits
|
||||||
# This number is defined per Finite Field/Prime/Elliptic Curve
|
# 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
|
# if it is a placebo operation. It stills performs the
|
||||||
# same memory accesses to be side-channel attack resistant
|
# same memory accesses to be side-channel attack resistant
|
||||||
|
|
||||||
# For efficiency we define templates and will create functions
|
# For efficiency we can define templates and will create functions
|
||||||
# specialized for runtime and compile-time inputs
|
# 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]) =
|
template addImpl[bits](result: CTBool[Limb], a: var BigInt[bits], b: BigInt[bits], ctl: CTBool[Limb]) =
|
||||||
## Constant-time big integer in-place addition
|
## Constant-time big integer in-place addition
|
|
@ -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.
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
@ -15,11 +15,11 @@ type
|
||||||
## by conditional branches, we don't use booleans.
|
## by conditional branches, we don't use booleans.
|
||||||
## We use an int to prevent compiler "optimization" and introduction of branches
|
## We use an int to prevent compiler "optimization" and introduction of branches
|
||||||
|
|
||||||
func ctrue*(T: type(BaseUint)): auto {.inline.}=
|
func ctrue*(T: type(Ct)): auto {.inline.}=
|
||||||
(CTBool[Ct[T]])(true)
|
(CTBool[T])(true)
|
||||||
|
|
||||||
func cfalse*(T: type(BaseUint)): auto {.inline.}=
|
func cfalse*(T: type(Ct)): auto {.inline.}=
|
||||||
(CTBool[Ct[T]])(false)
|
(CTBool[T])(false)
|
||||||
|
|
||||||
func ct*[T: BaseUint](x: T): Ct[T] {.inline.}=
|
func ct*[T: BaseUint](x: T): Ct[T] {.inline.}=
|
||||||
(Ct[T])(x)
|
(Ct[T])(x)
|
||||||
|
@ -103,6 +103,9 @@ func `not`*(ctl: CTBool): CTBool {.inline.}=
|
||||||
## Negate a constant-time boolean
|
## Negate a constant-time boolean
|
||||||
(type result)(ctl.undistinct xor (type ctl.undistinct)(1))
|
(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 =
|
template mux*[T: Ct](ctl: CTBool[T], x, y: T): T =
|
||||||
## Multiplexer / selector
|
## Multiplexer / selector
|
||||||
## Returns x if ctl == 1
|
## Returns x if ctl == 1
|
||||||
|
|
Loading…
Reference in New Issue