Skip to content

Commit be0bc19

Browse files
committed
elliptic-curve: add BasepointTableVartime::lincomb
Uses `WnafBase::multiscalar_mul` added in RustCrypto/group#14 to provide a variable-time linear combination operation which can use the precomputed wNAF for a basepoint. This has been tested in `p256` where it provides a 25% speedup for ECDSA verification.
1 parent f896a76 commit be0bc19

3 files changed

Lines changed: 34 additions & 2 deletions

File tree

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,5 @@ unused_qualifications = "warn"
5757
crypto-common = { path = "crypto-common" }
5858
digest = { path = "digest" }
5959
signature = { path = "signature" }
60+
61+
rustcrypto-group = { git = "https://github.com/RustCrypto/group" }

elliptic-curve/src/point/basepoint_table.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ impl<Point, const WINDOW_SIZE: usize> Deref for BasepointTable<Point, WINDOW_SIZ
9898
#[cfg(feature = "alloc")]
9999
pub(super) mod vartime {
100100
use super::LazyLock;
101+
use alloc::vec::Vec;
101102
use core::ops::Mul;
102103
use group::{Group, WnafBase, WnafScalar};
103104

@@ -151,6 +152,36 @@ pub(super) mod vartime {
151152
pub fn mul(&self, scalar: &Point::Scalar) -> Point {
152153
self.table.mul(&WnafScalar::new(scalar))
153154
}
155+
156+
/// Multiply `Point::generator` by the given scalar in variable-time, then compute a linear
157+
/// combination of the remaining points and scalars, i.e.
158+
///
159+
/// ```text
160+
/// scalar * G + scalars[0] * Points[0] + ...
161+
/// ```
162+
pub fn lincomb(
163+
&self,
164+
scalar: &Point::Scalar,
165+
points_and_scalars: &[(Point, Point::Scalar)],
166+
) -> Point {
167+
let mut bases = Vec::with_capacity(points_and_scalars.len() + 1);
168+
bases.push(self.table.clone());
169+
bases.extend(
170+
points_and_scalars
171+
.iter()
172+
.map(|(point, _)| WnafBase::new(*point)),
173+
);
174+
175+
let mut scalars = Vec::with_capacity(points_and_scalars.len() + 1);
176+
scalars.push(WnafScalar::new(scalar));
177+
scalars.extend(
178+
points_and_scalars
179+
.iter()
180+
.map(|(_, scalar)| WnafScalar::new(scalar)),
181+
);
182+
183+
WnafBase::multiscalar_mul(scalars.iter(), bases.iter())
184+
}
154185
}
155186

156187
impl<Point: Group, const WINDOW_SIZE: usize> Default for BasepointTableVartime<Point, WINDOW_SIZE> {

0 commit comments

Comments
 (0)