mirror of
https://github.com/status-im/constantine.git
synced 2025-02-23 17:38:09 +00:00
Add benchmark of constant-time vs unsafe powmod
This commit is contained in:
parent
acfc99c4f0
commit
8cbbd40a0c
69
benchmarks/powmod.nim
Normal file
69
benchmarks/powmod.nim
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Benchmark of modular exponentiation
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
|
# 2 implementations are available
|
||||||
|
# - 1 is constant time
|
||||||
|
# - 1 exposes the exponent bits to:
|
||||||
|
# timing attack,
|
||||||
|
# memory access analysis,
|
||||||
|
# power analysis (i.e. oscilloscopes on embedded)
|
||||||
|
# It is suitable for public exponents for example
|
||||||
|
# to compute modular inversion via the Fermat method
|
||||||
|
|
||||||
|
import
|
||||||
|
../constantine/config/[common, curves],
|
||||||
|
../constantine/math/[bigints_checked, finite_fields],
|
||||||
|
../constantine/io/[io_bigints, io_fields],
|
||||||
|
random, std/monotimes, times, strformat
|
||||||
|
|
||||||
|
const Iters = 10_000
|
||||||
|
|
||||||
|
randomize(1234)
|
||||||
|
|
||||||
|
proc mainCT() =
|
||||||
|
var x: Fq[BLS12_381]
|
||||||
|
# BN254 field modulus
|
||||||
|
x.fromHex("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
|
||||||
|
# BLS12-381 prime - 2
|
||||||
|
let exponent = BigInt[381].fromHex("0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaa9")
|
||||||
|
|
||||||
|
let start = getMonotime()
|
||||||
|
for _ in 0 ..< Iters:
|
||||||
|
var y = x
|
||||||
|
x.pow(exponent)
|
||||||
|
let stop = getMonotime()
|
||||||
|
|
||||||
|
echo &"Time for {Iters} iterations (constant-time 381-bit): {inMilliseconds(stop-start)} ms"
|
||||||
|
|
||||||
|
proc mainUnsafe() =
|
||||||
|
var x: Fq[BLS12_381]
|
||||||
|
# BN254 field modulus
|
||||||
|
x.fromHex("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
|
||||||
|
# BLS12-381 prime - 2
|
||||||
|
let exponent = BigInt[381].fromHex("0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaa9")
|
||||||
|
|
||||||
|
let start = getMonotime()
|
||||||
|
for _ in 0 ..< Iters:
|
||||||
|
var y = x
|
||||||
|
x.powUnsafeExponent(exponent)
|
||||||
|
let stop = getMonotime()
|
||||||
|
|
||||||
|
echo &"Time for {Iters} iterations (unsafe 381-bit): {inMilliseconds(stop-start)} ms"
|
||||||
|
|
||||||
|
mainCT()
|
||||||
|
mainUnsafe()
|
||||||
|
# 10_000 iterations with -d:danger on i9-9980XE all-core turbo 4.1GHz
|
||||||
|
|
||||||
|
# Time for 10000 iterations (constant-time 381-bit): 1349 ms
|
||||||
|
# Time for 10000 iterations (unsafe 381-bit): 1226 ms
|
@ -606,7 +606,9 @@ func montyPowPrologue(
|
|||||||
a: BigIntViewMut, M, one: BigIntViewConst,
|
a: BigIntViewMut, M, one: BigIntViewConst,
|
||||||
negInvModWord: Word,
|
negInvModWord: Word,
|
||||||
scratchspace: openarray[BigIntViewMut]
|
scratchspace: openarray[BigIntViewMut]
|
||||||
): tuple[window: uint, bigIntSize: int] =
|
): tuple[window: uint, bigIntSize: int] {.inline.}=
|
||||||
|
# Due to the high number of parameters,
|
||||||
|
# forcing this inline actually reduces the code size
|
||||||
|
|
||||||
result.window = scratchspace.len.getWindowLen()
|
result.window = scratchspace.len.getWindowLen()
|
||||||
result.bigIntSize = a.numLimbs() * sizeof(Word) + sizeof(BigIntView.bitLength)
|
result.bigIntSize = a.numLimbs() * sizeof(Word) + sizeof(BigIntView.bitLength)
|
||||||
@ -637,13 +639,15 @@ func montyPowSquarings(
|
|||||||
bigIntSize: int,
|
bigIntSize: int,
|
||||||
acc, acc_len: var uint,
|
acc, acc_len: var uint,
|
||||||
e: var int,
|
e: var int,
|
||||||
): tuple[k, bits: uint] =
|
): tuple[k, bits: uint] {.inline.}=
|
||||||
## Squaring step of exponentiation by squaring
|
## Squaring step of exponentiation by squaring
|
||||||
## Get the next k bits in range [1, window)
|
## Get the next k bits in range [1, window)
|
||||||
## Square k times
|
## Square k times
|
||||||
## Returns the number of squarings done and the corresponding bits
|
## Returns the number of squarings done and the corresponding bits
|
||||||
##
|
##
|
||||||
## Updates iteration variables and accumulators
|
## Updates iteration variables and accumulators
|
||||||
|
# Due to the high number of parameters,
|
||||||
|
# forcing this inline actually reduces the code size
|
||||||
|
|
||||||
# Get the next bits
|
# Get the next bits
|
||||||
var k = window
|
var k = window
|
||||||
|
Loading…
x
Reference in New Issue
Block a user