diff --git a/Cargo.lock b/Cargo.lock index da92a2b7..0ef1dc75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb08299a6046833a879ace115697f12fd2bd6c8d3e93c909ffc9e0738e7cae0" +checksum = "cc907c45bb7e9ef8fc3778defd0f3cd8c81288f1b4e748eba064948f20c47122" dependencies = [ "cpubits", "ctutils", diff --git a/Cargo.toml b/Cargo.toml index 956ed484..f6e9bd1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ exclude = ["checkct/", "marvin_toolkit/", "thirdparty/"] [dependencies] const-oid = { version = "0.10", default-features = false } -crypto-bigint = { version = "0.7.6", default-features = false, features = ["zeroize", "alloc"] } +crypto-bigint = { version = "0.7.7", default-features = false, features = ["zeroize", "alloc"] } crypto-primes = { version = "0.7", default-features = false } digest = { version = "0.11", default-features = false, features = ["alloc", "oid"] } rand_core = { version = "0.10", default-features = false } diff --git a/checkct/Cargo.lock b/checkct/Cargo.lock index 9b5ef0f3..8d4f8f96 100644 --- a/checkct/Cargo.lock +++ b/checkct/Cargo.lock @@ -43,9 +43,9 @@ checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" [[package]] name = "crypto-bigint" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb08299a6046833a879ace115697f12fd2bd6c8d3e93c909ffc9e0738e7cae0" +checksum = "cc907c45bb7e9ef8fc3778defd0f3cd8c81288f1b4e748eba064948f20c47122" dependencies = [ "cpubits", "ctutils", diff --git a/checkct/driver/src/raw_rsa.rs b/checkct/driver/src/raw_rsa.rs index 85caa376..f4642e54 100644 --- a/checkct/driver/src/raw_rsa.rs +++ b/checkct/driver/src/raw_rsa.rs @@ -5,7 +5,7 @@ use checkct_macros::checkct; use core::hint::black_box; use crypto_bigint::{ modular::{BoxedMontyForm, BoxedMontyParams, MontyParams}, - BoxedUint, NonZero, + BoxedUint, NonZero, Odd, }; use rsa::{ hazmat::rsa_decrypt, @@ -69,7 +69,7 @@ impl PrivateKeyParts for NonCrtKey { &self.d } - fn primes(&self) -> &[BoxedUint] { + fn primes(&self) -> &[Odd] { &[] } diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 10911363..cec673f2 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -119,8 +119,8 @@ pub fn rsa_decrypt( // (m1 - m2) mod p = (m1 mod p) - (m2 mod p) mod p let m2_mod_p = match p_params.bits_precision().cmp(&q_params.bits_precision()) { Ordering::Less => { - let p_wide = NonZero::new(priv_key.primes()[0].clone()) - .expect("`p` is non-zero") + let p_wide = priv_key.primes()[0] + .as_nz_ref() .resize_unchecked(q_params.bits_precision()); (&m2 % p_wide).resize_unchecked(p_params.bits_precision()) } @@ -138,7 +138,7 @@ pub fn rsa_decrypt( // m = m2 + h.q let m2 = m2.try_resize(n.bits_precision()).ok_or(Error::Internal)?; let hq = h - .concatenating_mul(&priv_key.primes()[1]) + .concatenating_mul(priv_key.primes()[1].as_ref()) .try_resize(n.bits_precision()) .ok_or(Error::Internal)?; m2.wrapping_add(&hq) diff --git a/src/encoding.rs b/src/encoding.rs index c4c6cac4..0d3d0d37 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -109,13 +109,13 @@ impl pkcs1::EncodeRsaPrivateKey for RsaPrivateKey { let exponent1 = Zeroizing::new( (self.d() - % NonZero::new((&self.primes[0]).resize_unchecked(bits) - &BoxedUint::one()) + % NonZero::new(self.primes[0].as_ref().resize_unchecked(bits) - &BoxedUint::one()) .unwrap()) .to_be_bytes(), ); let exponent2 = Zeroizing::new( (self.d() - % NonZero::new((&self.primes[1]).resize_unchecked(bits) - &BoxedUint::one()) + % NonZero::new(self.primes[1].as_ref().resize_unchecked(bits) - &BoxedUint::one()) .unwrap()) .to_be_bytes(), ); diff --git a/src/key.rs b/src/key.rs index 28d7701a..c2a5b931 100644 --- a/src/key.rs +++ b/src/key.rs @@ -38,7 +38,7 @@ pub struct RsaPublicKey { /// Public exponent: power to which a plaintext message is raised in /// order to encrypt it. /// - /// Typically `0x10001` (`65537`) + /// The recommended value is `0x10001` (`65537`). e: BoxedUint, n_params: BoxedMontyParams, @@ -71,7 +71,7 @@ pub struct RsaPrivateKey { /// Private exponent pub(crate) d: BoxedUint, /// Prime factors of N, contains >= 2 elements. - pub(crate) primes: Vec, + pub(crate) primes: Vec>, /// Precomputed values to speed up private operations pub(crate) precomputed: Option, } @@ -424,9 +424,11 @@ impl RsaPrivateKey { .into_iter() .map(|p| { let p_bits = p.bits(); - p.resize_unchecked(p_bits) + Odd::new(p.resize_unchecked(p_bits)) + .into_option() + .ok_or(Error::InvalidPrime) }) - .collect(); + .collect::>>()?; let k = RsaPrivateKey { pubkey_components: RsaPublicKey { @@ -589,14 +591,8 @@ impl RsaPrivateKey { let p = self.primes[0].clone(); let q = self.primes[1].clone(); - let p_odd = Odd::new(p.clone()) - .into_option() - .ok_or(Error::InvalidPrime)?; - let p_params = BoxedMontyParams::new(p_odd); - let q_odd = Odd::new(q.clone()) - .into_option() - .ok_or(Error::InvalidPrime)?; - let q_params = BoxedMontyParams::new(q_odd); + let p_params = BoxedMontyParams::new(p.clone()); + let q_params = BoxedMontyParams::new(q.clone()); let x = NonZero::new(p.wrapping_sub(BoxedUint::one())) .into_option() @@ -611,16 +607,10 @@ impl RsaPrivateKey { // Note that since `p` and `q` may have different `bits_precision`, // so we have to equalize them to calculate the remainder. let q_mod_p = match p.bits_precision().cmp(&q.bits_precision()) { - Ordering::Less => (&q - % NonZero::new(p.clone()) - .expect("`p` is non-zero") - .resize_unchecked(q.bits_precision())) - .resize_unchecked(p.bits_precision()), - Ordering::Greater => { - (&q).resize_unchecked(p.bits_precision()) - % &NonZero::new(p.clone()).expect("`p` is non-zero") - } - Ordering::Equal => &q % NonZero::new(p.clone()).expect("`p` is non-zero"), + Ordering::Less => (q.as_ref() % p.as_nz_ref().resize_unchecked(q.bits_precision())) + .resize_unchecked(p.bits_precision()), + Ordering::Greater => q.as_ref().resize_unchecked(p.bits_precision()) % p.as_nz_ref(), + Ordering::Equal => q.as_ref() % p.as_nz_ref(), }; let q_mod_p = BoxedMontyForm::new(q_mod_p, &p_params); @@ -649,8 +639,7 @@ impl RsaPrivateKey { pub fn crt_coefficient(&self) -> Option { let p = &self.primes[0]; let q = &self.primes[1]; - // TODO: maybe store primes as `NonZero`? - Option::from(q.invert_mod(&NonZero::new(p.clone()).expect("prime"))) + Option::from(q.invert_odd_mod(p)) } /// Performs basic sanity checks on the key. @@ -713,7 +702,7 @@ impl PrivateKeyParts for RsaPrivateKey { &self.d } - fn primes(&self) -> &[BoxedUint] { + fn primes(&self) -> &[Odd] { &self.primes } @@ -797,10 +786,10 @@ fn validate_private_key_parts(key: &RsaPrivateKey) -> Result<()> { let one = BoxedUint::one(); for prime in &key.primes { // Any primes ≤ 1 will cause divide-by-zero panics later. - if prime <= &one { + if prime.as_ref() <= &one { return Err(Error::InvalidPrime); } - m = m.wrapping_mul(prime); + m = m.wrapping_mul(prime.as_ref()); } if m != *key.pubkey_components.n { return Err(Error::InvalidModulus); @@ -1212,7 +1201,10 @@ mod tests { let ref_key = RsaPrivateKey::from_pkcs8_der(RSA_2048_PRIV_DER).unwrap(); assert_eq!(ref_key.validate(), Ok(())); - let primes = PrivateKeyParts::primes(&ref_key).to_vec(); + let primes: Vec<_> = PrivateKeyParts::primes(&ref_key) + .iter() + .map(|p| p.as_ref().clone()) + .collect(); let exp = PublicKeyParts::e(&ref_key); let key = RsaPrivateKey::from_primes(primes, exp.clone()) @@ -1235,7 +1227,10 @@ mod tests { let ref_key = RsaPrivateKey::from_pkcs8_der(RSA_2048_SP800_PRIV_DER).unwrap(); assert_eq!(ref_key.validate(), Ok(())); - let primes = PrivateKeyParts::primes(&ref_key).to_vec(); + let primes: Vec<_> = PrivateKeyParts::primes(&ref_key) + .iter() + .map(|p| p.as_ref().clone()) + .collect(); let exp = PublicKeyParts::e(&ref_key); let key = RsaPrivateKey::from_p_q(primes[0].clone(), primes[1].clone(), exp.clone()) diff --git a/src/traits/keys.rs b/src/traits/keys.rs index e07fc3c3..e625588d 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -4,7 +4,7 @@ use crate::key::SecretPrime; use alloc::boxed::Box; use crypto_bigint::{ modular::{BoxedMontyForm, BoxedMontyParams}, - BoxedUint, NonZero, + BoxedUint, NonZero, Odd, }; use zeroize::Zeroize; @@ -51,8 +51,8 @@ pub trait PrivateKeyParts: PublicKeyParts { /// Returns the private exponent of the key. fn d(&self) -> &BoxedUint; - /// Returns the prime factors. - fn primes(&self) -> &[BoxedUint]; + /// Returns the odd prime factors. + fn primes(&self) -> &[Odd]; /// Returns prime `p` if precomputed. fn p(&self) -> Option<&SecretPrime>; diff --git a/tests/pkcs1.rs b/tests/pkcs1.rs index b6384720..95539a1e 100644 --- a/tests/pkcs1.rs +++ b/tests/pkcs1.rs @@ -91,7 +91,7 @@ fn decode_rsa2048_priv_der() { 1024, ) .unwrap(); - assert!(bool::from(key.primes()[0].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[0].as_ref().ct_eq(&expected_prime))); let expected_prime = BoxedUint::from_be_slice( &hex!( @@ -103,7 +103,7 @@ fn decode_rsa2048_priv_der() { 1024, ) .unwrap(); - assert!(bool::from(key.primes()[1].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[1].as_ref().ct_eq(&expected_prime))); } #[test] @@ -170,7 +170,7 @@ fn decode_rsa4096_priv_der() { 2048, ) .unwrap(); - assert!(bool::from(key.primes()[0].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[0].as_ref().ct_eq(&expected_prime))); let expected_prime = BoxedUint::from_be_slice( &hex!( @@ -186,7 +186,7 @@ fn decode_rsa4096_priv_der() { 2048, ) .unwrap(); - assert!(bool::from(key.primes()[1].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[1].as_ref().ct_eq(&expected_prime))); } #[test] @@ -317,7 +317,7 @@ fn decode_rsa2048_priv_pem() { 1024, ) .unwrap(); - assert!(bool::from(key.primes()[0].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[0].as_ref().ct_eq(&expected_prime))); let expected_prime = BoxedUint::from_be_slice( &hex!( @@ -329,7 +329,7 @@ fn decode_rsa2048_priv_pem() { 1024, ) .unwrap(); - assert!(bool::from(key.primes()[1].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[1].as_ref().ct_eq(&expected_prime))); } #[test] @@ -398,7 +398,7 @@ fn decode_rsa4096_priv_pem() { 2048, ) .unwrap(); - assert!(bool::from(key.primes()[0].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[0].as_ref().ct_eq(&expected_prime))); let expected_prime = BoxedUint::from_be_slice( &hex!( @@ -414,7 +414,7 @@ fn decode_rsa4096_priv_pem() { 2048, ) .unwrap(); - assert!(bool::from(key.primes()[1].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[1].as_ref().ct_eq(&expected_prime))); } #[test] diff --git a/tests/pkcs8.rs b/tests/pkcs8.rs index e63f0b0e..b476f3aa 100644 --- a/tests/pkcs8.rs +++ b/tests/pkcs8.rs @@ -79,7 +79,7 @@ fn decode_rsa2048_priv_der() { 1024, ) .unwrap(); - assert!(bool::from(key.primes()[0].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[0].as_ref().ct_eq(&expected_prime))); let expected_prime = BoxedUint::from_be_slice( &hex!( @@ -91,7 +91,7 @@ fn decode_rsa2048_priv_der() { 1024, ) .unwrap(); - assert!(bool::from(key.primes()[1].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[1].as_ref().ct_eq(&expected_prime))); let _ = pkcs1v15::SigningKey::::from_pkcs8_der(RSA_2048_PRIV_DER).unwrap(); } @@ -163,7 +163,7 @@ fn decode_rsa2048_pss_priv_der() { 1024, ) .unwrap(); - assert!(bool::from(key.primes()[0].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[0].as_ref().ct_eq(&expected_prime))); let expected_prime = BoxedUint::from_be_slice( &hex!( @@ -175,7 +175,7 @@ fn decode_rsa2048_pss_priv_der() { 1024, ) .unwrap(); - assert!(bool::from(key.primes()[1].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[1].as_ref().ct_eq(&expected_prime))); let _ = pss::SigningKey::::from_pkcs8_der(RSA_2048_PSS_PRIV_DER).unwrap(); } @@ -270,7 +270,7 @@ fn decode_rsa2048_priv_pem() { 1024, ) .unwrap(); - assert!(bool::from(key.primes()[0].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[0].as_ref().ct_eq(&expected_prime))); let expected_prime = BoxedUint::from_be_slice( &hex!( @@ -282,7 +282,7 @@ fn decode_rsa2048_priv_pem() { 1024, ) .unwrap(); - assert!(bool::from(key.primes()[1].ct_eq(&expected_prime))); + assert!(bool::from(key.primes()[1].as_ref().ct_eq(&expected_prime))); let _ = pkcs1v15::SigningKey::::from_pkcs8_pem(RSA_2048_PRIV_PEM).unwrap(); }