Skip to content

Commit a415ae8

Browse files
committed
primeorder: PrimeCurveParams::mul_by_generator_and_mul_add_vartime
Adds a trait method that can be overridden to plug in variable-time linear combinations using precomputed wNAF for the basepoint which otherwise uses `lincomb_vartime` by default. When used in `p256` in combination with RustCrypto/traits#2405 which added `BasepointTableVartime::lincomb`, this results in a 25% speedup for ECDSA verification: ECDSA/P-256 (SHA-256)/verify time: [146.21 µs 147.14 µs 148.38 µs] change: [−25.356% −24.522% −23.756%] (p = 0.00 < 0.05) Performance has improved.
1 parent ddbaa08 commit a415ae8

5 files changed

Lines changed: 28 additions & 9 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ hash2curve = { path = "hash2curve" }
2727
primefield = { path = "primefield" }
2828
primeorder = { path = "primeorder" }
2929

30+
elliptic-curve = { git = "http://github.com/RustCrypto/traits.git" }
3031
rustcrypto-group = { git = "https://github.com/RustCrypto/group" }

p256/src/arithmetic.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,13 @@ impl PrimeCurveParams for NistP256 {
6868
fn mul_by_generator_vartime(k: &Scalar) -> ProjectivePoint {
6969
tables::BASEPOINT_TABLE_VARTIME.mul(k)
7070
}
71+
72+
#[cfg(all(feature = "alloc", feature = "precomputed-tables"))]
73+
fn mul_by_generator_and_mul_add_vartime(
74+
a: &elliptic_curve::Scalar<Self>,
75+
b_scalar: &elliptic_curve::Scalar<Self>,
76+
b_point: &primeorder::ProjectivePoint<Self>,
77+
) -> primeorder::ProjectivePoint<Self> {
78+
tables::BASEPOINT_TABLE_VARTIME.lincomb(a, &[(*b_point, *b_scalar)])
79+
}
7180
}

primeorder/src/lib.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub use elliptic_curve::{
2929

3030
use elliptic_curve::{
3131
CurveArithmetic, Generate,
32-
ops::{Invert, MulVartime},
32+
ops::{Invert, LinearCombination, MulVartime},
3333
subtle::CtOption,
3434
};
3535

@@ -73,6 +73,19 @@ pub trait PrimeCurveParams:
7373
fn mul_by_generator_vartime(k: &Scalar<Self>) -> ProjectivePoint<Self> {
7474
ProjectivePoint::GENERATOR.mul_vartime(k)
7575
}
76+
77+
/// Multiply `a` by the generator of the prime-order subgroup, adding the result to the point
78+
/// `P` multiplied by the scalar `b`, i.e. compute `aG + bP`.
79+
fn mul_by_generator_and_mul_add_vartime(
80+
a: &Scalar<Self>,
81+
b_scalar: &Scalar<Self>,
82+
b_point: &ProjectivePoint<Self>,
83+
) -> ProjectivePoint<Self> {
84+
ProjectivePoint::<Self>::lincomb_vartime(&[
85+
(ProjectivePoint::GENERATOR, *a),
86+
(*b_point, *b_scalar),
87+
])
88+
}
7689
}
7790

7891
/// Trait which allows curves to specify a variable-time basepoint table.

primeorder/src/projective.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -970,16 +970,13 @@ where
970970
C::mul_by_generator_vartime(scalar)
971971
}
972972

973-
// When we're guaranteed *not* to have basepoint tables available (because they need `alloc`)
974-
// use linear combinations for this computation, but they're slower when they are available
975-
// TODO(tarcieri): `WnafBase::multiscalar_mul` w\ basepoint table when `alloc` *is* available
976-
#[cfg(not(feature = "alloc"))]
973+
#[inline]
977974
fn mul_by_generator_and_mul_add_vartime(
978975
a: &Self::Scalar,
979976
b_scalar: &Self::Scalar,
980977
b_point: &Self,
981978
) -> Self {
982-
Self::lincomb(&[(Self::GENERATOR, *a), (*b_point, *b_scalar)])
979+
C::mul_by_generator_and_mul_add_vartime(a, b_scalar, b_point)
983980
}
984981
}
985982

0 commit comments

Comments
 (0)