Skip to content

Commit

Permalink
RSA: Precompute R**3 and store it instead of R**2.
Browse files Browse the repository at this point in the history
This saves two private-modulus-length multiplications per RSA
private key operation at the cost of two private-modulus-length
squarings per `RsaKeyPair` construction.
  • Loading branch information
briansmith committed Nov 23, 2023
1 parent 9b8d4d7 commit 3145a79
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 8 deletions.
6 changes: 6 additions & 0 deletions src/arithmetic/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,12 @@ impl<M> One<M, RR> {
}
}

impl<M> One<M, RRR> {
pub(crate) fn newRRR(One(oneRR): One<M, RR>, m: &Modulus<M>) -> Self {
Self(elem_squared(oneRR, m))
}
}

impl<M, E> AsRef<Elem<M, E>> for One<M, E> {
fn as_ref(&self) -> &Elem<M, E> {
&self.0
Expand Down
19 changes: 19 additions & 0 deletions src/arithmetic/montgomery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ pub enum Unencoded {}
#[derive(Copy, Clone)]
pub enum R {}

// Indicates the element is encoded three times; the value has three
// *R* factors that need to be canceled out.
#[allow(clippy::upper_case_acronyms)]
#[derive(Copy, Clone)]
pub enum RRR {}

// Indicates the element is encoded twice; the value has two *R*
// factors that need to be canceled out.
#[derive(Copy, Clone)]
Expand All @@ -34,6 +40,7 @@ pub enum RInverse {}

pub trait Encoding {}

impl Encoding for RRR {}
impl Encoding for RR {}
impl Encoding for R {}
impl Encoding for Unencoded {}
Expand All @@ -44,6 +51,10 @@ pub trait ReductionEncoding {
type Output: Encoding;
}

impl ReductionEncoding for RRR {
type Output = RR;
}

impl ReductionEncoding for RR {
type Output = R;
}
Expand All @@ -67,6 +78,10 @@ impl<E: Encoding> ProductEncoding for (R, E) {
type Output = E;
}

impl ProductEncoding for (RR, RR) {
type Output = RRR;
}

impl<E: ReductionEncoding> ProductEncoding for (RInverse, E)
where
E::Output: ReductionEncoding,
Expand All @@ -87,6 +102,10 @@ impl ProductEncoding for (RR, RInverse) {
type Output = <(RInverse, RR) as ProductEncoding>::Output;
}

impl ProductEncoding for (RRR, RInverse) {
type Output = <(RInverse, RRR) as ProductEncoding>::Output;
}

#[allow(unused_imports)]
use {
super::n0::N0,
Expand Down
16 changes: 8 additions & 8 deletions src/rsa/keypair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use super::{
use crate::{
arithmetic::{
bigint,
montgomery::{R, RR},
montgomery::{R, RR, RRR},
},
bits::BitLength,
cpu, digest,
Expand Down Expand Up @@ -443,16 +443,17 @@ impl<M> PrivatePrime<M> {

struct PrivateCrtPrime<M> {
modulus: bigint::OwnedModulus<M>,
oneRR: bigint::One<M, RR>,
oneRRR: bigint::One<M, RRR>,
exponent: bigint::PrivateExponent,
}

impl<M> PrivateCrtPrime<M> {
/// Constructs a `PrivateCrtPrime` from the private prime `p` and `dP` where
/// dP == d % (p - 1).
fn new(p: PrivatePrime<M>, dP: untrusted::Input) -> Result<Self, KeyRejected> {
let m = &p.modulus.modulus();
// [NIST SP-800-56B rev. 1] 6.4.1.4.3 - Steps 7.a & 7.b.
let dP = bigint::PrivateExponent::from_be_bytes_padded(dP, &p.modulus.modulus())
let dP = bigint::PrivateExponent::from_be_bytes_padded(dP, m)
.map_err(|error::Unspecified| KeyRejected::inconsistent_components())?;

// XXX: Steps 7.d and 7.e are omitted. We don't check that
Expand All @@ -464,9 +465,11 @@ impl<M> PrivateCrtPrime<M> {
// and `e`. TODO: Either prove that what we do is sufficient, or make
// it so.

let oneRRR = bigint::One::newRRR(p.oneRR, m);

Ok(Self {
modulus: p.modulus,
oneRR: p.oneRR,
oneRRR,
exponent: dP,
})
}
Expand All @@ -479,10 +482,7 @@ fn elem_exp_consttime<M>(
) -> Result<bigint::Elem<M>, error::Unspecified> {
let m = &p.modulus.modulus();
let c_mod_m = bigint::elem_reduced(c, m, other_prime_len_bits);
// We could precompute `oneRRR = elem_squared(&p.oneRR`) as mentioned
// in the Smooth CRT-RSA paper.
let c_mod_m = bigint::elem_mul(p.oneRR.as_ref(), c_mod_m, m);
let c_mod_m = bigint::elem_mul(p.oneRR.as_ref(), c_mod_m, m);
let c_mod_m = bigint::elem_mul(p.oneRRR.as_ref(), c_mod_m, m);
bigint::elem_exp_consttime(c_mod_m, &p.exponent, m)
}

Expand Down

0 comments on commit 3145a79

Please sign in to comment.