RSA: Support RSA key pairs where q < p without converting to p > q.
Previously we swapped p and q and calcualted a new qInv if p < q so that we could avoid doing a redunction during the CRT computation. Instead, just do the reduction during CRT as it's cheap. This notably reduces the number of operations we need in `bigint`, and it eliminates the need for the `Prime` modulus marker type. Now there are more things that can go wrong during CRT. First, we may wrongly forget to reduce m_2 mod p; before this wasn't necessary since every element of q was an element of p. Next, we may wrongly use the the value of m_2 mod p instead of m_2 later; before we could do this since previously m_2 mod p == m_2 since m_2 < q < p. Add tests for these cases. Rewrite the tests for `elem_reduced_once` given its new constraints.
This commit is contained in:
parent
23975ff236
commit
cfa3737947
@ -57,18 +57,6 @@ mod boxed_limbs;
|
||||
mod modulus;
|
||||
mod private_exponent;
|
||||
|
||||
/// A prime modulus.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Some logic may assume a `Prime` number is non-zero, and thus a non-empty
|
||||
/// array of limbs, or make similar assumptions. TODO: Any such logic should
|
||||
/// be encapsulated here, or this trait should be made non-`unsafe`. TODO:
|
||||
/// non-zero-ness and non-empty-ness should be factored out into a separate
|
||||
/// trait. (In retrospect, this shouldn't have been made an `unsafe` trait
|
||||
/// preemptively.)
|
||||
pub unsafe trait Prime {}
|
||||
|
||||
/// A modulus *s* that is smaller than another modulus *l* so every element of
|
||||
/// ℤ/sℤ is also an element of ℤ/lℤ.
|
||||
///
|
||||
@ -194,14 +182,12 @@ fn elem_mul_by_2<M, AF>(a: &mut Elem<M, AF>, m: &Modulus<M>) {
|
||||
// reduce elements (x mod q) mod p in the RSA CRT. If/when we do so, we
|
||||
// should update the testing so it is reflective of that usage, instead of
|
||||
// the old usage.
|
||||
#[cfg(test)]
|
||||
pub fn elem_reduced_once<Larger, Smaller>(
|
||||
a: &Elem<Larger, Unencoded>,
|
||||
m: &Modulus<Smaller>,
|
||||
) -> Elem<Smaller, Unencoded> {
|
||||
// `limbs_reduce_once_constant_time` requires `r` and `m` to have the same
|
||||
// number of limbs.
|
||||
assert_eq!(a.limbs.len(), m.limbs().len());
|
||||
pub fn elem_reduced_once<A, M>(
|
||||
a: &Elem<A, Unencoded>,
|
||||
m: &Modulus<M>,
|
||||
other_modulus_len_bits: BitLength,
|
||||
) -> Elem<M, Unencoded> {
|
||||
assert_eq!(m.len_bits(), other_modulus_len_bits);
|
||||
|
||||
let mut r = a.limbs.clone();
|
||||
limb::limbs_reduce_once_constant_time(&mut r, m.limbs());
|
||||
@ -405,14 +391,6 @@ pub(crate) fn elem_exp_vartime<M>(
|
||||
acc
|
||||
}
|
||||
|
||||
/// Uses Fermat's Little Theorem to calculate modular inverse in constant time.
|
||||
pub fn elem_inverse_consttime<M: Prime>(
|
||||
a: Elem<M, R>,
|
||||
m: &OwnedModulusWithOne<M>,
|
||||
) -> Result<Elem<M, Unencoded>, error::Unspecified> {
|
||||
elem_exp_consttime(a, &PrivateExponent::for_flt(&m.modulus()), m)
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
pub fn elem_exp_consttime<M>(
|
||||
base: Elem<M, R>,
|
||||
@ -939,16 +917,14 @@ mod tests {
|
||||
|section, test_case| {
|
||||
assert_eq!(section, "");
|
||||
|
||||
struct N {}
|
||||
struct QQ {}
|
||||
unsafe impl SmallerModulus<N> for QQ {}
|
||||
struct M {}
|
||||
struct O {}
|
||||
let m = consume_modulus::<M>(test_case, "m", cpu_features);
|
||||
let a = consume_elem_unchecked::<O>(test_case, "a", m.modulus().limbs().len());
|
||||
let expected_result = consume_elem::<M>(test_case, "r", &m.modulus());
|
||||
let other_modulus_len_bits = m.modulus().len_bits();
|
||||
|
||||
let qq = consume_modulus::<QQ>(test_case, "QQ", cpu_features);
|
||||
let expected_result = consume_elem::<QQ>(test_case, "R", &qq.modulus());
|
||||
let n = consume_modulus::<N>(test_case, "N", cpu_features);
|
||||
let a = consume_elem::<N>(test_case, "A", &n.modulus());
|
||||
|
||||
let actual_result = elem_reduced_once(&a, &qq.modulus());
|
||||
let actual_result = elem_reduced_once(&a, &m.modulus(), other_modulus_len_bits);
|
||||
assert_elem_eq(&actual_result, &expected_result);
|
||||
|
||||
Ok(())
|
||||
|
@ -13,11 +13,8 @@
|
||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
use super::{
|
||||
super::{
|
||||
montgomery::{Unencoded, RR},
|
||||
n0::N0,
|
||||
},
|
||||
BoxedLimbs, Elem, Nonnegative, One, PublicModulus, SmallerModulus,
|
||||
super::{montgomery::RR, n0::N0},
|
||||
BoxedLimbs, Elem, Nonnegative, One, PublicModulus, SmallerModulus, Unencoded,
|
||||
};
|
||||
use crate::{
|
||||
bits::BitLength,
|
||||
@ -236,13 +233,6 @@ impl<M> Modulus<'_, M> {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Get rid of this
|
||||
pub(super) fn one(&self) -> Elem<M, Unencoded> {
|
||||
let mut r = self.zero();
|
||||
r.limbs[0] = 1;
|
||||
r
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn limbs(&self) -> &[Limb] {
|
||||
self.limbs
|
||||
|
@ -12,7 +12,7 @@
|
||||
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
use super::{elem_add, elem_sub, limb, BoxedLimbs, Limb, LimbMask, Modulus, Prime};
|
||||
use super::{limb, BoxedLimbs, Limb, LimbMask, Modulus};
|
||||
use crate::error;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
@ -66,13 +66,4 @@ impl PrivateExponent {
|
||||
pub(super) fn limbs(&self) -> &[Limb] {
|
||||
&self.limbs
|
||||
}
|
||||
|
||||
// Returns `p - 2`.
|
||||
pub(super) fn for_flt<P: Prime>(p: &Modulus<P>) -> Self {
|
||||
let two = elem_add(p.one(), p.one(), p);
|
||||
let p_minus_2 = elem_sub(p.zero(), &two, p);
|
||||
Self {
|
||||
limbs: p_minus_2.limbs.into_limbs(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,39 +1,38 @@
|
||||
# 2**1024 - 105 is the largest 1024-bit prime.
|
||||
# Q == 2**1023 + 1155 is the smallest 1024-bit prime.
|
||||
#
|
||||
# import Math.NumberTheory.Prime;
|
||||
#
|
||||
# main = mapM_ (putStrLn . show) [prevPrime (2^1024), nextPrime (2^1023)]
|
||||
#
|
||||
# cabal install HaskellForMaths
|
||||
# ghc -O2 prime.hs
|
||||
# m = 2*1023 + 1
|
||||
# a = m
|
||||
m = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
|
||||
a = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
|
||||
r = 00
|
||||
|
||||
# N = P * Q
|
||||
# P == 2**1024 - 105
|
||||
# Q == 2**1023 + 1155
|
||||
# QQ = Q**2
|
||||
# A == N - 1 > QQ
|
||||
R = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcb7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9cb3b
|
||||
A = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044e7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe2644
|
||||
QQ = 40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000145b09
|
||||
N = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044e7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe2645
|
||||
# m = 2*1023 + 1
|
||||
# a = p + 1
|
||||
m = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
|
||||
a = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002
|
||||
r = 01
|
||||
|
||||
# N = P * Q
|
||||
# P == 2**1024 - 105
|
||||
# Q == 2**1023 + 1155
|
||||
# QQ = Q**2
|
||||
# A == QQ + 1 > QQ
|
||||
R = 01
|
||||
A = 40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000145b0a
|
||||
QQ = 40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000145b09
|
||||
N = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044e7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe2645
|
||||
# m = 2**1023 + 1
|
||||
# a = 2**1024 - 1
|
||||
m = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
|
||||
a = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
r = 7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
|
||||
|
||||
# N = P * Q
|
||||
# P == 2**1024 - 105
|
||||
# Q == 2**1023 + 1155
|
||||
# QQ = Q**2
|
||||
# A == QQ
|
||||
R = 00
|
||||
A = 40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000145b09
|
||||
QQ = 40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000145b09
|
||||
N = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044e7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe2645
|
||||
# m = 2*1023 + 1
|
||||
# a = p - 1
|
||||
# r = a
|
||||
m = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
|
||||
a = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
r = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
|
||||
# m = 2**1024 - 1
|
||||
# a = 2**1023 + 1
|
||||
# r = a
|
||||
m = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
a = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
|
||||
r = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
|
||||
|
||||
# m = 2**1023 + 1
|
||||
# a = 2**1023 + 1 + 2**1022
|
||||
# r = q
|
||||
m = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
|
||||
a = 9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
|
||||
r = 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
|
@ -41,14 +41,6 @@ impl Nonnegative {
|
||||
pub fn is_odd(&self) -> bool {
|
||||
limb::limbs_are_even_constant_time(&self.limbs) != LimbMask::True
|
||||
}
|
||||
|
||||
pub fn verify_less_than(&self, other: &Self) -> Result<(), error::Unspecified> {
|
||||
if !greater_than(other, self) {
|
||||
return Err(error::Unspecified);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn limbs(&self) -> &[Limb] {
|
||||
&self.limbs
|
||||
@ -59,12 +51,3 @@ impl Nonnegative {
|
||||
self.limbs.into_boxed_slice()
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a > b.
|
||||
fn greater_than(a: &Nonnegative, b: &Nonnegative) -> bool {
|
||||
if a.limbs.len() == b.limbs.len() {
|
||||
limb::limbs_less_than_limbs_vartime(&b.limbs, &a.limbs)
|
||||
} else {
|
||||
a.limbs.len() > b.limbs.len()
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,7 @@ use super::{
|
||||
|
||||
/// RSA PKCS#1 1.5 signatures.
|
||||
use crate::{
|
||||
arithmetic::{
|
||||
bigint::{self, Prime},
|
||||
montgomery::R,
|
||||
},
|
||||
arithmetic::{bigint, montgomery::R},
|
||||
bits::BitLength,
|
||||
cpu, digest,
|
||||
error::{self, KeyRejected},
|
||||
@ -260,18 +257,6 @@ impl KeyPair {
|
||||
let (q, _q_bits) = bigint::Nonnegative::from_be_bytes_with_bit_length(q)
|
||||
.map_err(|error::Unspecified| KeyRejected::invalid_encoding())?;
|
||||
|
||||
// Our implementation of CRT-based modular exponentiation used requires
|
||||
// that `p > q` so swap them if `p < q`. If swapped, `qInv` is
|
||||
// recalculated below. `p != q` is verified implicitly below, e.g. when
|
||||
// `q_mod_p` is constructed.
|
||||
let ((p, dP), (q, dQ, qInv)) = match q.verify_less_than(&p) {
|
||||
Ok(_) => ((p, dP), (q, dQ, Some(qInv))),
|
||||
Err(error::Unspecified) => {
|
||||
// TODO: verify `q` and `qInv` are inverses (mod p).
|
||||
((q, dQ), (p, dP, None))
|
||||
}
|
||||
};
|
||||
|
||||
// XXX: Some steps are done out of order, but the NIST steps are worded
|
||||
// in such a way that it is clear that NIST intends for them to be done
|
||||
// in order. TODO: Does this matter at all?
|
||||
@ -335,8 +320,8 @@ impl KeyPair {
|
||||
// assume that these preconditions are enough to let us assume that
|
||||
// checking p * q == 0 (mod n) is equivalent to checking p * q == n.
|
||||
let q_mod_n = q.modulus.to_elem(n);
|
||||
let q_mod_n = bigint::elem_mul(n_one.as_ref(), q_mod_n, n);
|
||||
let p_mod_n = p.modulus.to_elem(n);
|
||||
let p_mod_n = bigint::elem_mul(n_one.as_ref(), p_mod_n, n);
|
||||
let pq_mod_n = bigint::elem_mul(&q_mod_n, p_mod_n, n);
|
||||
if !pq_mod_n.is_zero() {
|
||||
return Err(KeyRejected::inconsistent_components());
|
||||
@ -368,19 +353,9 @@ impl KeyPair {
|
||||
|
||||
// 6.4.1.4.3 - Step 7.
|
||||
|
||||
let q_mod_p = q.modulus.to_elem(pm);
|
||||
|
||||
// Step 7.c.
|
||||
let qInv = if let Some(qInv) = qInv {
|
||||
bigint::Elem::from_be_bytes_padded(qInv, pm)
|
||||
.map_err(|error::Unspecified| KeyRejected::invalid_component())?
|
||||
} else {
|
||||
// We swapped `p` and `q` above, so we need to calculate `qInv`.
|
||||
// Step 7.f below will verify `qInv` is correct.
|
||||
let q_mod_p = bigint::elem_mul(p.modulus.oneRR().as_ref(), q_mod_p.clone(), pm);
|
||||
bigint::elem_inverse_consttime(q_mod_p, &p.modulus)
|
||||
.map_err(|error::Unspecified| KeyRejected::unexpected_error())?
|
||||
};
|
||||
let qInv = bigint::Elem::from_be_bytes_padded(qInv, pm)
|
||||
.map_err(|error::Unspecified| KeyRejected::invalid_component())?;
|
||||
|
||||
// Steps 7.d and 7.e are omitted per the documentation above, and
|
||||
// because we don't (in the long term) have a good way to do modulo
|
||||
@ -388,6 +363,8 @@ impl KeyPair {
|
||||
|
||||
// Step 7.f.
|
||||
let qInv = bigint::elem_mul(p.modulus.oneRR().as_ref(), qInv, pm);
|
||||
let q_mod_p = bigint::elem_reduced(&q_mod_n, pm, q.modulus.len_bits());
|
||||
let q_mod_p = bigint::elem_mul(p.modulus.oneRR().as_ref(), q_mod_p, pm);
|
||||
bigint::verify_inverses_consttime(&qInv, q_mod_p, pm)
|
||||
.map_err(|error::Unspecified| KeyRejected::inconsistent_components())?;
|
||||
|
||||
@ -424,12 +401,12 @@ impl signature::KeyPair for KeyPair {
|
||||
}
|
||||
}
|
||||
|
||||
struct PrivatePrime<M: Prime> {
|
||||
struct PrivatePrime<M> {
|
||||
modulus: bigint::OwnedModulusWithOne<M>,
|
||||
exponent: bigint::PrivateExponent,
|
||||
}
|
||||
|
||||
impl<M: Prime> PrivatePrime<M> {
|
||||
impl<M> PrivatePrime<M> {
|
||||
/// Constructs a `PrivatePrime` from the private prime `p` and `dP` where
|
||||
/// dP == d % (p - 1).
|
||||
fn new(
|
||||
@ -484,10 +461,7 @@ fn elem_exp_consttime<M>(
|
||||
c: &bigint::Elem<N>,
|
||||
p: &PrivatePrime<M>,
|
||||
other_prime_len_bits: BitLength,
|
||||
) -> Result<bigint::Elem<M>, error::Unspecified>
|
||||
where
|
||||
M: Prime,
|
||||
{
|
||||
) -> 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
|
||||
@ -502,14 +476,11 @@ where
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum P {}
|
||||
unsafe impl Prime for P {}
|
||||
unsafe impl bigint::SmallerModulus<N> for P {}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum Q {}
|
||||
unsafe impl Prime for Q {}
|
||||
unsafe impl bigint::SmallerModulus<N> for Q {}
|
||||
unsafe impl bigint::SmallerModulus<P> for Q {}
|
||||
|
||||
impl KeyPair {
|
||||
/// Computes the signature of `msg` and writes it into `signature`.
|
||||
@ -582,16 +553,19 @@ impl KeyPair {
|
||||
let c = base;
|
||||
|
||||
// Step 2.b.i.
|
||||
let m_1 = elem_exp_consttime(&c, &self.p, self.q.modulus.len_bits())?;
|
||||
let q_bits = self.q.modulus.len_bits();
|
||||
let m_1 = elem_exp_consttime(&c, &self.p, q_bits)?;
|
||||
let m_2 = elem_exp_consttime(&c, &self.q, self.p.modulus.len_bits())?;
|
||||
|
||||
// Step 2.b.ii isn't needed since there are only two primes.
|
||||
|
||||
// Step 2.b.iii.
|
||||
let p = &self.p.modulus.modulus();
|
||||
let m_2 = bigint::elem_widen(m_2, p);
|
||||
let m_1_minus_m_2 = bigint::elem_sub(m_1, &m_2, p);
|
||||
let h = bigint::elem_mul(&self.qInv, m_1_minus_m_2, p);
|
||||
let h = {
|
||||
let p = &self.p.modulus.modulus();
|
||||
let m_2 = bigint::elem_reduced_once(&m_2, p, q_bits);
|
||||
let m_1_minus_m_2 = bigint::elem_sub(m_1, &m_2, p);
|
||||
bigint::elem_mul(&self.qInv, m_1_minus_m_2, p)
|
||||
};
|
||||
|
||||
// Step 2.b.iv. The reduction in the modular multiplication isn't
|
||||
// necessary because `h < p` and `p * q == n` implies `h * q < n`.
|
||||
@ -624,3 +598,41 @@ impl KeyPair {
|
||||
Ok(m)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::test;
|
||||
use alloc::vec;
|
||||
|
||||
#[test]
|
||||
fn test_rsakeypair_private_exponentiate() {
|
||||
test::run(
|
||||
test_file!("keypair_private_exponentiate_tests.txt"),
|
||||
|section, test_case| {
|
||||
assert_eq!(section, "");
|
||||
|
||||
let key = test_case.consume_bytes("Key");
|
||||
let key = KeyPair::from_pkcs8(&key).unwrap();
|
||||
let test_cases = &[
|
||||
test_case.consume_bytes("p"),
|
||||
test_case.consume_bytes("p_plus_1"),
|
||||
test_case.consume_bytes("p_minus_1"),
|
||||
test_case.consume_bytes("q"),
|
||||
test_case.consume_bytes("q_plus_1"),
|
||||
test_case.consume_bytes("q_minus_1"),
|
||||
];
|
||||
for test_case in test_cases {
|
||||
// THe call to `elem_verify_equal_consttime` will cause
|
||||
// `private_exponentiate` to fail if the computation is
|
||||
// incorrect.
|
||||
let mut padded = vec![0; key.public.modulus_len()];
|
||||
let zeroes = padded.len() - test_case.len();
|
||||
padded[zeroes..].copy_from_slice(test_case);
|
||||
let _: bigint::Elem<_> = key.private_exponentiate(&padded).unwrap();
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
17
src/rsa/keypair_private_exponentiate_tests.txt
Normal file
17
src/rsa/keypair_private_exponentiate_tests.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# RSA 2048-bit key with e == 65537 and p < q.
|
||||
Key = 308204bd020100300d06092a864886f70d0101010500048204a7308204a30201000282010100a0afb85b74105f49f6836183d67b92602b53ad0d7a65f32a21d8959b8722aae1ec000cb9f22de09b794d7446e04be02a782615a659ceddb5f3344b6e566970718124dc8b8bf23c5aaa7447b7f11905f828e91f1a844d535624b987704ecca430d04cfee0deef46e7e2da65a3f2a1b3aae6cdf96795d24073a07312867aeb414e0bd6c23d80bd9ce6266fd90dac7666b019c141e3516ed51ced0d62a0b1db189860406ec5b7bbbeb49031979dba118ef6ad131365d6bd6994e695ab084592a5d2470341e4a9da14167a1387ec3d513687b7d849d64da896d4038f72f8a8a516c6402225a53eb813c1eb0e675af8880433545a90404946d7d8db2716fdd63898650203010001028201007df2de1548f720499020d0c98ecf931f3036c938fc4c76f9fa479294b2aa98b8b6cc1f2d8cc72afb926c048d1d783bbfee2723e71d13c9b2b96baf0850511b22ccb040f25c82458e6776f7541575a0b9300ff2224dbb726bde235226d48d10d1762433cfbcce5e8c99c2c7d266f71a2605fd42d54f98da8e0720cb4f7f7f70d2668b89cb57fde159ac7922756fd161379a5693168c388b7e1468552f67f896f69740e80e13b9badee87b7116e559c1e428276cc9d4788b0ee25f10ed560daa8339aeb52d8bb2b05a2e1e16e3fb348ae5feb5dbaf53a7d8a318865e1a746374df077d85120b02e3f0ceba47cc734c96ed6dac65f11bde2db2f1ffaec0da5924c102818100c045a3996d1465c73ca839c442b1026c82e418c68a5f96b34ff36557144a86af092b8c2873c42ac08d66e2f471c4094098be48058ed2bb0ebf0beb896f0eb18eea16d475914c901e35dffbcc257f19260819213c46eac7e508aae0114b98770471949f006d42a6c2e07d590e1f5f14747239154f65155daa4bea84f5ee8d2c7102818100d5f20732ea986dd3d1245dce180595a7f48b36c58f1576f6782062a4f1790871bfb2e31b96f1b596c59b6624cc2b56c441e4970fffe70e59c0fca099b598170106a60e32725c35401271ba2216039c627b18a2e319331c1444238724ba7c80e2f35d13fc0662638b414f7c12fe66db22328fa892a4b7632ea2c24f6b06fb3535028180448f5073e0127aec5d73bb0d819e6eb7d4c0931910b45f1f576df9ffe00b67153916df26798944995e92867115b40a7c8f3aa2a1e0b8c1dcd340e3df20cbc382ab7432942d9878775d4c9e13c0771eb79201abf93b6c7294f7cf3e90cc3cf48b9018a7cdd6280320d03dc228a805165d2371b9689329d83966529cd0b91c7bf1028181009f1bbed4d3f9067ca7a63709057e69bd1db5c6c707d13bc6b2b1cb0ac5f6701c4027a694a71e1d2102d6be1111b20d762956fa2d50f0221107e01904173403afa4a52c1bc246e6e73e904b8ffbf535815bf0877b030baa8f3bd97c31096b7c62cc0065d361601c8dbcc5830d911b274ef8713439d2bbfbcbfc092c0cf9852b1d02818058e7d95fe1a95fe10f60b59eba5c8c28c8eeaa82956a3035f37e7570f5ff91a104a5df77ba13a09bedb22018e2ac7461471b5e719ab202032cb3905391b7d15c74b36aff25c83987726e0ef1362c1b8f4f8282f2c4fd6a38a9a15e63400b92bfff31cbfc375313dc40f9cf19e031ededd32c47de6b3a99696a903638c4d6969a
|
||||
p = c045a3996d1465c73ca839c442b1026c82e418c68a5f96b34ff36557144a86af092b8c2873c42ac08d66e2f471c4094098be48058ed2bb0ebf0beb896f0eb18eea16d475914c901e35dffbcc257f19260819213c46eac7e508aae0114b98770471949f006d42a6c2e07d590e1f5f14747239154f65155daa4bea84f5ee8d2c71
|
||||
p_plus_1 = c045a3996d1465c73ca839c442b1026c82e418c68a5f96b34ff36557144a86af092b8c2873c42ac08d66e2f471c4094098be48058ed2bb0ebf0beb896f0eb18eea16d475914c901e35dffbcc257f19260819213c46eac7e508aae0114b98770471949f006d42a6c2e07d590e1f5f14747239154f65155daa4bea84f5ee8d2c72
|
||||
p_minus_1 = c045a3996d1465c73ca839c442b1026c82e418c68a5f96b34ff36557144a86af092b8c2873c42ac08d66e2f471c4094098be48058ed2bb0ebf0beb896f0eb18eea16d475914c901e35dffbcc257f19260819213c46eac7e508aae0114b98770471949f006d42a6c2e07d590e1f5f14747239154f65155daa4bea84f5ee8d2c70
|
||||
q = d5f20732ea986dd3d1245dce180595a7f48b36c58f1576f6782062a4f1790871bfb2e31b96f1b596c59b6624cc2b56c441e4970fffe70e59c0fca099b598170106a60e32725c35401271ba2216039c627b18a2e319331c1444238724ba7c80e2f35d13fc0662638b414f7c12fe66db22328fa892a4b7632ea2c24f6b06fb3535
|
||||
q_plus_1 = d5f20732ea986dd3d1245dce180595a7f48b36c58f1576f6782062a4f1790871bfb2e31b96f1b596c59b6624cc2b56c441e4970fffe70e59c0fca099b598170106a60e32725c35401271ba2216039c627b18a2e319331c1444238724ba7c80e2f35d13fc0662638b414f7c12fe66db22328fa892a4b7632ea2c24f6b06fb3536
|
||||
q_minus_1 = d5f20732ea986dd3d1245dce180595a7f48b36c58f1576f6782062a4f1790871bfb2e31b96f1b596c59b6624cc2b56c441e4970fffe70e59c0fca099b598170106a60e32725c35401271ba2216039c627b18a2e319331c1444238724ba7c80e2f35d13fc0662638b414f7c12fe66db22328fa892a4b7632ea2c24f6b06fb3534
|
||||
|
||||
# RSA 3072-bit key with e == 65537 and p < q.
|
||||
Key = 308206ff020100300d06092a864886f70d0101010500048206e9308206e50201000282018100a893194cf895bbbfa58f2863ab9bd00671cf5c48604efcb175d6f03a55d32a991c3021d52265369d45b94c4e80210a5d8d3d0738fb98669f1256d406eabafb67ad028de2e25909cd87b723a6f29eaaa46d77c74e998d3ca635ddb71335c2d77143c61d1875b0c6abe15474dd61e69fb0a5bfc381f8ffc251be4a03ff9cdebc6d890cc5d1e1b4da6115afd7d4bd9ec8b12361158eb5526cb9ccd5c1763862f65ac0cf10d7718efdbdc6f4e23325b129625d0e87a1136dc34af0f9e0e2abc7d617abbcfdb8f33d04a2cff977336df6c3956b5b667c399047d720da828370e601ca3e032a81dab5eeb9a5c37ffb4ae255fc0a3093756e9fd039faa87f2ccd396d8c44b51dec14d7a0c00e2a0735102d30ae30edf41e67af3bec5103f7ea969dc1222a0b7fdbd622788aef9fa410a9640312c33f14c322ae3b7ff2dce7c7440e9ea5f2521bfe75e206b16ea5176a7e4b9a7ba326fdc2541bc56fb6b16451a11f23f50217b61a277e3116cb65c6aa40615041e20118bd10fad88602bea3a232ca12f102030100010282018033cb3e72cfcdf1a9a88c9bb443fdd3a4a74336ef65e7deec0770cacea1a007ee932296c28d96db78e6fb4fdeaeaf7827d64571faa812e334ecc590cfaf3f540f3eb112372ba47fc68e744e97f4e39b3a7a07db4ce310ea1987635fe49f180669de90f84f939984f13a826085c496bf69df03546692c2c249ab55c274bf16107ef724dd82e6fe523a92173d113851990813feb848e89d329ac3bcc97c3146f6ba5b9343716e8aa89bae8d7f1287fa2ee4f2028cd988c6a8c255d7f0a8b46ee9f04c36250f4a66b148415c83fe991360231e8f267a9400a31111fedd19aadc93eb0b6833e556c2c91e2a69ee6ae0462eb6a146e1d30680f02bac5e2ec95879e9a42b05c790baf87e6481f0a703a4897a221f2f4604facb45948bef592d61891fe55e5c52b7a44f01a0148641dee97eeb2efd96968fd82310ea551184b4c63c48039e13bcd15abc15029d3c5bd41665895bef92e12513e06706cb03221ff5aa7f6aa64ebfcdcd6882ad2ec765731ee6452d6470a7053a276f51b7c20b7b54d8c0010281c100c9bc1dc851bcfeb8e8d33063be3d8be4d09f816c0567a06935c7b8082dd06c1f2ce9eba3fdadef1a77e087e05f76bb05d625bfc835dbc1cbf5397cdb9e5f67b23fce81bfc7b27f2cebd7db80b8a696bd57b3eae3f498a1b4782f8721c12c685b85ef648575ce81010fbd12e6bbefddc3e073ac309dec8d9671fbed47344b8ca8fb90a974fd4d306c92f2a2f8f6db36c57780faf07baf850454be836c6cca4c9e35327d84babcac06c14ea3295fbc772319d9582ea185e4a685ffdd1316bb2e810281c100d5eb7ff5b91f4068cd2739c0c5c4e609839e07b950307f55a5b5892d8ead0b3f77c8657204cc320e9b52d67af2eeec787dea098ece882abf6e93957ec1fb753f28e17de205a0e4967c7880ad9580b81a3a2315e3466f639a62162e4f0de8f009142bc19488510b2e0e2ef86f0be45f4efa51ea794fbabff294c3c40199c450221c99707026bd1de3649c10c37a4c493fab1aa9511ed64bec38a1724c8af4a9813de028dcdc0bde1639a1b6a4b9ac0480cee494a533fff8214de959a9a6bc8c710281c100c87a9b3a5d08ae3742a1c60009aa0e6159767a5ec84c405cee26495c4f734650010982b4d940c6528e79636ef64ffef280ebc8d885b59bb53e416034bd01e10282688e06f1c5109faacd3c85827b83682d454e94359a8d70d4d39ebe4bc3fefd9d6fd77cce23678e8f7e7dcf314be21e6beb685e7443063e518e643293e4d4a7864130366418169c7fb8837f598b66b5fcda0007875359a481374752341722e742c4a77a853d44d3fdbd5166a78e9af31618298b45d7d2f02e50a4f9f86812810281c100b05497bc6fa4f00db315a348607cc5f58fb542bea0f7e8ee2b52b1498932e073a783db031a2b4b13b93a962af076bb1b3307286bbb98884c1594b784add75db4fb38abf0141da46edb18e550b04c52f4e3792a40963d990797d49ac5753cce275da617c21c7f594cd44a296437943e6fb66cb16edfa69b3415262d39f88ad656d7e62ec573592dfad362c57aac2397b9508c00872a79104a1e000e5c43aa1ad2bab33c5b99527af52cfa3cb819884e89f2807e7a929b6ae7e0f5f97f9b3e0e310281c100b1e8aeff349d9d187e73d86f166a9703a14bc93ec599b203232027a180f3179ed10a51d9b482ef12f218285d2e06c45ae984995405cdbe71e72170f4a602ddd968c3673f1d5262e69eabc3106553ccc07b8bcd8306338346d2fd2bf595d96c48df5f959dd9384561014c79e7305728587bf01821eaf1f85e74f4365fa1492a30cf3ab54cd1080da479fd834bd07c1ec5e72e9ab68d855845cae166c8f885fdc20e946d40ec478628f4498ebc18e37204253765cf41bdfcf0cccd2ca1ef06b6ca
|
||||
p = C9BC1DC851BCFEB8E8D33063BE3D8BE4D09F816C0567A06935C7B8082DD06C1F2CE9EBA3FDADEF1A77E087E05F76BB05D625BFC835DBC1CBF5397CDB9E5F67B23FCE81BFC7B27F2CEBD7DB80B8a696bd57b3eae3f498a1b4782f8721c12c685b85ef648575ce81010fbd12e6bbefddc3e073ac309dec8d9671fbed47344b8ca8fb90a974fd4d306c92f2a2f8f6db36c57780faf07baf850454be836c6cca4c9e35327d84babcac06c14ea3295fbc772319d9582ea185e4a685ffdd1316bb2e81
|
||||
p_plus_1 = C9BC1DC851BCFEB8E8D33063BE3D8BE4D09F816C0567A06935C7B8082DD06C1F2CE9EBA3FDADEF1A77E087E05F76BB05D625BFC835DBC1CBF5397CDB9E5F67B23FCE81BFC7B27F2CEBD7DB80B8a696bd57b3eae3f498a1b4782f8721c12c685b85ef648575ce81010fbd12e6bbefddc3e073ac309dec8d9671fbed47344b8ca8fb90a974fd4d306c92f2a2f8f6db36c57780faf07baf850454be836c6cca4c9e35327d84babcac06c14ea3295fbc772319d9582ea185e4a685ffdd1316bb2e82
|
||||
p_minus_1 = C9BC1DC851BCFEB8E8D33063BE3D8BE4D09F816C0567A06935C7B8082DD06C1F2CE9EBA3FDADEF1A77E087E05F76BB05D625BFC835DBC1CBF5397CDB9E5F67B23FCE81BFC7B27F2CEBD7DB80B8a696bd57b3eae3f498a1b4782f8721c12c685b85ef648575ce81010fbd12e6bbefddc3e073ac309dec8d9671fbed47344b8ca8fb90a974fd4d306c92f2a2f8f6db36c57780faf07baf850454be836c6cca4c9e35327d84babcac06c14ea3295fbc772319d9582ea185e4a685ffdd1316bb2e80
|
||||
q = d5eb7ff5b91f4068cd2739c0c5c4e609839e07b950307f55a5b5892d8ead0b3f77c8657204cc320e9b52d67af2eeec787dea098ece882abf6e93957ec1fb753f28e17de205a0e4967c7880ad9580b81a3a2315e3466f639a62162e4f0de8f009142bc19488510b2e0e2ef86f0be45f4efa51ea794fbabff294c3c40199c450221c99707026bd1de3649c10c37a4c493fab1aa9511ed64bec38a1724c8af4a9813de028dcdc0bde1639a1b6a4b9ac0480cee494a533fff8214de959a9a6bc8c71
|
||||
q_plus_1 = d5eb7ff5b91f4068cd2739c0c5c4e609839e07b950307f55a5b5892d8ead0b3f77c8657204cc320e9b52d67af2eeec787dea098ece882abf6e93957ec1fb753f28e17de205a0e4967c7880ad9580b81a3a2315e3466f639a62162e4f0de8f009142bc19488510b2e0e2ef86f0be45f4efa51ea794fbabff294c3c40199c450221c99707026bd1de3649c10c37a4c493fab1aa9511ed64bec38a1724c8af4a9813de028dcdc0bde1639a1b6a4b9ac0480cee494a533fff8214de959a9a6bc8c72
|
||||
q_minus_1 = d5eb7ff5b91f4068cd2739c0c5c4e609839e07b950307f55a5b5892d8ead0b3f77c8657204cc320e9b52d67af2eeec787dea098ece882abf6e93957ec1fb753f28e17de205a0e4967c7880ad9580b81a3a2315e3466f639a62162e4f0de8f009142bc19488510b2e0e2ef86f0be45f4efa51ea794fbabff294c3c40199c450221c99707026bd1de3649c10c37a4c493fab1aa9511ed64bec38a1724c8af4a9813de028dcdc0bde1639a1b6a4b9ac0480cee494a533fff8214de959a9a6bc8c70
|
Loading…
x
Reference in New Issue
Block a user