diff --git a/Cargo.lock b/Cargo.lock index fbd342d5e..c10b82c85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -397,6 +397,7 @@ dependencies = [ name = "ed448-goldilocks" version = "0.14.0-pre.2" dependencies = [ + "criterion", "ed448", "elliptic-curve", "hash2curve", diff --git a/ed448-goldilocks/Cargo.toml b/ed448-goldilocks/Cargo.toml index 9c5327088..3b7b1b1cf 100644 --- a/ed448-goldilocks/Cargo.toml +++ b/ed448-goldilocks/Cargo.toml @@ -37,9 +37,14 @@ signing = ["dep:ed448", "dep:signature"] serde = ["dep:serdect", "ed448?/serde_bytes"] [dev-dependencies] +criterion = { version = "0.7", default-features = false, features = ["cargo_bench_support"] } hex-literal = "1" hex = "0.4" rand_core = { version = "0.9", features = ["os_rng"] } rand_chacha = "0.9" serde_bare = "0.5" serde_json = "1.0" + +[[bench]] +harness = false +name = "bench" diff --git a/ed448-goldilocks/benches/bench.rs b/ed448-goldilocks/benches/bench.rs new file mode 100644 index 000000000..96c029b90 --- /dev/null +++ b/ed448-goldilocks/benches/bench.rs @@ -0,0 +1,181 @@ +use criterion::{BatchSize, Criterion, criterion_group, criterion_main}; +use ed448_goldilocks::{ + CompressedDecaf, CompressedEdwardsY, Decaf448, DecafPoint, DecafScalar, EdwardsPoint, + EdwardsScalar, MontgomeryPoint, +}; +use elliptic_curve::{Field, Group}; +use hash2curve::{ExpandMsgXof, GroupDigest}; +use rand_core::{OsRng, TryRngCore}; +use sha3::Shake256; + +pub fn ed448(c: &mut Criterion) { + let mut group = c.benchmark_group("Ed448"); + + group.bench_function("scalar multiplication", |b| { + b.iter_batched( + || { + let point = EdwardsPoint::try_from_rng(&mut OsRng).unwrap(); + let scalar = EdwardsScalar::try_from_rng(&mut OsRng).unwrap(); + (point, scalar) + }, + |(point, scalar)| point * scalar, + BatchSize::SmallInput, + ) + }); + + group.bench_function("point addition", |b| { + b.iter_batched( + || { + let p1 = EdwardsPoint::try_from_rng(&mut OsRng).unwrap(); + let p2 = EdwardsPoint::try_from_rng(&mut OsRng).unwrap(); + (p1, p2) + }, + |(p1, p2)| p1 + p2, + BatchSize::SmallInput, + ) + }); + + group.bench_function("hash_to_curve", |b| { + b.iter_batched( + || { + let mut msg = [0; 64]; + OsRng.try_fill_bytes(&mut msg).unwrap(); + msg + }, + |msg| EdwardsPoint::hash_with_defaults(&msg), + BatchSize::SmallInput, + ) + }); + + group.bench_function("encode_to_curve", |b| { + b.iter_batched( + || { + let mut msg = [0; 64]; + OsRng.try_fill_bytes(&mut msg).unwrap(); + msg + }, + |msg| EdwardsPoint::encode_with_defaults(&msg), + BatchSize::SmallInput, + ) + }); + + group.bench_function("compress", |b| { + b.iter_batched( + || EdwardsPoint::try_from_rng(&mut OsRng).unwrap(), + |point| point.compress().0, + BatchSize::SmallInput, + ) + }); + + group.bench_function("decompress", |b| { + b.iter_batched( + || EdwardsPoint::try_from_rng(&mut OsRng).unwrap().compress().0, + |bytes| CompressedEdwardsY(bytes).decompress().unwrap(), + BatchSize::SmallInput, + ) + }); + + group.finish(); +} + +pub fn decaf448(c: &mut Criterion) { + let mut group = c.benchmark_group("Decaf448"); + + group.bench_function("scalar multiplication", |b| { + b.iter_batched( + || { + let point = DecafPoint::try_from_rng(&mut OsRng).unwrap(); + let scalar = DecafScalar::try_from_rng(&mut OsRng).unwrap(); + (point, scalar) + }, + |(point, scalar)| point * scalar, + BatchSize::SmallInput, + ) + }); + + group.bench_function("point addition", |b| { + b.iter_batched( + || { + let p1 = DecafPoint::try_from_rng(&mut OsRng).unwrap(); + let p2 = DecafPoint::try_from_rng(&mut OsRng).unwrap(); + (p1, p2) + }, + |(p1, p2)| p1 + p2, + BatchSize::SmallInput, + ) + }); + + group.bench_function("hash_to_curve", |b| { + b.iter_batched( + || { + let mut msg = [0; 64]; + OsRng.try_fill_bytes(&mut msg).unwrap(); + msg + }, + |msg| { + Decaf448::hash_from_bytes::>( + &[&msg], + &[b"decaf448_XOF:SHAKE256_D448MAP_RO_"], + ) + }, + BatchSize::SmallInput, + ) + }); + + group.bench_function("encode_to_curve", |b| { + b.iter_batched( + || { + let mut msg = [0; 64]; + OsRng.try_fill_bytes(&mut msg).unwrap(); + msg + }, + |msg| { + Decaf448::encode_from_bytes::>( + &[&msg], + &[b"decaf448_XOF:SHAKE256_D448MAP_NU_"], + ) + }, + BatchSize::SmallInput, + ) + }); + + group.bench_function("compress", |b| { + b.iter_batched( + || DecafPoint::try_from_rng(&mut OsRng).unwrap(), + |point| point.compress().0, + BatchSize::SmallInput, + ) + }); + + group.bench_function("decompress", |b| { + b.iter_batched( + || DecafPoint::try_from_rng(&mut OsRng).unwrap().compress().0, + |bytes| CompressedDecaf(bytes).decompress().unwrap(), + BatchSize::SmallInput, + ) + }); + + group.finish(); +} + +pub fn curve448(c: &mut Criterion) { + let mut group = c.benchmark_group("Curve448"); + + group.bench_function("scalar multiplication", |b| { + b.iter_batched( + || { + let mut point = MontgomeryPoint::default(); + OsRng.try_fill_bytes(&mut point.0).unwrap(); + let scalar = EdwardsScalar::try_from_rng(&mut OsRng).unwrap(); + (point, scalar) + }, + |(point, scalar)| &point * &scalar, + BatchSize::SmallInput, + ) + }); + + group.finish(); +} + +criterion_group!(benches, ed448, decaf448, curve448); +criterion_main!(benches);