Skip to content

Commit ae65734

Browse files
authored
Use bounded exponentiation to improve encrypt/verify performance (#662)
Limit exponentiation to the bit length of e to reduce computation time. This is safe since e is public. Improves encrypt/verify performance by over 2x on my laptop. rsa_2048_pkcsv1_encrypt time: [17.822 µs 17.849 µs 17.877 µs] change: [-80.899% -80.786% -80.697%] (p = 0.00 < 0.05) Performance has improved. rsa_4096_pkcsv1_encrypt time: [149.74 µs 150.04 µs 150.37 µs] change: [-63.132% -61.496% -60.140%] (p = 0.00 < 0.05) Performance has improved. aws_lc_rs_2048_pkcs1_encrypt time: [10.682 µs 10.714 µs 10.747 µs] aws_lc_rs_4096_pkcs1_encrypt time: [31.771 µs 31.826 µs 31.879 µs]
1 parent 03e25a7 commit ae65734

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

src/algorithms/rsa.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ use crate::traits::keys::{PrivateKeyParts, PublicKeyParts};
1818
/// or signature scheme. See the [module-level documentation][crate::hazmat] for more information.
1919
#[inline]
2020
pub fn rsa_encrypt<K: PublicKeyParts>(key: &K, m: &BoxedUint) -> Result<BoxedUint> {
21-
let res = pow_mod_params(m, key.e(), key.n_params());
21+
let e = key.e();
22+
let res = pow_mod_params_vartime_exp_bits(m, e, e.bits(), key.n_params());
2223
Ok(res)
2324
}
2425

@@ -195,7 +196,8 @@ fn blind<R: TryCryptoRng + ?Sized, K: PublicKeyParts>(
195196

196197
let blinded = {
197198
// r^e (mod n)
198-
let mut rpowe = pow_mod_params(&r, key.e(), n_params);
199+
let e = key.e();
200+
let mut rpowe = pow_mod_params_vartime_exp_bits(&r, e, e.bits(), n_params);
199201
// c * r^e (mod n)
200202
let c = c.mul_mod(&rpowe, n_params.modulus().as_nz_ref());
201203
rpowe.zeroize();
@@ -234,6 +236,19 @@ fn pow_mod_params(base: &BoxedUint, exp: &BoxedUint, n_params: &BoxedMontyParams
234236
base.pow(exp).retrieve()
235237
}
236238

239+
/// Computes `base.pow_mod(exp, n)` with a bounded exponent and precomputed `n_params`.
240+
///
241+
/// The exponent bit length `exp_bits` may be leaked in the time pattern.
242+
fn pow_mod_params_vartime_exp_bits(
243+
base: &BoxedUint,
244+
exp: &BoxedUint,
245+
exp_bits: u32,
246+
n_params: &BoxedMontyParams,
247+
) -> BoxedUint {
248+
let base = reduce_vartime(base, n_params);
249+
base.pow_bounded_exp(exp, exp_bits).retrieve()
250+
}
251+
237252
fn reduce_vartime(n: &BoxedUint, p: &BoxedMontyParams) -> BoxedMontyForm {
238253
let modulus = p.modulus().as_nz_ref().clone();
239254
let n_reduced = n.rem_vartime(&modulus).resize_unchecked(p.bits_precision());

0 commit comments

Comments
 (0)