diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 7ca90c79..9d21f782 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -46,13 +46,14 @@ pub fn rsa_decrypt( let mut ir = None; let n_params = priv_key.n_params(); + let bits = d.bits_precision(); let c = if let Some(ref mut rng) = rng { let (blinded, unblinder) = blind(rng, priv_key, &c, &n_params); ir = Some(unblinder); - Cow::Owned(blinded) + blinded.widen(bits) } else { - Cow::Borrowed(c) + c.widen(bits) }; let has_precomputes = priv_key.dp().is_some(); @@ -77,10 +78,10 @@ pub fn rsa_decrypt( // precomputed: dQ = (1/e) mod (q-1) = d mod (q-1) // m1 = c^dP mod p - let cp = BoxedMontyForm::new(c.clone().into_owned(), p_params.clone()); + let cp = BoxedMontyForm::new(c.clone(), p_params.clone()); let mut m1 = cp.pow(&dp); // m2 = c^dQ mod q - let cq = BoxedMontyForm::new(c.into_owned(), q_params.clone()); + let cq = BoxedMontyForm::new(c, q_params.clone()); let m2 = cq.pow(&dq).retrieve(); // (m1 - m2) mod p = (m1 mod p) - (m2 mod p) mod p @@ -101,6 +102,7 @@ pub fn rsa_decrypt( match ir { Some(ref ir) => { // unblind + let m = m.shorten(n_params.bits_precision()); let res = unblind(&m, ir, n_params); Ok(res) } @@ -148,13 +150,14 @@ fn blind( // which equals mr mod n. The factor of r can then be removed // by multiplying by the multiplicative inverse of r. debug_assert_eq!(&key.n().clone().get(), n_params.modulus()); + let bits = key.n_bits_precision(); - let mut r: BoxedUint = BoxedUint::one(); + let mut r: BoxedUint = BoxedUint::one_with_precision(bits); let mut ir: Option = None; while ir.is_none() { r = BoxedUint::random_mod(rng, key.n()); if r.is_zero().into() { - r = BoxedUint::one(); + r = BoxedUint::one_with_precision(bits); } // r^-1 (mod n) @@ -171,12 +174,28 @@ fn blind( c }; - (blinded, ir.unwrap()) + let ir = ir.unwrap(); + debug_assert_eq!(blinded.bits_precision(), bits); + debug_assert_eq!(ir.bits_precision(), bits); + + (blinded, ir) } /// Given an m and and unblinding factor, unblind the m. fn unblind(m: &BoxedUint, unblinder: &BoxedUint, n_params: BoxedMontyParams) -> BoxedUint { // m * r^-1 (mod n) + debug_assert_eq!( + m.bits_precision(), + unblinder.bits_precision(), + "invalid unblinder" + ); + + debug_assert_eq!( + m.bits_precision(), + n_params.bits_precision(), + "invalid n_params" + ); + mul_mod_params(m, unblinder, n_params) } @@ -271,21 +290,19 @@ pub(crate) fn compute_private_exponent_euler_totient( if primes.len() < 2 { return Err(Error::InvalidPrime); } - - let mut totient = BoxedUint::one(); + let bits = primes[0].bits_precision(); + let mut totient = BoxedUint::one_with_precision(bits); for prime in primes { totient = totient * (prime - &BoxedUint::one()); } - let totient = Odd::new(totient).unwrap(); + let exp = BoxedUint::from(exp).widen(totient.bits_precision()); // NOTE: `mod_inverse` checks if `exp` evenly divides `totient` and returns `None` if so. // This ensures that `exp` is not a factor of any `(prime - 1)`. - if let Some(d) = BoxedUint::from(exp).inv_odd_mod(&totient).into() { - Ok(d) - } else { - // `exp` evenly divides `totient` - Err(Error::InvalidPrime) + match exp.inv_mod(&totient).into_option() { + Some(res) => Ok(res), + None => Err(Error::InvalidPrime), } } diff --git a/src/encoding.rs b/src/encoding.rs index cb4ff1d4..4bbe6624 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -116,11 +116,16 @@ impl EncodePrivateKey for RsaPrivateKey { let private_exponent = Zeroizing::new(self.d().to_be_bytes()); let prime1 = Zeroizing::new(self.primes[0].to_be_bytes()); let prime2 = Zeroizing::new(self.primes[1].to_be_bytes()); + + let bits = self.d().bits_precision(); + let exponent1 = Zeroizing::new( - (self.d() % NonZero::new(&self.primes[0] - &BoxedUint::one()).unwrap()).to_be_bytes(), + (self.d() % NonZero::new(&self.primes[0].widen(bits) - &BoxedUint::one()).unwrap()) + .to_be_bytes(), ); let exponent2 = Zeroizing::new( - (self.d() % NonZero::new(&self.primes[1] - &BoxedUint::one()).unwrap()).to_be_bytes(), + (self.d() % NonZero::new(&self.primes[1].widen(bits) - &BoxedUint::one()).unwrap()) + .to_be_bytes(), ); let coefficient = Zeroizing::new( self.crt_coefficient() diff --git a/src/key.rs b/src/key.rs index 5ea588b0..050b9cc3 100644 --- a/src/key.rs +++ b/src/key.rs @@ -376,8 +376,9 @@ impl RsaPrivateKey { } let d = &self.d; - let p = &self.primes[0]; - let q = &self.primes[1]; + let bits = d.bits_precision(); + let p = self.primes[0].widen(bits); + let q = self.primes[1].widen(bits); // TODO: error handling @@ -388,8 +389,10 @@ impl RsaPrivateKey { let x = NonZero::new(p.wrapping_sub(&BoxedUint::one())).unwrap(); let dp = d.rem_vartime(&x); + let x = NonZero::new(q.wrapping_sub(&BoxedUint::one())).unwrap(); let dq = d.rem_vartime(&x); + let qinv = BoxedMontyForm::new(q.clone(), p_params.clone()); let qinv = qinv.invert(); if qinv.is_none().into() { @@ -397,6 +400,12 @@ impl RsaPrivateKey { } let qinv = qinv.unwrap(); + debug_assert_eq!(dp.bits_precision(), bits); + debug_assert_eq!(dq.bits_precision(), bits); + debug_assert_eq!(qinv.bits_precision(), bits); + debug_assert_eq!(p_params.bits_precision(), bits); + debug_assert_eq!(q_params.bits_precision(), bits); + self.precomputed = Some(PrecomputedValues { dp, dq,