mirror of
https://github.com/saymrwulf/betrusted-curve25519-dalek-source.git
synced 2026-09-04 20:24:07 +00:00
Fixed-based Montgomery scalar multiplication (#503)
* Fixed-based Montgomery scalar multiplication Adds `MontgomeryPoint::mul_base` as an API for fixed-base scalar multiplication which allows for potential future optimizations. As a baseline implementation, it uses the variable base scalar multiplication implementation. This follows the existing `EdwardsPoint::mul_base` and `RistrettoPoint::mul_base` APIs. * Added Montgomery mul_base bench * Switched MontgomeryPoint::mul_base to use EdwardsPoint::mul_base --------- Co-authored-by: Michael Rosenberg <michael@mrosenberg.pub>
This commit is contained in:
parent
79bcbdc89b
commit
b375b46d37
2 changed files with 59 additions and 67 deletions
|
|
@ -1,12 +1,10 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
use rand::rngs::OsRng;
|
||||
use rand::thread_rng;
|
||||
use rand::{rngs::OsRng, thread_rng};
|
||||
|
||||
use criterion::measurement::Measurement;
|
||||
use criterion::BatchSize;
|
||||
use criterion::Criterion;
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkGroup, BenchmarkId};
|
||||
use criterion::{
|
||||
criterion_main, measurement::Measurement, BatchSize, BenchmarkGroup, BenchmarkId, Criterion,
|
||||
};
|
||||
|
||||
use curve25519_dalek::constants;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
|
|
@ -19,26 +17,26 @@ mod edwards_benches {
|
|||
|
||||
use curve25519_dalek::edwards::EdwardsPoint;
|
||||
|
||||
fn compress(c: &mut Criterion) {
|
||||
fn compress<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
||||
let B = &constants::ED25519_BASEPOINT_POINT;
|
||||
c.bench_function("EdwardsPoint compression", move |b| b.iter(|| B.compress()));
|
||||
}
|
||||
|
||||
fn decompress(c: &mut Criterion) {
|
||||
fn decompress<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
||||
let B_comp = &constants::ED25519_BASEPOINT_COMPRESSED;
|
||||
c.bench_function("EdwardsPoint decompression", move |b| {
|
||||
b.iter(|| B_comp.decompress().unwrap())
|
||||
});
|
||||
}
|
||||
|
||||
fn consttime_fixed_base_scalar_mul(c: &mut Criterion) {
|
||||
fn consttime_fixed_base_scalar_mul<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
||||
let s = Scalar::from(897987897u64).invert();
|
||||
c.bench_function("Constant-time fixed-base scalar mul", move |b| {
|
||||
b.iter(|| EdwardsPoint::mul_base(&s))
|
||||
});
|
||||
}
|
||||
|
||||
fn consttime_variable_base_scalar_mul(c: &mut Criterion) {
|
||||
fn consttime_variable_base_scalar_mul<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
||||
let B = &constants::ED25519_BASEPOINT_POINT;
|
||||
let s = Scalar::from(897987897u64).invert();
|
||||
c.bench_function("Constant-time variable-base scalar mul", move |b| {
|
||||
|
|
@ -46,7 +44,7 @@ mod edwards_benches {
|
|||
});
|
||||
}
|
||||
|
||||
fn vartime_double_base_scalar_mul(c: &mut Criterion) {
|
||||
fn vartime_double_base_scalar_mul<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
||||
c.bench_function("Variable-time aA+bB, A variable, B fixed", |bench| {
|
||||
let mut rng = thread_rng();
|
||||
let A = EdwardsPoint::mul_base(&Scalar::random(&mut rng));
|
||||
|
|
@ -58,15 +56,15 @@ mod edwards_benches {
|
|||
});
|
||||
}
|
||||
|
||||
criterion_group! {
|
||||
name = edwards_benches;
|
||||
config = Criterion::default();
|
||||
targets =
|
||||
compress,
|
||||
decompress,
|
||||
consttime_fixed_base_scalar_mul,
|
||||
consttime_variable_base_scalar_mul,
|
||||
vartime_double_base_scalar_mul,
|
||||
pub(crate) fn edwards_benches() {
|
||||
let mut c = Criterion::default();
|
||||
let mut g = c.benchmark_group("edwards benches");
|
||||
|
||||
compress(&mut g);
|
||||
decompress(&mut g);
|
||||
consttime_fixed_base_scalar_mul(&mut g);
|
||||
consttime_variable_base_scalar_mul(&mut g);
|
||||
vartime_double_base_scalar_mul(&mut g);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -211,28 +209,19 @@ mod multiscalar_benches {
|
|||
}
|
||||
}
|
||||
|
||||
fn multiscalar_multiplications(c: &mut Criterion) {
|
||||
let mut group: BenchmarkGroup<_> = c.benchmark_group("Multiscalar multiplications");
|
||||
pub(crate) fn multiscalar_benches() {
|
||||
let mut c = Criterion::default();
|
||||
let mut g = c.benchmark_group("multiscalar benches");
|
||||
|
||||
consttime_multiscalar_mul(&mut group);
|
||||
vartime_multiscalar_mul(&mut group);
|
||||
vartime_precomputed_pure_static(&mut group);
|
||||
consttime_multiscalar_mul(&mut g);
|
||||
vartime_multiscalar_mul(&mut g);
|
||||
vartime_precomputed_pure_static(&mut g);
|
||||
|
||||
let dynamic_fracs = [0.0, 0.2, 0.5];
|
||||
|
||||
for frac in dynamic_fracs.iter() {
|
||||
vartime_precomputed_helper(&mut group, *frac);
|
||||
vartime_precomputed_helper(&mut g, *frac);
|
||||
}
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
criterion_group! {
|
||||
name = multiscalar_benches;
|
||||
// Lower the sample size to run the benchmarks faster
|
||||
config = Criterion::default().sample_size(15);
|
||||
targets =
|
||||
multiscalar_multiplications,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -240,14 +229,14 @@ mod ristretto_benches {
|
|||
use super::*;
|
||||
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||
|
||||
fn compress(c: &mut Criterion) {
|
||||
fn compress<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
||||
c.bench_function("RistrettoPoint compression", |b| {
|
||||
let B = &constants::RISTRETTO_BASEPOINT_POINT;
|
||||
b.iter(|| B.compress())
|
||||
});
|
||||
}
|
||||
|
||||
fn decompress(c: &mut Criterion) {
|
||||
fn decompress<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
||||
c.bench_function("RistrettoPoint decompression", |b| {
|
||||
let B_comp = &constants::RISTRETTO_BASEPOINT_COMPRESSED;
|
||||
b.iter(|| B_comp.decompress().unwrap())
|
||||
|
|
@ -270,26 +259,21 @@ mod ristretto_benches {
|
|||
}
|
||||
}
|
||||
|
||||
fn double_and_compress_group(c: &mut Criterion) {
|
||||
let mut group: BenchmarkGroup<_> = c.benchmark_group("double & compress batched");
|
||||
double_and_compress_batch(&mut group);
|
||||
group.finish();
|
||||
}
|
||||
pub(crate) fn ristretto_benches() {
|
||||
let mut c = Criterion::default();
|
||||
let mut g = c.benchmark_group("ristretto benches");
|
||||
|
||||
criterion_group! {
|
||||
name = ristretto_benches;
|
||||
config = Criterion::default();
|
||||
targets =
|
||||
compress,
|
||||
decompress,
|
||||
double_and_compress_group,
|
||||
compress(&mut g);
|
||||
decompress(&mut g);
|
||||
double_and_compress_batch(&mut g);
|
||||
}
|
||||
}
|
||||
|
||||
mod montgomery_benches {
|
||||
use super::*;
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
|
||||
fn montgomery_ladder(c: &mut Criterion) {
|
||||
fn montgomery_ladder<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
||||
c.bench_function("Montgomery pseudomultiplication", |b| {
|
||||
let B = constants::X25519_BASEPOINT;
|
||||
let s = Scalar::from(897987897u64).invert();
|
||||
|
|
@ -297,17 +281,26 @@ mod montgomery_benches {
|
|||
});
|
||||
}
|
||||
|
||||
criterion_group! {
|
||||
name = montgomery_benches;
|
||||
config = Criterion::default();
|
||||
targets = montgomery_ladder,
|
||||
fn consttime_fixed_base_scalar_mul<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
||||
let s = Scalar::from(897987897u64).invert();
|
||||
c.bench_function("Constant-time fixed-base scalar mul", move |b| {
|
||||
b.iter(|| MontgomeryPoint::mul_base(&s))
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn montgomery_benches() {
|
||||
let mut c = Criterion::default();
|
||||
let mut g = c.benchmark_group("montgomery benches");
|
||||
|
||||
montgomery_ladder(&mut g);
|
||||
consttime_fixed_base_scalar_mul(&mut g);
|
||||
}
|
||||
}
|
||||
|
||||
mod scalar_benches {
|
||||
use super::*;
|
||||
|
||||
fn scalar_inversion(c: &mut Criterion) {
|
||||
fn scalar_inversion<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
||||
c.bench_function("Scalar inversion", |b| {
|
||||
let s = Scalar::from(897987897u64).invert();
|
||||
b.iter(|| s.invert());
|
||||
|
|
@ -332,18 +325,12 @@ mod scalar_benches {
|
|||
}
|
||||
}
|
||||
|
||||
fn batch_scalar_inversion_group(c: &mut Criterion) {
|
||||
let mut group: BenchmarkGroup<_> = c.benchmark_group("batch scalar inversion");
|
||||
batch_scalar_inversion(&mut group);
|
||||
group.finish();
|
||||
}
|
||||
pub(crate) fn scalar_benches() {
|
||||
let mut c = Criterion::default();
|
||||
let mut g = c.benchmark_group("scalar benches");
|
||||
|
||||
criterion_group! {
|
||||
name = scalar_benches;
|
||||
config = Criterion::default();
|
||||
targets =
|
||||
scalar_inversion,
|
||||
batch_scalar_inversion_group,
|
||||
scalar_inversion(&mut g);
|
||||
batch_scalar_inversion(&mut g);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,11 @@ impl Zeroize for MontgomeryPoint {
|
|||
}
|
||||
|
||||
impl MontgomeryPoint {
|
||||
/// Fixed-base scalar multiplication (i.e. multiplication by the base point).
|
||||
pub fn mul_base(scalar: &Scalar) -> Self {
|
||||
EdwardsPoint::mul_base(scalar).to_montgomery()
|
||||
}
|
||||
|
||||
/// View this `MontgomeryPoint` as an array of bytes.
|
||||
pub const fn as_bytes(&self) -> &[u8; 32] {
|
||||
&self.0
|
||||
|
|
|
|||
Loading…
Reference in a new issue