From fcc3577e7c023a10b7ed57a917ef36099ca1d744 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Wed, 29 Nov 2023 14:23:01 +0100 Subject: [PATCH 01/51] implement minimal decryption routine using BoxedUint --- Cargo.lock | 29 +++++++++ Cargo.toml | 1 + src/algorithms/rsa.rs | 142 +++++++++++++++++++++++++++++++++++++++++- src/pkcs1v15.rs | 42 ++++++++++++- 4 files changed, 212 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 54a10497..6a435700 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64ct" version = "1.6.0" @@ -116,6 +122,18 @@ dependencies = [ "libc", ] +[[package]] +name = "crypto-bigint" +version = "0.6.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b60cb3dc0bfcdf8199b7eabd5df62f7b7af001c7da89b89eba17ebf3fea01638" +dependencies = [ + "rand_core", + "serdect", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -469,6 +487,7 @@ version = "0.9.5" dependencies = [ "base64ct", "const-oid", + "crypto-bigint", "digest", "hex-literal", "num-bigint-dig", @@ -566,6 +585,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha1" version = "0.10.6" diff --git a/Cargo.toml b/Cargo.toml index 13ceb3c6..47d1db5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ pkcs8 = { version = "0.10.2", default-features = false, features = ["alloc"] } signature = { version = ">2.0, <2.3", default-features = false , features = ["alloc", "digest", "rand_core"] } spki = { version = "0.7.2", default-features = false, features = ["alloc"] } zeroize = { version = "1.5", features = ["alloc"] } +crypto-bigint = { version = "0.6.0-pre.0", features = ["zeroize", "alloc"] } # optional dependencies sha1 = { version = "0.10.5", optional = true, default-features = false, features = ["oid"] } diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 35101526..8a630d24 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -1,11 +1,16 @@ //! Generic RSA implementation +use core::cmp::Ordering; + use alloc::borrow::Cow; use alloc::vec::Vec; +use crypto_bigint::modular::{BoxedResidue, BoxedResidueParams}; +use crypto_bigint::{BoxedUint, Limb, NonZero, Zero}; use num_bigint::{BigInt, BigUint, IntoBigInt, IntoBigUint, ModInverse, RandBigInt, ToBigInt}; use num_integer::{sqrt, Integer}; -use num_traits::{FromPrimitive, One, Pow, Signed, Zero}; +use num_traits::{FromPrimitive, One, Pow, Signed, Zero as _}; use rand_core::CryptoRngCore; +use subtle::CtOption; use zeroize::{Zeroize, Zeroizing}; use crate::errors::{Error, Result}; @@ -150,6 +155,24 @@ pub fn rsa_decrypt_and_check( Ok(m) } +pub fn rsa_decrypt_and_check_new( + priv_key: &impl PrivateKeyParts, + rng: Option<&mut R>, + c: &BigUint, +) -> Result { + let m = rsa_decrypt_new(rng, priv_key, c)?; + + // In order to defend against errors in the CRT computation, m^e is + // calculated, which should match the original ciphertext. + let check = rsa_encrypt(priv_key, &m)?; + + if c != &check { + return Err(Error::Internal); + } + + Ok(m) +} + /// Returns the blinded c, along with the unblinding factor. fn blind( rng: &mut R, @@ -303,6 +326,123 @@ pub(crate) fn compute_private_exponent_carmicheal( } } +fn to_biguint(uint: &BoxedUint) -> BigUint { + BigUint::from_bytes_be(&uint.to_be_bytes()) +} + +fn to_uint(big_uint: BigUint) -> BoxedUint { + let bytes = big_uint.to_bytes_be(); + let pad_count = Limb::BYTES - (bytes.len() % Limb::BYTES); + let mut padded_bytes = vec![0u8; pad_count]; + padded_bytes.extend_from_slice(&bytes); + BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() * 8).unwrap() +} + +fn blind_new( + rng: &mut R, + key: &K, + c: &BoxedUint, +) -> (BoxedUint, BoxedUint) { + let n = NonZero::new(to_uint(key.n().clone())).unwrap(); + let mut r: BoxedUint; + let mut ir: CtOption; + let unblinder; + loop { + r = todo!(); // BoxedUint::random_mod(&mut rng, &n); + if r.is_zero().into() { + r = BoxedUint::one(); + } + ir = r.inv_mod(&n); + + // TODO: constant time? + if let Some(ir) = ir.into() { + unblinder = ir; + break; + } + } + + let n_params = BoxedResidueParams::new(n.get()).unwrap(); + let e = to_uint(key.e().clone()); + let c = { + let r = reduce(&r, n_params); + let rpowe = r.pow(&e).retrieve(); + + let c = c.wrapping_mul(&rpowe); + let c = c.rem_vartime(&n); + + rpowe.zeroize(); + + c + }; + + (c, unblinder) +} + +fn unblind_new(key: &impl PublicKeyParts, m: &BoxedUint, unblinder: &BoxedUint) -> BoxedUint { + let n = to_uint(key.n().clone()); + let n = NonZero::new(n).expect("should have been checked before"); + let a = m.wrapping_mul(unblinder); + a.rem_vartime(&n) +} + +fn reduce(n: &BoxedUint, p: BoxedResidueParams) -> BoxedResidue { + let bits_precision = p.modulus().bits_precision(); + let modulus = NonZero::new(p.modulus().clone()).unwrap(); + + let n = match n.bits_precision().cmp(&bits_precision) { + Ordering::Less => n.widen(bits_precision), + Ordering::Equal => n.clone(), + Ordering::Greater => n.shorten(bits_precision), + }; + + let n_reduced = n.rem_vartime(&modulus).widen(p.bits_precision()); + BoxedResidue::new(&n_reduced, p) +} + +pub fn rsa_decrypt_new( + mut rng: Option<&mut R>, + priv_key: &impl PrivateKeyParts, + c: &BigUint, +) -> Result { + // convert to crypto bigint + let c = to_uint(c.clone()); + let n = to_uint(priv_key.n().clone()); + let d = to_uint(priv_key.d().clone()); + + if c >= n { + return Err(Error::Decryption); + } + + // TODO: is this fine? + if n.is_zero().into() { + return Err(Error::Decryption); + } + + let mut ir = None; + + let c = if let Some(ref mut rng) = rng { + let (blinded, unblinder) = blind_new(rng, priv_key, &c); + ir = Some(unblinder); + blinded + } else { + c + }; + + // TODO: fast path with precalculated values; + let n_params = BoxedResidueParams::new(n).unwrap(); + let c = reduce(&c, n_params); + let m = c.pow(&d).retrieve(); + + match ir { + Some(ref ir) => { + // unblind + let m = unblind_new(priv_key, &m, ir); + Ok(to_biguint(&m)) + } + None => Ok(to_biguint(&m)), + } +} + #[cfg(test)] mod tests { use num_traits::FromPrimitive; diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index 4600aeb4..a5c247a0 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -27,7 +27,7 @@ use zeroize::Zeroizing; use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; use crate::algorithms::pkcs1v15::*; -use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; +use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_decrypt_and_check_new, rsa_encrypt}; use crate::errors::{Error, Result}; use crate::key::{self, RsaPrivateKey, RsaPublicKey}; use crate::traits::{PaddingScheme, PublicKeyParts, SignatureScheme}; @@ -172,6 +172,20 @@ fn decrypt( pkcs1v15_encrypt_unpad(em, priv_key.size()) } +#[inline] +fn decrypt_new( + rng: Option<&mut R>, + priv_key: &RsaPrivateKey, + ciphertext: &[u8], +) -> Result> { + key::check_public(priv_key)?; + + let em = rsa_decrypt_and_check_new(priv_key, rng, &BigUint::from_bytes_be(ciphertext))?; + let em = uint_to_zeroizing_be_pad(em, priv_key.size())?; + + pkcs1v15_encrypt_unpad(em, priv_key.size()) +} + /// Calculates the signature of hashed using /// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5. Note that `hashed` must /// be the result of hashing the input message using the given hash @@ -357,6 +371,32 @@ mod tests { } } + #[test] + fn test_new_encrypt_decrypt_pkcs1v15() { + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let priv_key = get_private_key(); + let k = priv_key.size(); + + for i in 1..100 { + let mut input = vec![0u8; i * 8]; + rng.fill_bytes(&mut input); + if input.len() > k - 11 { + input = input[0..k - 11].to_vec(); + } + + let pub_key: RsaPublicKey = priv_key.clone().into(); + let ciphertext = encrypt(&mut rng, &pub_key, &input).unwrap(); + assert_ne!(input, ciphertext); + + let blind: bool = rng.next_u32() < (1u32 << 31); + // TODO: + // let blinder = if blind { Some(&mut rng) } else { None }; + let blinder: Option<&mut ChaCha8Rng> = None; + let plaintext = decrypt_new(blinder, &priv_key, &ciphertext).unwrap(); + assert_eq!(input, plaintext); + } + } + #[test] fn test_decrypt_pkcs1v15_traits() { let priv_key = get_private_key(); From bc929946c4627b3b864af53c6adc7c84f978436b Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Wed, 29 Nov 2023 16:06:14 +0100 Subject: [PATCH 02/51] convert internals to use crypto-bigint --- src/algorithms/rsa.rs | 65 ++++--------- src/encoding.rs | 11 ++- src/key.rs | 208 +++++++++++++++++++++++++++--------------- src/pkcs1v15.rs | 2 +- src/pss.rs | 2 +- src/traits/keys.rs | 132 +++++++++++++++++++++++++-- 6 files changed, 284 insertions(+), 136 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 8a630d24..f290402b 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -1,11 +1,9 @@ //! Generic RSA implementation -use core::cmp::Ordering; - use alloc::borrow::Cow; use alloc::vec::Vec; -use crypto_bigint::modular::{BoxedResidue, BoxedResidueParams}; -use crypto_bigint::{BoxedUint, Limb, NonZero, Zero}; +use crypto_bigint::modular::BoxedResidueParams; +use crypto_bigint::{BoxedUint, NonZero, Zero}; use num_bigint::{BigInt, BigUint, IntoBigInt, IntoBigUint, ModInverse, RandBigInt, ToBigInt}; use num_integer::{sqrt, Integer}; use num_traits::{FromPrimitive, One, Pow, Signed, Zero as _}; @@ -14,6 +12,8 @@ use subtle::CtOption; use zeroize::{Zeroize, Zeroizing}; use crate::errors::{Error, Result}; +use crate::key::{reduce, to_biguint, to_uint}; +use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew}; use crate::traits::{PrivateKeyParts, PublicKeyParts}; /// ⚠️ Raw RSA encryption of m with the public key. No padding is performed. @@ -24,7 +24,7 @@ use crate::traits::{PrivateKeyParts, PublicKeyParts}; /// or signature scheme. See the [module-level documentation][crate::hazmat] for more information. #[inline] pub fn rsa_encrypt(key: &K, m: &BigUint) -> Result { - Ok(m.modpow(key.e(), key.n())) + Ok(m.modpow(&key.e(), &key.n())) } /// ⚠️ Performs raw RSA decryption with no padding or error checking. @@ -41,7 +41,7 @@ pub fn rsa_decrypt( priv_key: &impl PrivateKeyParts, c: &BigUint, ) -> Result { - if c >= priv_key.n() { + if c >= &priv_key.n() { return Err(Error::Decryption); } @@ -71,8 +71,8 @@ pub fn rsa_decrypt( let p = &priv_key.primes()[0]; let q = &priv_key.primes()[1]; - let mut m = c.modpow(dp, p).into_bigint().unwrap(); - let mut m2 = c.modpow(dq, q).into_bigint().unwrap(); + let mut m = c.modpow(&dp, p).into_bigint().unwrap(); + let mut m2 = c.modpow(&dq, q).into_bigint().unwrap(); m -= &m2; @@ -115,7 +115,7 @@ pub fn rsa_decrypt( m.into_biguint().expect("failed to decrypt") } - _ => c.modpow(priv_key.d(), priv_key.n()), + _ => c.modpow(&priv_key.d(), &priv_key.n()), }; match ir { @@ -156,7 +156,7 @@ pub fn rsa_decrypt_and_check( } pub fn rsa_decrypt_and_check_new( - priv_key: &impl PrivateKeyParts, + priv_key: &impl PrivateKeyPartsNew, rng: Option<&mut R>, c: &BigUint, ) -> Result { @@ -188,7 +188,7 @@ fn blind( let mut ir: Option; let unblinder; loop { - r = rng.gen_biguint_below(key.n()); + r = rng.gen_biguint_below(&key.n()); if r.is_zero() { r = BigUint::one(); } @@ -202,7 +202,7 @@ fn blind( } let c = { - let mut rpowe = r.modpow(key.e(), key.n()); // N != 0 + let mut rpowe = r.modpow(&key.e(), &key.n()); // N != 0 let mut c = c * &rpowe; c %= key.n(); @@ -326,18 +326,6 @@ pub(crate) fn compute_private_exponent_carmicheal( } } -fn to_biguint(uint: &BoxedUint) -> BigUint { - BigUint::from_bytes_be(&uint.to_be_bytes()) -} - -fn to_uint(big_uint: BigUint) -> BoxedUint { - let bytes = big_uint.to_bytes_be(); - let pad_count = Limb::BYTES - (bytes.len() % Limb::BYTES); - let mut padded_bytes = vec![0u8; pad_count]; - padded_bytes.extend_from_slice(&bytes); - BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() * 8).unwrap() -} - fn blind_new( rng: &mut R, key: &K, @@ -378,38 +366,23 @@ fn blind_new( (c, unblinder) } -fn unblind_new(key: &impl PublicKeyParts, m: &BoxedUint, unblinder: &BoxedUint) -> BoxedUint { - let n = to_uint(key.n().clone()); - let n = NonZero::new(n).expect("should have been checked before"); +fn unblind_new(key: &impl PublicKeyPartsNew, m: &BoxedUint, unblinder: &BoxedUint) -> BoxedUint { + let n = key.n(); let a = m.wrapping_mul(unblinder); a.rem_vartime(&n) } -fn reduce(n: &BoxedUint, p: BoxedResidueParams) -> BoxedResidue { - let bits_precision = p.modulus().bits_precision(); - let modulus = NonZero::new(p.modulus().clone()).unwrap(); - - let n = match n.bits_precision().cmp(&bits_precision) { - Ordering::Less => n.widen(bits_precision), - Ordering::Equal => n.clone(), - Ordering::Greater => n.shorten(bits_precision), - }; - - let n_reduced = n.rem_vartime(&modulus).widen(p.bits_precision()); - BoxedResidue::new(&n_reduced, p) -} - pub fn rsa_decrypt_new( mut rng: Option<&mut R>, - priv_key: &impl PrivateKeyParts, + priv_key: &impl PrivateKeyPartsNew, c: &BigUint, ) -> Result { // convert to crypto bigint let c = to_uint(c.clone()); - let n = to_uint(priv_key.n().clone()); - let d = to_uint(priv_key.d().clone()); + let n = priv_key.n(); + let d = priv_key.d(); - if c >= n { + if c >= **n { return Err(Error::Decryption); } @@ -429,7 +402,7 @@ pub fn rsa_decrypt_new( }; // TODO: fast path with precalculated values; - let n_params = BoxedResidueParams::new(n).unwrap(); + let n_params = BoxedResidueParams::new(n.clone().get()).unwrap(); let c = reduce(&c, n_params); let m = c.pow(&d).retrieve(); diff --git a/src/encoding.rs b/src/encoding.rs index bc0fac2c..04faab82 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -4,6 +4,7 @@ //! `pkcs1` crate's traits for types which impl the `pkcs8` crate's traits. use crate::{ + key::to_biguint, traits::{PrivateKeyParts, PublicKeyParts}, BigUint, RsaPrivateKey, RsaPublicKey, }; @@ -72,10 +73,12 @@ impl EncodePrivateKey for RsaPrivateKey { let modulus = self.n().to_bytes_be(); let public_exponent = self.e().to_bytes_be(); let private_exponent = Zeroizing::new(self.d().to_bytes_be()); - let prime1 = Zeroizing::new(self.primes[0].to_bytes_be()); - let prime2 = Zeroizing::new(self.primes[1].to_bytes_be()); - let exponent1 = Zeroizing::new((self.d() % (&self.primes[0] - 1u8)).to_bytes_be()); - let exponent2 = Zeroizing::new((self.d() % (&self.primes[1] - 1u8)).to_bytes_be()); + let prime1 = Zeroizing::new(to_biguint(&self.primes[0]).to_bytes_be()); + let prime2 = Zeroizing::new(to_biguint(&self.primes[1]).to_bytes_be()); + let exponent1 = + Zeroizing::new((self.d() % (&to_biguint(&self.primes[0]) - 1u8)).to_bytes_be()); + let exponent2 = + Zeroizing::new((self.d() % (&to_biguint(&self.primes[1]) - 1u8)).to_bytes_be()); let coefficient = Zeroizing::new( self.crt_coefficient() .ok_or(pkcs1::Error::Crypto)? diff --git a/src/key.rs b/src/key.rs index 5e6de22f..8abcd96d 100644 --- a/src/key.rs +++ b/src/key.rs @@ -1,7 +1,9 @@ use alloc::vec::Vec; +use core::cmp::Ordering; use core::hash::{Hash, Hasher}; +use crypto_bigint::modular::{BoxedResidue, BoxedResidueParams}; +use crypto_bigint::{BoxedUint, Limb, NonZero}; use num_bigint::traits::ModInverse; -use num_bigint::Sign::Plus; use num_bigint::{BigInt, BigUint}; use num_integer::Integer; use num_traits::{FromPrimitive, One, ToPrimitive}; @@ -18,20 +20,30 @@ use crate::algorithms::rsa::{ use crate::dummy_rng::DummyRng; use crate::errors::{Error, Result}; +use crate::traits::keys::{CrtValueNew, PrivateKeyPartsNew, PublicKeyPartsNew}; use crate::traits::{PaddingScheme, PrivateKeyParts, PublicKeyParts, SignatureScheme}; -use crate::CrtValue; /// Represents the public part of an RSA key. -#[derive(Debug, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct RsaPublicKey { /// Modulus: product of prime numbers `p` and `q` - n: BigUint, + n: NonZero, /// Public exponent: power to which a plaintext message is raised in /// order to encrypt it. /// /// Typically 0x10001 (65537) - e: BigUint, + e: BoxedUint, +} + +// TODO: derive `Hash` impl when `BoxedUint` supports it +impl Hash for RsaPublicKey { + fn hash(&self, state: &mut H) { + // Domain separator for RSA private keys + state.write(b"RsaPublicKey"); + Hash::hash(&self.n.as_words(), state); + Hash::hash(&self.e.as_words(), state); + } } /// Represents a whole RSA key, public and private parts. @@ -41,9 +53,9 @@ pub struct RsaPrivateKey { /// Public components of the private key. pubkey_components: RsaPublicKey, /// Private exponent - pub(crate) d: BigUint, + 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 #[cfg_attr(feature = "serde", serde(skip))] pub(crate) precomputed: Option, @@ -86,17 +98,17 @@ impl ZeroizeOnDrop for RsaPrivateKey {} #[derive(Debug, Clone)] pub(crate) struct PrecomputedValues { /// D mod (P-1) - pub(crate) dp: BigUint, + pub(crate) dp: BoxedUint, /// D mod (Q-1) - pub(crate) dq: BigUint, + pub(crate) dq: BoxedUint, /// Q^-1 mod P - pub(crate) qinv: BigInt, + pub(crate) qinv: BoxedUint, /// CRTValues is used for the 3rd and subsequent primes. Due to a /// historical accident, the CRT for the first two primes is handled /// differently in PKCS#1 and interoperability is sufficiently /// important that we mirror this. - pub(crate) crt_values: Vec, + pub(crate) crt_values: Vec, } impl Zeroize for PrecomputedValues { @@ -125,18 +137,21 @@ impl From for RsaPublicKey { impl From<&RsaPrivateKey> for RsaPublicKey { fn from(private_key: &RsaPrivateKey) -> Self { - let n = private_key.n().clone(); - let e = private_key.e().clone(); - RsaPublicKey { n, e } + let n = PublicKeyPartsNew::n(private_key); + let e = PublicKeyPartsNew::e(private_key); + RsaPublicKey { + n: n.clone(), + e: e.clone(), + } } } -impl PublicKeyParts for RsaPublicKey { - fn n(&self) -> &BigUint { +impl PublicKeyPartsNew for RsaPublicKey { + fn n(&self) -> &NonZero { &self.n } - fn e(&self) -> &BigUint { + fn e(&self) -> &BoxedUint { &self.e } } @@ -183,7 +198,10 @@ impl RsaPublicKey { /// Create a new public key from its components. pub fn new_with_max_size(n: BigUint, e: BigUint, max_size: usize) -> Result { - let k = Self { n, e }; + let k = Self { + n: NonZero::new(to_uint(n)).unwrap(), + e: to_uint(e), + }; check_public_with_max_size(&k, max_size)?; Ok(k) } @@ -195,16 +213,19 @@ impl RsaPublicKey { /// Most applications should use [`RsaPublicKey::new`] or /// [`RsaPublicKey::new_with_max_size`] instead. pub fn new_unchecked(n: BigUint, e: BigUint) -> Self { - Self { n, e } + Self { + n: NonZero::new(to_uint(n)).unwrap(), + e: to_uint(e), + } } } -impl PublicKeyParts for RsaPrivateKey { - fn n(&self) -> &BigUint { +impl PublicKeyPartsNew for RsaPrivateKey { + fn n(&self) -> &NonZero { &self.pubkey_components.n } - fn e(&self) -> &BigUint { + fn e(&self) -> &BoxedUint { &self.pubkey_components.e } } @@ -252,6 +273,8 @@ impl RsaPrivateKey { mut primes: Vec, ) -> Result { let mut should_validate = false; + let mut primes: Vec<_> = primes.into_iter().map(to_uint).collect(); + if primes.len() < 2 { if !primes.is_empty() { return Err(Error::NprimesTooSmall); @@ -259,14 +282,17 @@ impl RsaPrivateKey { // Recover `p` and `q` from `d`. // See method in Appendix C.2: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf let (p, q) = recover_primes(&n, &e, &d)?; - primes.push(p); - primes.push(q); + primes.push(to_uint(p)); + primes.push(to_uint(q)); should_validate = true; } let mut k = RsaPrivateKey { - pubkey_components: RsaPublicKey { n, e }, - d, + pubkey_components: RsaPublicKey { + n: NonZero::new(to_uint(n)).unwrap(), + e: to_uint(e), + }, + d: to_uint(d), primes, precomputed: None, }; @@ -335,25 +361,26 @@ impl RsaPrivateKey { if self.precomputed.is_some() { return Ok(()); } + let d = to_biguint(&self.d); + let dp = &d % (&to_biguint(&self.primes[0]) - BigUint::one()); + let dq = &d % (&to_biguint(&self.primes[1]) - BigUint::one()); + let qinv = self.primes[1].inv_mod(&self.primes[0]); + if qinv.is_none().into() { + return Err(Error::InvalidPrime); + } + let qinv = qinv.unwrap(); - let dp = &self.d % (&self.primes[0] - BigUint::one()); - let dq = &self.d % (&self.primes[1] - BigUint::one()); - let qinv = self.primes[1] - .clone() - .mod_inverse(&self.primes[0]) - .ok_or(Error::InvalidPrime)?; - - let mut r: BigUint = &self.primes[0] * &self.primes[1]; - let crt_values: Vec = { + let mut r: BigUint = &to_biguint(&self.primes[0]) * &to_biguint(&self.primes[1]); + let crt_values: Vec = { let mut values = Vec::with_capacity(self.primes.len() - 2); for prime in &self.primes[2..] { - let res = CrtValue { - exp: BigInt::from_biguint(Plus, &self.d % (prime - BigUint::one())), - r: BigInt::from_biguint(Plus, r.clone()), - coeff: BigInt::from_biguint( - Plus, + let prime = to_biguint(prime); + let res = CrtValueNew { + exp: to_uint(&d % (&prime - BigUint::one())), + r: to_uint(r.clone()), + coeff: to_uint( r.clone() - .mod_inverse(prime) + .mod_inverse(&prime) .ok_or(Error::InvalidCoefficient)? .to_biguint() .unwrap(), @@ -367,8 +394,8 @@ impl RsaPrivateKey { }; self.precomputed = Some(PrecomputedValues { - dp, - dq, + dp: to_uint(dp), + dq: to_uint(dq), qinv, crt_values, }); @@ -383,7 +410,9 @@ impl RsaPrivateKey { /// Compute CRT coefficient: `(1/q) mod p`. pub fn crt_coefficient(&self) -> Option { - (&self.primes[1]).mod_inverse(&self.primes[0])?.to_biguint() + (&to_biguint(&self.primes[1])) + .mod_inverse(&to_biguint(&self.primes[0]))? + .to_biguint() } /// Performs basic sanity checks on the key. @@ -394,13 +423,14 @@ impl RsaPrivateKey { // Check that Πprimes == n. let mut m = BigUint::one(); for prime in &self.primes { + let prime = to_biguint(&prime); // Any primes ≤ 1 will cause divide-by-zero panics later. - if *prime < BigUint::one() { + if prime < BigUint::one() { return Err(Error::InvalidPrime); } m *= prime; } - if m != self.pubkey_components.n { + if m != to_biguint(&self.pubkey_components.n) { return Err(Error::InvalidModulus); } @@ -409,9 +439,11 @@ impl RsaPrivateKey { // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) = // exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1 // mod p. Thus a^de ≡ a mod n for all a coprime to n, as required. - let mut de = self.e().clone(); - de *= self.d.clone(); + let mut de = PublicKeyParts::e(self); + de *= PrivateKeyParts::d(self); + for prime in &self.primes { + let prime = to_biguint(&prime); let congruence: BigUint = &de % (prime - BigUint::one()); if !congruence.is_one() { return Err(Error::InvalidExponent); @@ -463,29 +495,28 @@ impl RsaPrivateKey { } } -impl PrivateKeyParts for RsaPrivateKey { - fn d(&self) -> &BigUint { +impl PrivateKeyPartsNew for RsaPrivateKey { + fn d(&self) -> &BoxedUint { &self.d } - fn primes(&self) -> &[BigUint] { + fn primes(&self) -> &[BoxedUint] { &self.primes } - fn dp(&self) -> Option<&BigUint> { + fn dp(&self) -> Option<&BoxedUint> { self.precomputed.as_ref().map(|p| &p.dp) } - fn dq(&self) -> Option<&BigUint> { + fn dq(&self) -> Option<&BoxedUint> { self.precomputed.as_ref().map(|p| &p.dq) } - fn qinv(&self) -> Option<&BigInt> { + fn qinv(&self) -> Option<&BoxedUint> { self.precomputed.as_ref().map(|p| &p.qinv) } - fn crt_values(&self) -> Option<&[CrtValue]> { - /* for some reason the standard self.precomputed.as_ref().map() doesn't work */ + fn crt_values(&self) -> Option<&[CrtValueNew]> { if let Some(p) = &self.precomputed { Some(p.crt_values.as_slice()) } else { @@ -531,10 +562,37 @@ fn check_public_with_max_size(public_key: &impl PublicKeyParts, max_size: usize) Ok(()) } +pub(crate) fn to_biguint(uint: &BoxedUint) -> BigUint { + BigUint::from_bytes_be(&uint.to_be_bytes()) +} + +pub(crate) fn to_uint(big_uint: BigUint) -> BoxedUint { + let bytes = big_uint.to_bytes_be(); + let pad_count = Limb::BYTES - (bytes.len() % Limb::BYTES); + let mut padded_bytes = vec![0u8; pad_count]; + padded_bytes.extend_from_slice(&bytes); + BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() * 8).unwrap() +} + +pub(crate) fn reduce(n: &BoxedUint, p: BoxedResidueParams) -> BoxedResidue { + let bits_precision = p.modulus().bits_precision(); + let modulus = NonZero::new(p.modulus().clone()).unwrap(); + + let n = match n.bits_precision().cmp(&bits_precision) { + Ordering::Less => n.widen(bits_precision), + Ordering::Equal => n.clone(), + Ordering::Greater => n.shorten(bits_precision), + }; + + let n_reduced = n.rem_vartime(&modulus).widen(p.bits_precision()); + BoxedResidue::new(&n_reduced, p) +} + #[cfg(test)] mod tests { use super::*; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; + use crate::traits::PublicKeyParts; use hex_literal::hex; use num_traits::{FromPrimitive, ToPrimitive}; @@ -545,24 +603,24 @@ mod tests { fn test_from_into() { let private_key = RsaPrivateKey { pubkey_components: RsaPublicKey { - n: BigUint::from_u64(100).unwrap(), - e: BigUint::from_u64(200).unwrap(), + n: NonZero::new(to_uint(BigUint::from_u64(100).unwrap())).unwrap(), + e: to_uint(BigUint::from_u64(200).unwrap()), }, - d: BigUint::from_u64(123).unwrap(), + d: to_uint(BigUint::from_u64(123).unwrap()), primes: vec![], precomputed: None, }; let public_key: RsaPublicKey = private_key.into(); - assert_eq!(public_key.n().to_u64(), Some(100)); - assert_eq!(public_key.e().to_u64(), Some(200)); + assert_eq!(PublicKeyParts::n(&public_key).to_u64(), Some(100)); + assert_eq!(PublicKeyParts::e(&public_key).to_u64(), Some(200)); } fn test_key_basics(private_key: &RsaPrivateKey) { private_key.validate().expect("invalid private key"); assert!( - private_key.d() < private_key.n(), + PrivateKeyParts::d(private_key) < PublicKeyParts::n(private_key), "private exponent too large" ); @@ -595,7 +653,7 @@ mod tests { components.primes, ) .unwrap(); - assert_eq!(private_key.n().bits(), $size); + assert_eq!(PublicKeyParts::n(&private_key).bits(), $size); test_key_basics(&private_key); } @@ -804,19 +862,19 @@ mod tests { let ref_key = RsaPrivateKey::from_pkcs8_der(RSA_2048_PRIV_DER).unwrap(); assert_eq!(ref_key.validate(), Ok(())); - let primes = ref_key.primes().to_vec(); + let primes = PrivateKeyParts::primes(&ref_key).to_vec(); - let exp = ref_key.e().clone(); + let exp = PublicKeyParts::e(&ref_key); let key = RsaPrivateKey::from_primes(primes, exp).expect("failed to import key from primes"); assert_eq!(key.validate(), Ok(())); - assert_eq!(key.n(), ref_key.n()); + assert_eq!(PublicKeyParts::n(&key), PublicKeyParts::n(&ref_key)); - assert_eq!(key.dp(), ref_key.dp()); - assert_eq!(key.dq(), ref_key.dq()); + assert_eq!(PrivateKeyParts::dp(&key), PrivateKeyParts::dp(&ref_key)); + assert_eq!(PrivateKeyParts::dq(&key), PrivateKeyParts::dq(&ref_key)); - assert_eq!(key.d(), ref_key.d()); + assert_eq!(PrivateKeyParts::d(&key), PrivateKeyParts::d(&ref_key)); } #[test] @@ -826,18 +884,18 @@ mod tests { let ref_key = RsaPrivateKey::from_pkcs8_der(RSA_2048_SP800_PRIV_DER).unwrap(); assert_eq!(ref_key.validate(), Ok(())); - let primes = ref_key.primes().to_vec(); - let exp = ref_key.e().clone(); + let primes = PrivateKeyParts::primes(&ref_key).to_vec(); + let exp = PublicKeyParts::e(&ref_key); let key = RsaPrivateKey::from_p_q(primes[0].clone(), primes[1].clone(), exp) .expect("failed to import key from primes"); assert_eq!(key.validate(), Ok(())); - assert_eq!(key.n(), ref_key.n()); + assert_eq!(PublicKeyParts::n(&key), PublicKeyParts::n(&ref_key)); - assert_eq!(key.dp(), ref_key.dp()); - assert_eq!(key.dq(), ref_key.dq()); + assert_eq!(PrivateKeyParts::dp(&key), PrivateKeyParts::dp(&ref_key)); + assert_eq!(PrivateKeyParts::dq(&key), PrivateKeyParts::dq(&ref_key)); - assert_eq!(key.d(), ref_key.d()); + assert_eq!(PrivateKeyParts::d(&key), PrivateKeyParts::d(&ref_key)); } } diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index a5c247a0..d3a47be4 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -223,7 +223,7 @@ fn verify( sig: &BigUint, sig_len: usize, ) -> Result<()> { - if sig >= pub_key.n() || sig_len != pub_key.size() { + if sig >= &pub_key.n() || sig_len != pub_key.size() { return Err(Error::Verification); } diff --git a/src/pss.rs b/src/pss.rs index dd6ebcc1..c7535872 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -150,7 +150,7 @@ pub(crate) fn verify_digest( where D: Digest + FixedOutputReset, { - if sig >= pub_key.n() || sig_len != pub_key.size() { + if sig >= &pub_key.n() || sig_len != pub_key.size() { return Err(Error::Verification); } diff --git a/src/traits/keys.rs b/src/traits/keys.rs index b218c896..9d7b8d5a 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -1,15 +1,20 @@ //! Traits related to the key components -use num_bigint::{BigInt, BigUint}; +use alloc::vec::Vec; + +use crypto_bigint::{BoxedUint, NonZero}; +use num_bigint::{BigInt, BigUint, IntoBigInt}; use zeroize::Zeroize; +use crate::key::to_biguint; + /// Components of an RSA public key. pub trait PublicKeyParts { /// Returns the modulus of the key. - fn n(&self) -> &BigUint; + fn n(&self) -> BigUint; /// Returns the public exponent of the key. - fn e(&self) -> &BigUint; + fn e(&self) -> BigUint; /// Returns the modulus size in bytes. Raw signatures and ciphertexts for /// or by this public key will have the same size. @@ -18,25 +23,120 @@ pub trait PublicKeyParts { } } +pub trait PublicKeyPartsNew { + /// Returns the modulus of the key. + fn n(&self) -> &NonZero; + + /// Returns the public exponent of the key. + fn e(&self) -> &BoxedUint; + + /// Returns the modulus size in bytes. Raw signatures and ciphertexts for + /// or by this public key will have the same size. + fn size(&self) -> usize { + (self.n().bits() + 7) / 8 + } +} + +impl PublicKeyParts for T { + fn n(&self) -> BigUint { + to_biguint(&PublicKeyPartsNew::n(self).clone().get()) + } + + fn e(&self) -> BigUint { + to_biguint(PublicKeyPartsNew::e(self)) + } + + fn size(&self) -> usize { + PublicKeyPartsNew::size(self) + } +} + /// Components of an RSA private key. pub trait PrivateKeyParts: PublicKeyParts { /// Returns the private exponent of the key. - fn d(&self) -> &BigUint; + fn d(&self) -> BigUint; /// Returns the prime factors. - fn primes(&self) -> &[BigUint]; + fn primes(&self) -> Vec; /// Returns the precomputed dp value, D mod (P-1) - fn dp(&self) -> Option<&BigUint>; + fn dp(&self) -> Option; /// Returns the precomputed dq value, D mod (Q-1) - fn dq(&self) -> Option<&BigUint>; + fn dq(&self) -> Option; /// Returns the precomputed qinv value, Q^-1 mod P - fn qinv(&self) -> Option<&BigInt>; + fn qinv(&self) -> Option; /// Returns an iterator over the CRT Values - fn crt_values(&self) -> Option<&[CrtValue]>; + fn crt_values(&self) -> Option>; +} + +/// Components of an RSA private key. +impl PrivateKeyParts for T { + fn d(&self) -> BigUint { + to_biguint(PrivateKeyPartsNew::d(self)) + } + fn primes(&self) -> Vec { + PrivateKeyPartsNew::primes(self) + .iter() + .map(to_biguint) + .collect() + } + fn dp(&self) -> Option { + PrivateKeyPartsNew::dp(self).map(to_biguint) + } + + fn dq(&self) -> Option { + PrivateKeyPartsNew::dq(self).map(to_biguint) + } + fn qinv(&self) -> Option { + PrivateKeyPartsNew::qinv(self).and_then(|v| to_biguint(v).into_bigint()) + } + + fn crt_values(&self) -> Option> { + PrivateKeyPartsNew::crt_values(self).map(|v| { + v.iter() + .map(|v| CrtValue { + exp: to_biguint(&v.exp).into_bigint().unwrap(), + coeff: to_biguint(&v.coeff).into_bigint().unwrap(), + r: to_biguint(&v.r).into_bigint().unwrap(), + }) + .collect() + }) + } +} + +/// Components of an RSA private key. +pub trait PrivateKeyPartsNew: PublicKeyPartsNew { + /// Returns the private exponent of the key. + fn d(&self) -> &BoxedUint; + + /// Returns the prime factors. + fn primes(&self) -> &[BoxedUint]; + + /// Returns the precomputed dp value, D mod (P-1) + fn dp(&self) -> Option<&BoxedUint>; + + /// Returns the precomputed dq value, D mod (Q-1) + fn dq(&self) -> Option<&BoxedUint>; + + /// Returns the precomputed qinv value, Q^-1 mod P + fn qinv(&self) -> Option<&BoxedUint>; + + /// Returns an iterator over the CRT Values + fn crt_values(&self) -> Option<&[CrtValueNew]>; +} + +/// Contains the precomputed Chinese remainder theorem values. +#[derive(Debug, Clone)] +pub struct CrtValueNew { + /// D mod (prime - 1) + pub(crate) exp: BoxedUint, + /// R·Coeff ≡ 1 mod Prime. + pub(crate) coeff: BoxedUint, + /// product of primes prior to this (inc p and q) + pub(crate) r: BoxedUint, } /// Contains the precomputed Chinese remainder theorem values. @@ -63,3 +163,17 @@ impl Drop for CrtValue { self.zeroize(); } } + +impl Zeroize for CrtValueNew { + fn zeroize(&mut self) { + self.exp.zeroize(); + self.coeff.zeroize(); + self.r.zeroize(); + } +} + +impl Drop for CrtValueNew { + fn drop(&mut self) { + self.zeroize(); + } +} From 21b7c813ca2cf6153a05ffb89a0bbbaf7d645d50 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Wed, 29 Nov 2023 16:21:29 +0100 Subject: [PATCH 03/51] store residue_params --- src/algorithms/rsa.rs | 12 ++++++++---- src/key.rs | 11 +++++++++++ src/traits/keys.rs | 4 +++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index f290402b..2c93b576 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -330,6 +330,7 @@ fn blind_new( rng: &mut R, key: &K, c: &BoxedUint, + n_params: &BoxedResidueParams, ) -> (BoxedUint, BoxedUint) { let n = NonZero::new(to_uint(key.n().clone())).unwrap(); let mut r: BoxedUint; @@ -349,10 +350,9 @@ fn blind_new( } } - let n_params = BoxedResidueParams::new(n.get()).unwrap(); let e = to_uint(key.e().clone()); let c = { - let r = reduce(&r, n_params); + let r = reduce(&r, n_params.clone()); let rpowe = r.pow(&e).retrieve(); let c = c.wrapping_mul(&rpowe); @@ -393,8 +393,13 @@ pub fn rsa_decrypt_new( let mut ir = None; + let n_params = priv_key + .residue_params() + .cloned() + .unwrap_or_else(|| BoxedResidueParams::new(n.clone().get()).unwrap()); + let c = if let Some(ref mut rng) = rng { - let (blinded, unblinder) = blind_new(rng, priv_key, &c); + let (blinded, unblinder) = blind_new(rng, priv_key, &c, &n_params); ir = Some(unblinder); blinded } else { @@ -402,7 +407,6 @@ pub fn rsa_decrypt_new( }; // TODO: fast path with precalculated values; - let n_params = BoxedResidueParams::new(n.clone().get()).unwrap(); let c = reduce(&c, n_params); let m = c.pow(&d).retrieve(); diff --git a/src/key.rs b/src/key.rs index 8abcd96d..302952f0 100644 --- a/src/key.rs +++ b/src/key.rs @@ -109,6 +109,8 @@ pub(crate) struct PrecomputedValues { /// differently in PKCS#1 and interoperability is sufficiently /// important that we mirror this. pub(crate) crt_values: Vec, + + pub(crate) residue_params: BoxedResidueParams, } impl Zeroize for PrecomputedValues { @@ -393,11 +395,16 @@ impl RsaPrivateKey { values }; + // TODO: how to handle error? + let residue_params = + BoxedResidueParams::new(self.pubkey_components.n.clone().get()).unwrap(); + self.precomputed = Some(PrecomputedValues { dp: to_uint(dp), dq: to_uint(dq), qinv, crt_values, + residue_params, }); Ok(()) @@ -523,6 +530,10 @@ impl PrivateKeyPartsNew for RsaPrivateKey { None } } + + fn residue_params(&self) -> Option<&BoxedResidueParams> { + self.precomputed.as_ref().map(|p| &p.residue_params) + } } /// Check that the public key is well formed and has an exponent within acceptable bounds. diff --git a/src/traits/keys.rs b/src/traits/keys.rs index 9d7b8d5a..f0e5fe98 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; -use crypto_bigint::{BoxedUint, NonZero}; +use crypto_bigint::{modular::BoxedResidueParams, BoxedUint, NonZero}; use num_bigint::{BigInt, BigUint, IntoBigInt}; use zeroize::Zeroize; @@ -126,6 +126,8 @@ pub trait PrivateKeyPartsNew: PublicKeyPartsNew { /// Returns an iterator over the CRT Values fn crt_values(&self) -> Option<&[CrtValueNew]>; + + fn residue_params(&self) -> Option<&BoxedResidueParams>; } /// Contains the precomputed Chinese remainder theorem values. From 98a86a238949ae5e97b3155b0418b1e84e5223fc Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Wed, 29 Nov 2023 16:36:26 +0100 Subject: [PATCH 04/51] implement blinding (tests failing currently) --- src/algorithms/rsa.rs | 19 +++++++++---------- src/key.rs | 4 ++-- src/pkcs1v15.rs | 4 +--- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 2c93b576..3d748abe 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -3,7 +3,7 @@ use alloc::borrow::Cow; use alloc::vec::Vec; use crypto_bigint::modular::BoxedResidueParams; -use crypto_bigint::{BoxedUint, NonZero, Zero}; +use crypto_bigint::{BoxedUint, NonZero}; use num_bigint::{BigInt, BigUint, IntoBigInt, IntoBigUint, ModInverse, RandBigInt, ToBigInt}; use num_integer::{sqrt, Integer}; use num_traits::{FromPrimitive, One, Pow, Signed, Zero as _}; @@ -326,22 +326,23 @@ pub(crate) fn compute_private_exponent_carmicheal( } } -fn blind_new( +fn blind_new( rng: &mut R, key: &K, c: &BoxedUint, n_params: &BoxedResidueParams, ) -> (BoxedUint, BoxedUint) { - let n = NonZero::new(to_uint(key.n().clone())).unwrap(); let mut r: BoxedUint; let mut ir: CtOption; let unblinder; loop { - r = todo!(); // BoxedUint::random_mod(&mut rng, &n); + // TODO: use constant time gen + r = to_uint(rng.gen_biguint_below(&to_biguint(&key.n()))); + // TODO: correct mapping if r.is_zero().into() { r = BoxedUint::one(); } - ir = r.inv_mod(&n); + ir = r.inv_mod(key.n()); // TODO: constant time? if let Some(ir) = ir.into() { @@ -350,13 +351,12 @@ fn blind_new( } } - let e = to_uint(key.e().clone()); let c = { let r = reduce(&r, n_params.clone()); - let rpowe = r.pow(&e).retrieve(); + let mut rpowe = r.pow(key.e()).retrieve(); let c = c.wrapping_mul(&rpowe); - let c = c.rem_vartime(&n); + let c = c.rem_vartime(key.n()); rpowe.zeroize(); @@ -367,9 +367,8 @@ fn blind_new( } fn unblind_new(key: &impl PublicKeyPartsNew, m: &BoxedUint, unblinder: &BoxedUint) -> BoxedUint { - let n = key.n(); let a = m.wrapping_mul(unblinder); - a.rem_vartime(&n) + a.rem_vartime(key.n()) } pub fn rsa_decrypt_new( diff --git a/src/key.rs b/src/key.rs index 302952f0..fb15e84d 100644 --- a/src/key.rs +++ b/src/key.rs @@ -4,7 +4,7 @@ use core::hash::{Hash, Hasher}; use crypto_bigint::modular::{BoxedResidue, BoxedResidueParams}; use crypto_bigint::{BoxedUint, Limb, NonZero}; use num_bigint::traits::ModInverse; -use num_bigint::{BigInt, BigUint}; +use num_bigint::BigUint; use num_integer::Integer; use num_traits::{FromPrimitive, One, ToPrimitive}; use rand_core::CryptoRngCore; @@ -272,7 +272,7 @@ impl RsaPrivateKey { n: BigUint, e: BigUint, d: BigUint, - mut primes: Vec, + primes: Vec, ) -> Result { let mut should_validate = false; let mut primes: Vec<_> = primes.into_iter().map(to_uint).collect(); diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index d3a47be4..7f4d2f3c 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -389,9 +389,7 @@ mod tests { assert_ne!(input, ciphertext); let blind: bool = rng.next_u32() < (1u32 << 31); - // TODO: - // let blinder = if blind { Some(&mut rng) } else { None }; - let blinder: Option<&mut ChaCha8Rng> = None; + let blinder = if blind { Some(&mut rng) } else { None }; let plaintext = decrypt_new(blinder, &priv_key, &ciphertext).unwrap(); assert_eq!(input, plaintext); } From f4131c59e4fc7b0fd699530a28f33a2ae664f6f5 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Wed, 29 Nov 2023 17:42:23 +0100 Subject: [PATCH 05/51] fix blinding and fold in new impl --- Cargo.lock | 3 +- Cargo.toml | 3 + src/algorithms/rsa.rs | 220 ++++++++++++------------------------------ src/pkcs1v15.rs | 40 +------- 4 files changed, 68 insertions(+), 198 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6a435700..61ae1cf5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,8 +125,7 @@ dependencies = [ [[package]] name = "crypto-bigint" version = "0.6.0-pre.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b60cb3dc0bfcdf8199b7eabd5df62f7b7af001c7da89b89eba17ebf3fea01638" +source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#f09c9ab948a695f2053370b4adccc3cbe65ae976" dependencies = [ "rand_core", "serdect", diff --git a/Cargo.toml b/Cargo.toml index 47d1db5b..f9612117 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,3 +65,6 @@ rustdoc-args = ["--cfg", "docsrs"] [profile.dev] opt-level = 2 + +[patch.crates-io] +crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint", branch = "master" } \ No newline at end of file diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 3d748abe..d8e871bb 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -1,10 +1,9 @@ //! Generic RSA implementation -use alloc::borrow::Cow; use alloc::vec::Vec; use crypto_bigint::modular::BoxedResidueParams; -use crypto_bigint::{BoxedUint, NonZero}; -use num_bigint::{BigInt, BigUint, IntoBigInt, IntoBigUint, ModInverse, RandBigInt, ToBigInt}; +use crypto_bigint::{BoxedUint, RandomMod}; +use num_bigint::{BigUint, IntoBigInt, IntoBigUint, ModInverse, ToBigInt}; use num_integer::{sqrt, Integer}; use num_traits::{FromPrimitive, One, Pow, Signed, Zero as _}; use rand_core::CryptoRngCore; @@ -14,7 +13,7 @@ use zeroize::{Zeroize, Zeroizing}; use crate::errors::{Error, Result}; use crate::key::{reduce, to_biguint, to_uint}; use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew}; -use crate::traits::{PrivateKeyParts, PublicKeyParts}; +use crate::traits::PublicKeyParts; /// ⚠️ Raw RSA encryption of m with the public key. No padding is performed. /// @@ -38,25 +37,35 @@ pub fn rsa_encrypt(key: &K, m: &BigUint) -> Result { #[inline] pub fn rsa_decrypt( mut rng: Option<&mut R>, - priv_key: &impl PrivateKeyParts, - c: &BigUint, + priv_key: &impl PrivateKeyPartsNew, + c_orig: &BigUint, ) -> Result { - if c >= &priv_key.n() { + // convert to crypto bigint + let c = to_uint(c_orig.clone()); + let n = priv_key.n(); + let d = priv_key.d(); + + if c >= **n { return Err(Error::Decryption); } - if priv_key.n().is_zero() { + // TODO: is this fine? + if n.is_zero().into() { return Err(Error::Decryption); } let mut ir = None; + let n_params = priv_key + .residue_params() + .cloned() + .unwrap_or_else(|| BoxedResidueParams::new(n.clone().get()).unwrap()); let c = if let Some(ref mut rng) = rng { - let (blinded, unblinder) = blind(rng, priv_key, c); + let (blinded, unblinder) = blind(rng, priv_key, &c, &n_params); ir = Some(unblinder); - Cow::Owned(blinded) + blinded } else { - Cow::Borrowed(c) + c }; let dp = priv_key.dp(); @@ -68,19 +77,21 @@ pub fn rsa_decrypt( (Some(dp), Some(dq), Some(qinv), Some(crt_values)) => { // We have the precalculated values needed for the CRT. - let p = &priv_key.primes()[0]; - let q = &priv_key.primes()[1]; + let dp = to_biguint(dp); + let dq = to_biguint(dq); + let qinv = to_biguint(qinv).to_bigint().unwrap(); + let p = to_biguint(&priv_key.primes()[0]); + let q = to_biguint(&priv_key.primes()[1]); - let mut m = c.modpow(&dp, p).into_bigint().unwrap(); - let mut m2 = c.modpow(&dq, q).into_bigint().unwrap(); + let mut m = c_orig.modpow(&dp, &p).into_bigint().unwrap(); + let mut m2 = c_orig.modpow(&dq, &q).into_bigint().unwrap(); m -= &m2; let mut primes: Vec<_> = priv_key .primes() .iter() - .map(ToBigInt::to_bigint) - .map(Option::unwrap) + .map(|p| to_biguint(p).to_bigint().unwrap()) .collect(); while m.is_negative() { @@ -91,17 +102,17 @@ pub fn rsa_decrypt( m *= &primes[1]; m += &m2; - let mut c = c.into_owned().into_bigint().unwrap(); + let mut c = c_orig.to_bigint().unwrap(); for (i, value) in crt_values.iter().enumerate() { let prime = &primes[2 + i]; - m2 = c.modpow(&value.exp, prime); + m2 = c.modpow(&to_biguint(&value.exp).to_bigint().unwrap(), prime); m2 -= &m; - m2 *= &value.coeff; + m2 *= &to_biguint(&value.coeff).to_bigint().unwrap(); m2 %= prime; while m2.is_negative() { m2 += prime; } - m2 *= &value.r; + m2 *= &to_biguint(&value.r).to_bigint().unwrap(); m += &m2; } @@ -113,17 +124,21 @@ pub fn rsa_decrypt( c.zeroize(); m2.zeroize(); - m.into_biguint().expect("failed to decrypt") + to_uint(m.into_biguint().expect("failed to decrypt")) + } + _ => { + let c = reduce(&c, n_params); + c.pow(&d).retrieve() } - _ => c.modpow(&priv_key.d(), &priv_key.n()), }; match ir { Some(ref ir) => { // unblind - Ok(unblind(priv_key, &m, ir)) + let res = to_biguint(&unblind(priv_key, &m, ir)); + Ok(res) } - None => Ok(m), + None => Ok(to_biguint(&m)), } } @@ -138,29 +153,11 @@ pub fn rsa_decrypt( /// or signature scheme. See the [module-level documentation][crate::hazmat] for more information. #[inline] pub fn rsa_decrypt_and_check( - priv_key: &impl PrivateKeyParts, - rng: Option<&mut R>, - c: &BigUint, -) -> Result { - let m = rsa_decrypt(rng, priv_key, c)?; - - // In order to defend against errors in the CRT computation, m^e is - // calculated, which should match the original ciphertext. - let check = rsa_encrypt(priv_key, &m)?; - - if c != &check { - return Err(Error::Internal); - } - - Ok(m) -} - -pub fn rsa_decrypt_and_check_new( priv_key: &impl PrivateKeyPartsNew, rng: Option<&mut R>, c: &BigUint, ) -> Result { - let m = rsa_decrypt_new(rng, priv_key, c)?; + let m = rsa_decrypt(rng, priv_key, c)?; // In order to defend against errors in the CRT computation, m^e is // calculated, which should match the original ciphertext. @@ -174,38 +171,40 @@ pub fn rsa_decrypt_and_check_new( } /// Returns the blinded c, along with the unblinding factor. -fn blind( +fn blind( rng: &mut R, key: &K, - c: &BigUint, -) -> (BigUint, BigUint) { + c: &BoxedUint, + n_params: &BoxedResidueParams, +) -> (BoxedUint, BoxedUint) { // Blinding involves multiplying c by r^e. // Then the decryption operation performs (m^e * r^e)^d mod n // which equals mr mod n. The factor of r can then be removed // by multiplying by the multiplicative inverse of r. - let mut r: BigUint; - let mut ir: Option; + let mut r: BoxedUint; + let mut ir: CtOption; let unblinder; loop { - r = rng.gen_biguint_below(&key.n()); - if r.is_zero() { - r = BigUint::one(); + // TODO: use constant time gen + r = BoxedUint::random_mod(rng, key.n()); + // TODO: correct mapping + if r.is_zero().into() { + r = BoxedUint::one(); } - ir = r.clone().mod_inverse(key.n()); - if let Some(ir) = ir { - if let Some(ub) = ir.into_biguint() { - unblinder = ub; - break; - } + ir = r.inv_mod(key.n()); + + // TODO: constant time? + if let Some(ir) = ir.into() { + unblinder = ir; + break; } } let c = { - let mut rpowe = r.modpow(&key.e(), &key.n()); // N != 0 - let mut c = c * &rpowe; - c %= key.n(); - + let r = reduce(&r, n_params.clone()); + let mut rpowe = r.pow(key.e()).retrieve(); + let c = c.mul_mod(&rpowe, key.n()); rpowe.zeroize(); c @@ -215,8 +214,8 @@ fn blind( } /// Given an m and and unblinding factor, unblind the m. -fn unblind(key: &impl PublicKeyParts, m: &BigUint, unblinder: &BigUint) -> BigUint { - (m * unblinder) % key.n() +fn unblind(key: &impl PublicKeyPartsNew, m: &BoxedUint, unblinder: &BoxedUint) -> BoxedUint { + m.mul_mod(unblinder, key.n()) } /// The following (deterministic) algorithm also recovers the prime factors `p` and `q` of a modulus `n`, given the @@ -326,99 +325,6 @@ pub(crate) fn compute_private_exponent_carmicheal( } } -fn blind_new( - rng: &mut R, - key: &K, - c: &BoxedUint, - n_params: &BoxedResidueParams, -) -> (BoxedUint, BoxedUint) { - let mut r: BoxedUint; - let mut ir: CtOption; - let unblinder; - loop { - // TODO: use constant time gen - r = to_uint(rng.gen_biguint_below(&to_biguint(&key.n()))); - // TODO: correct mapping - if r.is_zero().into() { - r = BoxedUint::one(); - } - ir = r.inv_mod(key.n()); - - // TODO: constant time? - if let Some(ir) = ir.into() { - unblinder = ir; - break; - } - } - - let c = { - let r = reduce(&r, n_params.clone()); - let mut rpowe = r.pow(key.e()).retrieve(); - - let c = c.wrapping_mul(&rpowe); - let c = c.rem_vartime(key.n()); - - rpowe.zeroize(); - - c - }; - - (c, unblinder) -} - -fn unblind_new(key: &impl PublicKeyPartsNew, m: &BoxedUint, unblinder: &BoxedUint) -> BoxedUint { - let a = m.wrapping_mul(unblinder); - a.rem_vartime(key.n()) -} - -pub fn rsa_decrypt_new( - mut rng: Option<&mut R>, - priv_key: &impl PrivateKeyPartsNew, - c: &BigUint, -) -> Result { - // convert to crypto bigint - let c = to_uint(c.clone()); - let n = priv_key.n(); - let d = priv_key.d(); - - if c >= **n { - return Err(Error::Decryption); - } - - // TODO: is this fine? - if n.is_zero().into() { - return Err(Error::Decryption); - } - - let mut ir = None; - - let n_params = priv_key - .residue_params() - .cloned() - .unwrap_or_else(|| BoxedResidueParams::new(n.clone().get()).unwrap()); - - let c = if let Some(ref mut rng) = rng { - let (blinded, unblinder) = blind_new(rng, priv_key, &c, &n_params); - ir = Some(unblinder); - blinded - } else { - c - }; - - // TODO: fast path with precalculated values; - let c = reduce(&c, n_params); - let m = c.pow(&d).retrieve(); - - match ir { - Some(ref ir) => { - // unblind - let m = unblind_new(priv_key, &m, ir); - Ok(to_biguint(&m)) - } - None => Ok(to_biguint(&m)), - } -} - #[cfg(test)] mod tests { use num_traits::FromPrimitive; diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index 7f4d2f3c..2fc3f787 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -27,7 +27,7 @@ use zeroize::Zeroizing; use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; use crate::algorithms::pkcs1v15::*; -use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_decrypt_and_check_new, rsa_encrypt}; +use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; use crate::key::{self, RsaPrivateKey, RsaPublicKey}; use crate::traits::{PaddingScheme, PublicKeyParts, SignatureScheme}; @@ -172,20 +172,6 @@ fn decrypt( pkcs1v15_encrypt_unpad(em, priv_key.size()) } -#[inline] -fn decrypt_new( - rng: Option<&mut R>, - priv_key: &RsaPrivateKey, - ciphertext: &[u8], -) -> Result> { - key::check_public(priv_key)?; - - let em = rsa_decrypt_and_check_new(priv_key, rng, &BigUint::from_bytes_be(ciphertext))?; - let em = uint_to_zeroizing_be_pad(em, priv_key.size())?; - - pkcs1v15_encrypt_unpad(em, priv_key.size()) -} - /// Calculates the signature of hashed using /// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5. Note that `hashed` must /// be the result of hashing the input message using the given hash @@ -371,30 +357,6 @@ mod tests { } } - #[test] - fn test_new_encrypt_decrypt_pkcs1v15() { - let mut rng = ChaCha8Rng::from_seed([42; 32]); - let priv_key = get_private_key(); - let k = priv_key.size(); - - for i in 1..100 { - let mut input = vec![0u8; i * 8]; - rng.fill_bytes(&mut input); - if input.len() > k - 11 { - input = input[0..k - 11].to_vec(); - } - - let pub_key: RsaPublicKey = priv_key.clone().into(); - let ciphertext = encrypt(&mut rng, &pub_key, &input).unwrap(); - assert_ne!(input, ciphertext); - - let blind: bool = rng.next_u32() < (1u32 << 31); - let blinder = if blind { Some(&mut rng) } else { None }; - let plaintext = decrypt_new(blinder, &priv_key, &ciphertext).unwrap(); - assert_eq!(input, plaintext); - } - } - #[test] fn test_decrypt_pkcs1v15_traits() { let priv_key = get_private_key(); From 2dafa35b416b156449d91bd2f808448f1f485eb2 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Wed, 29 Nov 2023 18:38:25 +0100 Subject: [PATCH 06/51] implement basic widening strategy --- src/algorithms/rsa.rs | 30 ++++++---- src/key.rs | 130 ++++++++++++++++++++++++++++++------------ 2 files changed, 112 insertions(+), 48 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index d8e871bb..d743d407 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -1,7 +1,7 @@ //! Generic RSA implementation use alloc::vec::Vec; -use crypto_bigint::modular::BoxedResidueParams; +use crypto_bigint::modular::{BoxedResidue, BoxedResidueParams}; use crypto_bigint::{BoxedUint, RandomMod}; use num_bigint::{BigUint, IntoBigInt, IntoBigUint, ModInverse, ToBigInt}; use num_integer::{sqrt, Integer}; @@ -11,7 +11,7 @@ use subtle::CtOption; use zeroize::{Zeroize, Zeroizing}; use crate::errors::{Error, Result}; -use crate::key::{reduce, to_biguint, to_uint}; +use crate::key::{reduce, to_biguint, to_uint_exact}; use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew}; use crate::traits::PublicKeyParts; @@ -40,11 +40,13 @@ pub fn rsa_decrypt( priv_key: &impl PrivateKeyPartsNew, c_orig: &BigUint, ) -> Result { - // convert to crypto bigint - let c = to_uint(c_orig.clone()); let n = priv_key.n(); + let nbits = n.bits_precision(); + let c = to_uint_exact(c_orig.clone(), nbits); let d = priv_key.d(); + std::dbg!(nbits, d.bits_precision(), c.bits_precision()); + if c >= **n { return Err(Error::Decryption); } @@ -124,10 +126,10 @@ pub fn rsa_decrypt( c.zeroize(); m2.zeroize(); - to_uint(m.into_biguint().expect("failed to decrypt")) + to_uint_exact(m.into_biguint().expect("failed to decrypt"), nbits) } _ => { - let c = reduce(&c, n_params); + let c = reduce(&c, n_params.clone()); c.pow(&d).retrieve() } }; @@ -135,7 +137,7 @@ pub fn rsa_decrypt( match ir { Some(ref ir) => { // unblind - let res = to_biguint(&unblind(priv_key, &m, ir)); + let res = to_biguint(&unblind(&m, ir, n_params)); Ok(res) } None => Ok(to_biguint(&m)), @@ -204,7 +206,7 @@ fn blind( let c = { let r = reduce(&r, n_params.clone()); let mut rpowe = r.pow(key.e()).retrieve(); - let c = c.mul_mod(&rpowe, key.n()); + let c = mul_mod_params(c, &rpowe, n_params.clone()); rpowe.zeroize(); c @@ -213,9 +215,17 @@ fn blind( (c, unblinder) } +/// Computes `lhs.mul_mod(rhs, n)` with precomputed `n_param`. +fn mul_mod_params(lhs: &BoxedUint, rhs: &BoxedUint, n_params: BoxedResidueParams) -> BoxedUint { + // TODO: nicer api in crypto-bigint? + let lhs = BoxedResidue::new(lhs, n_params.clone()); + let rhs = BoxedResidue::new(rhs, n_params); + (lhs * rhs).retrieve() +} + /// Given an m and and unblinding factor, unblind the m. -fn unblind(key: &impl PublicKeyPartsNew, m: &BoxedUint, unblinder: &BoxedUint) -> BoxedUint { - m.mul_mod(unblinder, key.n()) +fn unblind(m: &BoxedUint, unblinder: &BoxedUint, n_params: BoxedResidueParams) -> BoxedUint { + mul_mod_params(m, unblinder, n_params) } /// The following (deterministic) algorithm also recovers the prime factors `p` and `q` of a modulus `n`, given the diff --git a/src/key.rs b/src/key.rs index fb15e84d..b70d9f6f 100644 --- a/src/key.rs +++ b/src/key.rs @@ -200,11 +200,13 @@ impl RsaPublicKey { /// Create a new public key from its components. pub fn new_with_max_size(n: BigUint, e: BigUint, max_size: usize) -> Result { - let k = Self { - n: NonZero::new(to_uint(n)).unwrap(), - e: to_uint(e), - }; - check_public_with_max_size(&k, max_size)?; + check_public_with_max_size(&n, &e, max_size)?; + + let n = NonZero::new(to_uint(n)).unwrap(); + // widen to 64bit + let e = to_uint_exact(e, 64); + let k = Self { n, e }; + Ok(k) } @@ -215,10 +217,30 @@ impl RsaPublicKey { /// Most applications should use [`RsaPublicKey::new`] or /// [`RsaPublicKey::new_with_max_size`] instead. pub fn new_unchecked(n: BigUint, e: BigUint) -> Self { - Self { - n: NonZero::new(to_uint(n)).unwrap(), - e: to_uint(e), - } + // TODO: widen? + let n = NonZero::new(to_uint(n)).unwrap(); + let e = to_uint_exact(e, 64); + Self { n, e } + } +} + +fn needed_bits(n: &BigUint) -> usize { + // widen to the max size bits + let n_bits = n.bits(); + + // TODO: better algorithm/more sizes + if n_bits <= 512 { + 512 + } else if n_bits <= 1024 { + 1024 + } else if n_bits <= 2048 { + 2048 + } else if n_bits <= 4096 { + 4096 + } else if n_bits <= 8192 { + 8192 + } else { + 16384 } } @@ -274,8 +296,16 @@ impl RsaPrivateKey { d: BigUint, primes: Vec, ) -> Result { + let n_c = NonZero::new(to_uint(n.clone())).unwrap(); + let nbits = n_c.bits_precision(); + + std::dbg!(nbits); + let mut should_validate = false; - let mut primes: Vec<_> = primes.into_iter().map(to_uint).collect(); + let mut primes: Vec<_> = primes + .into_iter() + .map(|p| to_uint_exact(p, nbits)) + .collect(); if primes.len() < 2 { if !primes.is_empty() { @@ -284,17 +314,15 @@ impl RsaPrivateKey { // Recover `p` and `q` from `d`. // See method in Appendix C.2: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf let (p, q) = recover_primes(&n, &e, &d)?; - primes.push(to_uint(p)); - primes.push(to_uint(q)); + primes.push(to_uint_exact(p, nbits)); + primes.push(to_uint_exact(q, nbits)); should_validate = true; } + let e = to_uint_exact(e, 64); let mut k = RsaPrivateKey { - pubkey_components: RsaPublicKey { - n: NonZero::new(to_uint(n)).unwrap(), - e: to_uint(e), - }, - d: to_uint(d), + pubkey_components: RsaPublicKey { n: n_c, e }, + d: to_uint_exact(d, nbits), primes, precomputed: None, }; @@ -363,6 +391,10 @@ impl RsaPrivateKey { if self.precomputed.is_some() { return Ok(()); } + + // already widened to what we need + let nbits = self.pubkey_components.n.bits_precision(); + let d = to_biguint(&self.d); let dp = &d % (&to_biguint(&self.primes[0]) - BigUint::one()); let dq = &d % (&to_biguint(&self.primes[1]) - BigUint::one()); @@ -378,14 +410,15 @@ impl RsaPrivateKey { for prime in &self.primes[2..] { let prime = to_biguint(prime); let res = CrtValueNew { - exp: to_uint(&d % (&prime - BigUint::one())), - r: to_uint(r.clone()), - coeff: to_uint( + exp: to_uint_exact(&d % (&prime - BigUint::one()), nbits), + r: to_uint_exact(r.clone(), nbits), + coeff: to_uint_exact( r.clone() .mod_inverse(&prime) .ok_or(Error::InvalidCoefficient)? .to_biguint() .unwrap(), + nbits, ), }; r *= prime; @@ -400,8 +433,8 @@ impl RsaPrivateKey { BoxedResidueParams::new(self.pubkey_components.n.clone().get()).unwrap(); self.precomputed = Some(PrecomputedValues { - dp: to_uint(dp), - dq: to_uint(dq), + dp: to_uint_exact(dp, nbits), + dq: to_uint_exact(dq, nbits), qinv, crt_values, residue_params, @@ -539,34 +572,31 @@ impl PrivateKeyPartsNew for RsaPrivateKey { /// Check that the public key is well formed and has an exponent within acceptable bounds. #[inline] pub fn check_public(public_key: &impl PublicKeyParts) -> Result<()> { - check_public_with_max_size(public_key, RsaPublicKey::MAX_SIZE) + check_public_with_max_size(&public_key.n(), &public_key.e(), RsaPublicKey::MAX_SIZE) } /// Check that the public key is well formed and has an exponent within acceptable bounds. #[inline] -fn check_public_with_max_size(public_key: &impl PublicKeyParts, max_size: usize) -> Result<()> { - if public_key.n().bits() > max_size { +fn check_public_with_max_size(n: &BigUint, e: &BigUint, max_size: usize) -> Result<()> { + if n.bits() > max_size { return Err(Error::ModulusTooLarge); } - let e = public_key - .e() - .to_u64() - .ok_or(Error::PublicExponentTooLarge)?; + let eu64 = e.to_u64().ok_or(Error::PublicExponentTooLarge)?; - if public_key.e() >= public_key.n() || public_key.n().is_even() { + if e >= n || n.is_even() { return Err(Error::InvalidModulus); } - if public_key.e().is_even() { + if e.is_even() { return Err(Error::InvalidExponent); } - if e < RsaPublicKey::MIN_PUB_EXPONENT { + if eu64 < RsaPublicKey::MIN_PUB_EXPONENT { return Err(Error::PublicExponentTooSmall); } - if e > RsaPublicKey::MAX_PUB_EXPONENT { + if eu64 > RsaPublicKey::MAX_PUB_EXPONENT { return Err(Error::PublicExponentTooLarge); } @@ -577,12 +607,35 @@ pub(crate) fn to_biguint(uint: &BoxedUint) -> BigUint { BigUint::from_bytes_be(&uint.to_be_bytes()) } +pub(crate) fn to_uint_exact(big_uint: BigUint, nbits: usize) -> BoxedUint { + let bytes = big_uint.to_bytes_be(); + let pad_count = Limb::BYTES - (bytes.len() % Limb::BYTES); + let mut padded_bytes = vec![0u8; pad_count]; + padded_bytes.extend_from_slice(&bytes); + + let res = BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() * 8).unwrap(); + + match res.bits_precision().cmp(&nbits) { + Ordering::Equal => res, + Ordering::Greater => panic!("too large: {} > {}", res.bits_precision(), nbits), + Ordering::Less => res.widen(nbits), + } +} + pub(crate) fn to_uint(big_uint: BigUint) -> BoxedUint { + let nbits = needed_bits(&big_uint); + let bytes = big_uint.to_bytes_be(); let pad_count = Limb::BYTES - (bytes.len() % Limb::BYTES); let mut padded_bytes = vec![0u8; pad_count]; padded_bytes.extend_from_slice(&bytes); - BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() * 8).unwrap() + + let res = BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() * 8).unwrap(); + + if res.bits() < nbits { + return res.widen(nbits); + } + res } pub(crate) fn reduce(n: &BoxedUint, p: BoxedResidueParams) -> BoxedResidue { @@ -614,10 +667,10 @@ mod tests { fn test_from_into() { let private_key = RsaPrivateKey { pubkey_components: RsaPublicKey { - n: NonZero::new(to_uint(BigUint::from_u64(100).unwrap())).unwrap(), - e: to_uint(BigUint::from_u64(200).unwrap()), + n: NonZero::new(to_uint(BigUint::from_u64(100).unwrap()).widen(64)).unwrap(), + e: to_uint(BigUint::from_u64(200).unwrap()).widen(64), }, - d: to_uint(BigUint::from_u64(123).unwrap()), + d: to_uint(BigUint::from_u64(123).unwrap()).widen(64), primes: vec![], precomputed: None, }; @@ -654,7 +707,8 @@ mod tests { let mut rng = ChaCha8Rng::from_seed([42; 32]); let exp = BigUint::from_u64(RsaPrivateKey::EXP).expect("invalid static exponent"); - for _ in 0..10 { + for i in 0..10 { + std::dbg!(i, $size); let components = generate_multi_prime_key_with_exp(&mut rng, $multi, $size, &exp).unwrap(); let private_key = RsaPrivateKey::from_components( From cb7d48604136d02ad0b8573d5fe03189258092aa Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Wed, 29 Nov 2023 20:27:31 +0100 Subject: [PATCH 07/51] fix some widening/padding --- src/algorithms/rsa.rs | 1 + src/key.rs | 39 +++++++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index d743d407..7f3872c0 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -62,6 +62,7 @@ pub fn rsa_decrypt( .residue_params() .cloned() .unwrap_or_else(|| BoxedResidueParams::new(n.clone().get()).unwrap()); + let c = if let Some(ref mut rng) = rng { let (blinded, unblinder) = blind(rng, priv_key, &c, &n_params); ir = Some(unblinder); diff --git a/src/key.rs b/src/key.rs index b70d9f6f..4c354dda 100644 --- a/src/key.rs +++ b/src/key.rs @@ -229,7 +229,13 @@ fn needed_bits(n: &BigUint) -> usize { let n_bits = n.bits(); // TODO: better algorithm/more sizes - if n_bits <= 512 { + if n_bits <= 64 { + 64 + } else if n_bits <= 128 { + 128 + } else if n_bits <= 256 { + 256 + } else if n_bits <= 512 { 512 } else if n_bits <= 1024 { 1024 @@ -608,12 +614,7 @@ pub(crate) fn to_biguint(uint: &BoxedUint) -> BigUint { } pub(crate) fn to_uint_exact(big_uint: BigUint, nbits: usize) -> BoxedUint { - let bytes = big_uint.to_bytes_be(); - let pad_count = Limb::BYTES - (bytes.len() % Limb::BYTES); - let mut padded_bytes = vec![0u8; pad_count]; - padded_bytes.extend_from_slice(&bytes); - - let res = BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() * 8).unwrap(); + let res = inner_to_uint(big_uint); match res.bits_precision().cmp(&nbits) { Ordering::Equal => res, @@ -622,17 +623,23 @@ pub(crate) fn to_uint_exact(big_uint: BigUint, nbits: usize) -> BoxedUint { } } -pub(crate) fn to_uint(big_uint: BigUint) -> BoxedUint { - let nbits = needed_bits(&big_uint); - +fn inner_to_uint(big_uint: BigUint) -> BoxedUint { let bytes = big_uint.to_bytes_be(); - let pad_count = Limb::BYTES - (bytes.len() % Limb::BYTES); + let rem = bytes.len() % Limb::BYTES; + let pad_count = if rem == 0 { 0 } else { Limb::BYTES - rem }; + let mut padded_bytes = vec![0u8; pad_count]; padded_bytes.extend_from_slice(&bytes); - let res = BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() * 8).unwrap(); + BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() * 8).unwrap() +} + +pub(crate) fn to_uint(big_uint: BigUint) -> BoxedUint { + let nbits = needed_bits(&big_uint); - if res.bits() < nbits { + let res = inner_to_uint(big_uint); + std::dbg!(res.bits_precision(), nbits); + if res.bits_precision() < nbits { return res.widen(nbits); } res @@ -667,10 +674,10 @@ mod tests { fn test_from_into() { let private_key = RsaPrivateKey { pubkey_components: RsaPublicKey { - n: NonZero::new(to_uint(BigUint::from_u64(100).unwrap()).widen(64)).unwrap(), - e: to_uint(BigUint::from_u64(200).unwrap()).widen(64), + n: NonZero::new(to_uint_exact(BigUint::from_u64(100).unwrap(), 64)).unwrap(), + e: to_uint_exact(BigUint::from_u64(200).unwrap(), 64), }, - d: to_uint(BigUint::from_u64(123).unwrap()).widen(64), + d: to_uint_exact(BigUint::from_u64(123).unwrap(), 64), primes: vec![], precomputed: None, }; From fd19c883dc51d54d7cde5ec9c04cd65aa42391ab Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Wed, 29 Nov 2023 20:39:41 +0100 Subject: [PATCH 08/51] cleanup rsa algorithm --- src/algorithms/rsa.rs | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 7f3872c0..ca810d89 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -7,7 +7,6 @@ use num_bigint::{BigUint, IntoBigInt, IntoBigUint, ModInverse, ToBigInt}; use num_integer::{sqrt, Integer}; use num_traits::{FromPrimitive, One, Pow, Signed, Zero as _}; use rand_core::CryptoRngCore; -use subtle::CtOption; use zeroize::{Zeroize, Zeroizing}; use crate::errors::{Error, Result}; @@ -129,10 +128,7 @@ pub fn rsa_decrypt( to_uint_exact(m.into_biguint().expect("failed to decrypt"), nbits) } - _ => { - let c = reduce(&c, n_params.clone()); - c.pow(&d).retrieve() - } + _ => pow(&c, &d, &n_params), }; match ir { @@ -185,35 +181,30 @@ fn blind( // which equals mr mod n. The factor of r can then be removed // by multiplying by the multiplicative inverse of r. - let mut r: BoxedUint; - let mut ir: CtOption; - let unblinder; - loop { - // TODO: use constant time gen + let mut r: BoxedUint = BoxedUint::one(); + let mut ir: Option = None; + while ir.is_none() { r = BoxedUint::random_mod(rng, key.n()); - // TODO: correct mapping if r.is_zero().into() { r = BoxedUint::one(); } - ir = r.inv_mod(key.n()); - - // TODO: constant time? - if let Some(ir) = ir.into() { - unblinder = ir; - break; - } + ir = r.inv_mod(key.n()).into(); } let c = { - let r = reduce(&r, n_params.clone()); - let mut rpowe = r.pow(key.e()).retrieve(); + let mut rpowe = pow(&r, key.e(), n_params); let c = mul_mod_params(c, &rpowe, n_params.clone()); rpowe.zeroize(); c }; - (c, unblinder) + (c, ir.unwrap()) +} + +fn pow(base: &BoxedUint, exp: &BoxedUint, n_params: &BoxedResidueParams) -> BoxedUint { + let base = reduce(&base, n_params.clone()); + base.pow(exp).retrieve() } /// Computes `lhs.mul_mod(rhs, n)` with precomputed `n_param`. From 813fe77b6565068076cae9951fe632adbd162764 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Wed, 29 Nov 2023 20:54:35 +0100 Subject: [PATCH 09/51] docs and debugging --- src/algorithms/rsa.rs | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index ca810d89..b8a62ebd 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -125,10 +125,12 @@ pub fn rsa_decrypt( primes.clear(); c.zeroize(); m2.zeroize(); - to_uint_exact(m.into_biguint().expect("failed to decrypt"), nbits) } - _ => pow(&c, &d, &n_params), + _ => { + // c^d (mod n) + pow_mod_params(&c, &d, n_params.clone()) + } }; match ir { @@ -157,6 +159,8 @@ pub fn rsa_decrypt_and_check( c: &BigUint, ) -> Result { let m = rsa_decrypt(rng, priv_key, c)?; + let m2 = rsa_decrypt::(None, priv_key, c)?; + assert_eq!(m, m2); // In order to defend against errors in the CRT computation, m^e is // calculated, which should match the original ciphertext. @@ -180,6 +184,7 @@ fn blind( // Then the decryption operation performs (m^e * r^e)^d mod n // 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 mut r: BoxedUint = BoxedUint::one(); let mut ir: Option = None; @@ -188,26 +193,37 @@ fn blind( if r.is_zero().into() { r = BoxedUint::one(); } + + // r^-1 (mod n) ir = r.inv_mod(key.n()).into(); } - let c = { - let mut rpowe = pow(&r, key.e(), n_params); + let blinded = { + // r^e (mod n) + let mut rpowe = pow_mod_params(&r, key.e(), n_params.clone()); + // c * r^e (mod n) let c = mul_mod_params(c, &rpowe, n_params.clone()); rpowe.zeroize(); c }; - (c, ir.unwrap()) + (blinded, ir.unwrap()) } -fn pow(base: &BoxedUint, exp: &BoxedUint, n_params: &BoxedResidueParams) -> BoxedUint { - let base = reduce(&base, n_params.clone()); +/// Given an m and and unblinding factor, unblind the m. +fn unblind(m: &BoxedUint, unblinder: &BoxedUint, n_params: BoxedResidueParams) -> BoxedUint { + // m * r^-1 (mod n) + mul_mod_params(m, unblinder, n_params) +} + +/// Computes `base.pow_mod(exp, n)` with precomputed `n_params`. +fn pow_mod_params(base: &BoxedUint, exp: &BoxedUint, n_params: BoxedResidueParams) -> BoxedUint { + let base = reduce(&base, n_params); base.pow(exp).retrieve() } -/// Computes `lhs.mul_mod(rhs, n)` with precomputed `n_param`. +/// Computes `lhs.mul_mod(rhs, n)` with precomputed `n_params`. fn mul_mod_params(lhs: &BoxedUint, rhs: &BoxedUint, n_params: BoxedResidueParams) -> BoxedUint { // TODO: nicer api in crypto-bigint? let lhs = BoxedResidue::new(lhs, n_params.clone()); @@ -215,11 +231,6 @@ fn mul_mod_params(lhs: &BoxedUint, rhs: &BoxedUint, n_params: BoxedResidueParams (lhs * rhs).retrieve() } -/// Given an m and and unblinding factor, unblind the m. -fn unblind(m: &BoxedUint, unblinder: &BoxedUint, n_params: BoxedResidueParams) -> BoxedUint { - mul_mod_params(m, unblinder, n_params) -} - /// The following (deterministic) algorithm also recovers the prime factors `p` and `q` of a modulus `n`, given the /// public exponent `e` and private exponent `d` using the method described in /// [NIST 800-56B Appendix C.2](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf). From efc4460003ec771333576f154b1eee779007183b Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Thu, 30 Nov 2023 22:07:09 +0100 Subject: [PATCH 10/51] fix crt value calculation in decryption --- src/algorithms/rsa.rs | 102 ++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 64 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index b8a62ebd..4965e1be 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -1,11 +1,10 @@ //! Generic RSA implementation -use alloc::vec::Vec; use crypto_bigint::modular::{BoxedResidue, BoxedResidueParams}; use crypto_bigint::{BoxedUint, RandomMod}; -use num_bigint::{BigUint, IntoBigInt, IntoBigUint, ModInverse, ToBigInt}; +use num_bigint::{BigUint, ModInverse}; use num_integer::{sqrt, Integer}; -use num_traits::{FromPrimitive, One, Pow, Signed, Zero as _}; +use num_traits::{FromPrimitive, One, Pow, Zero as _}; use rand_core::CryptoRngCore; use zeroize::{Zeroize, Zeroizing}; @@ -70,67 +69,42 @@ pub fn rsa_decrypt( c }; - let dp = priv_key.dp(); - let dq = priv_key.dq(); - let qinv = priv_key.qinv(); - let crt_values = priv_key.crt_values(); - - let m = match (dp, dq, qinv, crt_values) { - (Some(dp), Some(dq), Some(qinv), Some(crt_values)) => { - // We have the precalculated values needed for the CRT. - - let dp = to_biguint(dp); - let dq = to_biguint(dq); - let qinv = to_biguint(qinv).to_bigint().unwrap(); - let p = to_biguint(&priv_key.primes()[0]); - let q = to_biguint(&priv_key.primes()[1]); - - let mut m = c_orig.modpow(&dp, &p).into_bigint().unwrap(); - let mut m2 = c_orig.modpow(&dq, &q).into_bigint().unwrap(); - - m -= &m2; - - let mut primes: Vec<_> = priv_key - .primes() - .iter() - .map(|p| to_biguint(p).to_bigint().unwrap()) - .collect(); - - while m.is_negative() { - m += &primes[0]; - } - m *= qinv; - m %= &primes[0]; - m *= &primes[1]; - m += &m2; - - let mut c = c_orig.to_bigint().unwrap(); - for (i, value) in crt_values.iter().enumerate() { - let prime = &primes[2 + i]; - m2 = c.modpow(&to_biguint(&value.exp).to_bigint().unwrap(), prime); - m2 -= &m; - m2 *= &to_biguint(&value.coeff).to_bigint().unwrap(); - m2 %= prime; - while m2.is_negative() { - m2 += prime; - } - m2 *= &to_biguint(&value.r).to_bigint().unwrap(); - m += &m2; - } - - // clear tmp values - for prime in primes.iter_mut() { - prime.zeroize(); - } - primes.clear(); - c.zeroize(); - m2.zeroize(); - to_uint_exact(m.into_biguint().expect("failed to decrypt"), nbits) - } - _ => { - // c^d (mod n) - pow_mod_params(&c, &d, n_params.clone()) - } + let has_precomputes = priv_key.dp().is_some(); + let is_multiprime = priv_key.primes().len() > 2; + + let m = if is_multiprime || !has_precomputes { + // c^d (mod n) + pow_mod_params(&c, &d, n_params.clone()) + } else { + // We have the precalculated values needed for the CRT. + + let dp = priv_key.dp().unwrap(); + let dq = priv_key.dq().unwrap(); + let qinv = priv_key.qinv().unwrap(); + + let p = &priv_key.primes()[0]; + let q = &priv_key.primes()[1]; + + // TODO: store + let p_params = BoxedResidueParams::new(p.clone()).unwrap(); + let q_params = BoxedResidueParams::new(q.clone()).unwrap(); + + // precomputed: dP = (1/e) mod (p-1) = d mod (p-1) + // precomputed: dQ = (1/e) mod (q-1) = d mod (q-1) + + // m1 = c^dP mod p + let m1 = pow_mod_params(&c, &dp, p_params.clone()); + // m2 = c^dQ mod q + let m2 = pow_mod_params(&c, &dq, q_params); + + // precomputed: qInv = (1/q) mod p + + // h = qInv.(m1 - m2) mod p + let x = m1.sub_mod(&m2, p); + let h = mul_mod_params(qinv, &x, p_params.clone()); + // m = m2 + h.q + let m = m2.wrapping_add(&h.wrapping_mul(q)); // TODO: verify wrapping is correct here + m }; match ir { From 9fde5fb95ca373f19bcbfa9991e7cc156cc8c3cc Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Thu, 30 Nov 2023 22:18:41 +0100 Subject: [PATCH 11/51] cleanup --- src/algorithms/rsa.rs | 4 ---- src/key.rs | 7 +------ 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 4965e1be..b52754b6 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -43,8 +43,6 @@ pub fn rsa_decrypt( let c = to_uint_exact(c_orig.clone(), nbits); let d = priv_key.d(); - std::dbg!(nbits, d.bits_precision(), c.bits_precision()); - if c >= **n { return Err(Error::Decryption); } @@ -133,8 +131,6 @@ pub fn rsa_decrypt_and_check( c: &BigUint, ) -> Result { let m = rsa_decrypt(rng, priv_key, c)?; - let m2 = rsa_decrypt::(None, priv_key, c)?; - assert_eq!(m, m2); // In order to defend against errors in the CRT computation, m^e is // calculated, which should match the original ciphertext. diff --git a/src/key.rs b/src/key.rs index 4c354dda..502fb30b 100644 --- a/src/key.rs +++ b/src/key.rs @@ -305,8 +305,6 @@ impl RsaPrivateKey { let n_c = NonZero::new(to_uint(n.clone())).unwrap(); let nbits = n_c.bits_precision(); - std::dbg!(nbits); - let mut should_validate = false; let mut primes: Vec<_> = primes .into_iter() @@ -636,9 +634,7 @@ fn inner_to_uint(big_uint: BigUint) -> BoxedUint { pub(crate) fn to_uint(big_uint: BigUint) -> BoxedUint { let nbits = needed_bits(&big_uint); - let res = inner_to_uint(big_uint); - std::dbg!(res.bits_precision(), nbits); if res.bits_precision() < nbits { return res.widen(nbits); } @@ -714,8 +710,7 @@ mod tests { let mut rng = ChaCha8Rng::from_seed([42; 32]); let exp = BigUint::from_u64(RsaPrivateKey::EXP).expect("invalid static exponent"); - for i in 0..10 { - std::dbg!(i, $size); + for _ in 0..10 { let components = generate_multi_prime_key_with_exp(&mut rng, $multi, $size, &exp).unwrap(); let private_key = RsaPrivateKey::from_components( From 3f1751eb24544f0259a988d8ab5a07ddce3ebf95 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Thu, 30 Nov 2023 22:41:31 +0100 Subject: [PATCH 12/51] convert core key algorithms --- src/key.rs | 96 +++++++++++++++------------------------------- src/traits/keys.rs | 10 +---- 2 files changed, 31 insertions(+), 75 deletions(-) diff --git a/src/key.rs b/src/key.rs index 502fb30b..a8e8bf34 100644 --- a/src/key.rs +++ b/src/key.rs @@ -3,10 +3,9 @@ use core::cmp::Ordering; use core::hash::{Hash, Hasher}; use crypto_bigint::modular::{BoxedResidue, BoxedResidueParams}; use crypto_bigint::{BoxedUint, Limb, NonZero}; -use num_bigint::traits::ModInverse; use num_bigint::BigUint; use num_integer::Integer; -use num_traits::{FromPrimitive, One, ToPrimitive}; +use num_traits::{FromPrimitive, ToPrimitive}; use rand_core::CryptoRngCore; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -21,7 +20,7 @@ use crate::algorithms::rsa::{ use crate::dummy_rng::DummyRng; use crate::errors::{Error, Result}; use crate::traits::keys::{CrtValueNew, PrivateKeyPartsNew, PublicKeyPartsNew}; -use crate::traits::{PaddingScheme, PrivateKeyParts, PublicKeyParts, SignatureScheme}; +use crate::traits::{PaddingScheme, PublicKeyParts, SignatureScheme}; /// Represents the public part of an RSA key. #[derive(Debug, Clone, PartialEq, Eq)] @@ -104,12 +103,6 @@ pub(crate) struct PrecomputedValues { /// Q^-1 mod P pub(crate) qinv: BoxedUint, - /// CRTValues is used for the 3rd and subsequent primes. Due to a - /// historical accident, the CRT for the first two primes is handled - /// differently in PKCS#1 and interoperability is sufficiently - /// important that we mirror this. - pub(crate) crt_values: Vec, - pub(crate) residue_params: BoxedResidueParams, } @@ -118,10 +111,6 @@ impl Zeroize for PrecomputedValues { self.dp.zeroize(); self.dq.zeroize(); self.qinv.zeroize(); - for val in self.crt_values.iter_mut() { - val.zeroize(); - } - self.crt_values.clear(); } } @@ -396,51 +385,29 @@ impl RsaPrivateKey { return Ok(()); } - // already widened to what we need - let nbits = self.pubkey_components.n.bits_precision(); + let d = &self.d; + let p = &self.primes[0]; + let q = &self.primes[1]; - let d = to_biguint(&self.d); - let dp = &d % (&to_biguint(&self.primes[0]) - BigUint::one()); - let dq = &d % (&to_biguint(&self.primes[1]) - BigUint::one()); - let qinv = self.primes[1].inv_mod(&self.primes[0]); + // TODO: error handling + + 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 = q.inv_mod(p); if qinv.is_none().into() { return Err(Error::InvalidPrime); } let qinv = qinv.unwrap(); - let mut r: BigUint = &to_biguint(&self.primes[0]) * &to_biguint(&self.primes[1]); - let crt_values: Vec = { - let mut values = Vec::with_capacity(self.primes.len() - 2); - for prime in &self.primes[2..] { - let prime = to_biguint(prime); - let res = CrtValueNew { - exp: to_uint_exact(&d % (&prime - BigUint::one()), nbits), - r: to_uint_exact(r.clone(), nbits), - coeff: to_uint_exact( - r.clone() - .mod_inverse(&prime) - .ok_or(Error::InvalidCoefficient)? - .to_biguint() - .unwrap(), - nbits, - ), - }; - r *= prime; - - values.push(res); - } - values - }; - - // TODO: how to handle error? let residue_params = BoxedResidueParams::new(self.pubkey_components.n.clone().get()).unwrap(); self.precomputed = Some(PrecomputedValues { - dp: to_uint_exact(dp, nbits), - dq: to_uint_exact(dq, nbits), + dp, + dq, qinv, - crt_values, residue_params, }); @@ -454,9 +421,10 @@ impl RsaPrivateKey { /// Compute CRT coefficient: `(1/q) mod p`. pub fn crt_coefficient(&self) -> Option { - (&to_biguint(&self.primes[1])) - .mod_inverse(&to_biguint(&self.primes[0]))? - .to_biguint() + let p = &self.primes[0]; + let q = &self.primes[1]; + + Option::from(q.inv_mod(p)).map(|x| to_biguint(&x)) } /// Performs basic sanity checks on the key. @@ -465,16 +433,15 @@ impl RsaPrivateKey { check_public(self)?; // Check that Πprimes == n. - let mut m = BigUint::one(); + let mut m = BoxedUint::one_with_precision(self.pubkey_components.n.bits_precision()); for prime in &self.primes { - let prime = to_biguint(&prime); // Any primes ≤ 1 will cause divide-by-zero panics later. - if prime < BigUint::one() { + if prime < &BoxedUint::one() { return Err(Error::InvalidPrime); } - m *= prime; + m = m.wrapping_mul(prime); } - if m != to_biguint(&self.pubkey_components.n) { + if m != *self.pubkey_components.n { return Err(Error::InvalidModulus); } @@ -483,13 +450,14 @@ impl RsaPrivateKey { // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) = // exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1 // mod p. Thus a^de ≡ a mod n for all a coprime to n, as required. - let mut de = PublicKeyParts::e(self); - de *= PrivateKeyParts::d(self); + let d = self.d.widen(2 * self.d.bits_precision()); + let de = d.wrapping_mul(&self.pubkey_components.e); for prime in &self.primes { - let prime = to_biguint(&prime); - let congruence: BigUint = &de % (prime - BigUint::one()); - if !congruence.is_one() { + let prime = prime.widen(d.bits_precision()); + let x = NonZero::new(prime.wrapping_sub(&BoxedUint::one())).unwrap(); + let congruence = de.rem_vartime(&x); + if !bool::from(congruence.is_one()) { return Err(Error::InvalidExponent); } } @@ -561,11 +529,7 @@ impl PrivateKeyPartsNew for RsaPrivateKey { } fn crt_values(&self) -> Option<&[CrtValueNew]> { - if let Some(p) = &self.precomputed { - Some(p.crt_values.as_slice()) - } else { - None - } + None } fn residue_params(&self) -> Option<&BoxedResidueParams> { @@ -659,7 +623,7 @@ pub(crate) fn reduce(n: &BoxedUint, p: BoxedResidueParams) -> BoxedResidue { mod tests { use super::*; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; - use crate::traits::PublicKeyParts; + use crate::traits::{PrivateKeyParts, PublicKeyParts}; use hex_literal::hex; use num_traits::{FromPrimitive, ToPrimitive}; diff --git a/src/traits/keys.rs b/src/traits/keys.rs index f0e5fe98..11985856 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -95,15 +95,7 @@ impl PrivateKeyParts for T { } fn crt_values(&self) -> Option> { - PrivateKeyPartsNew::crt_values(self).map(|v| { - v.iter() - .map(|v| CrtValue { - exp: to_biguint(&v.exp).into_bigint().unwrap(), - coeff: to_biguint(&v.coeff).into_bigint().unwrap(), - r: to_biguint(&v.r).into_bigint().unwrap(), - }) - .collect() - }) + None } } From b795c22f60a20b1ccd92e212b8697bd02289de61 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Thu, 30 Nov 2023 22:44:47 +0100 Subject: [PATCH 13/51] cache p and q params --- src/algorithms/rsa.rs | 8 +++----- src/key.rs | 16 ++++++++++++++++ src/traits/keys.rs | 4 ++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index b52754b6..b24fc042 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -79,21 +79,19 @@ pub fn rsa_decrypt( let dp = priv_key.dp().unwrap(); let dq = priv_key.dq().unwrap(); let qinv = priv_key.qinv().unwrap(); + let p_params = priv_key.p_params().unwrap(); + let q_params = priv_key.q_params().unwrap(); let p = &priv_key.primes()[0]; let q = &priv_key.primes()[1]; - // TODO: store - let p_params = BoxedResidueParams::new(p.clone()).unwrap(); - let q_params = BoxedResidueParams::new(q.clone()).unwrap(); - // precomputed: dP = (1/e) mod (p-1) = d mod (p-1) // precomputed: dQ = (1/e) mod (q-1) = d mod (q-1) // m1 = c^dP mod p let m1 = pow_mod_params(&c, &dp, p_params.clone()); // m2 = c^dQ mod q - let m2 = pow_mod_params(&c, &dq, q_params); + let m2 = pow_mod_params(&c, &dq, q_params.clone()); // precomputed: qInv = (1/q) mod p diff --git a/src/key.rs b/src/key.rs index a8e8bf34..452d6954 100644 --- a/src/key.rs +++ b/src/key.rs @@ -104,6 +104,9 @@ pub(crate) struct PrecomputedValues { pub(crate) qinv: BoxedUint, pub(crate) residue_params: BoxedResidueParams, + + pub(crate) p_params: BoxedResidueParams, + pub(crate) q_params: BoxedResidueParams, } impl Zeroize for PrecomputedValues { @@ -404,11 +407,16 @@ impl RsaPrivateKey { let residue_params = BoxedResidueParams::new(self.pubkey_components.n.clone().get()).unwrap(); + let p_params = BoxedResidueParams::new(p.clone()).unwrap(); + let q_params = BoxedResidueParams::new(q.clone()).unwrap(); + self.precomputed = Some(PrecomputedValues { dp, dq, qinv, residue_params, + p_params, + q_params, }); Ok(()) @@ -535,6 +543,14 @@ impl PrivateKeyPartsNew for RsaPrivateKey { fn residue_params(&self) -> Option<&BoxedResidueParams> { self.precomputed.as_ref().map(|p| &p.residue_params) } + + fn p_params(&self) -> Option<&BoxedResidueParams> { + self.precomputed.as_ref().map(|p| &p.p_params) + } + + fn q_params(&self) -> Option<&BoxedResidueParams> { + self.precomputed.as_ref().map(|p| &p.q_params) + } } /// Check that the public key is well formed and has an exponent within acceptable bounds. diff --git a/src/traits/keys.rs b/src/traits/keys.rs index 11985856..5912ed01 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -120,6 +120,10 @@ pub trait PrivateKeyPartsNew: PublicKeyPartsNew { fn crt_values(&self) -> Option<&[CrtValueNew]>; fn residue_params(&self) -> Option<&BoxedResidueParams>; + + fn p_params(&self) -> Option<&BoxedResidueParams>; + + fn q_params(&self) -> Option<&BoxedResidueParams>; } /// Contains the precomputed Chinese remainder theorem values. From 64815335199d6243f6b05242796bd6789d3ea2d2 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Thu, 30 Nov 2023 22:55:38 +0100 Subject: [PATCH 14/51] convert hazmt decrypt interface --- src/algorithms/rsa.rs | 17 ++++++++--------- src/key.rs | 2 ++ src/oaep.rs | 14 +++++++++++--- src/pkcs1v15.rs | 17 +++++++++++------ src/pss.rs | 13 +++++++++++-- 5 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index b24fc042..ca53b243 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -1,5 +1,6 @@ //! Generic RSA implementation +use alloc::borrow::Cow; use crypto_bigint::modular::{BoxedResidue, BoxedResidueParams}; use crypto_bigint::{BoxedUint, RandomMod}; use num_bigint::{BigUint, ModInverse}; @@ -9,7 +10,7 @@ use rand_core::CryptoRngCore; use zeroize::{Zeroize, Zeroizing}; use crate::errors::{Error, Result}; -use crate::key::{reduce, to_biguint, to_uint_exact}; +use crate::key::{reduce, to_biguint}; use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew}; use crate::traits::PublicKeyParts; @@ -36,14 +37,12 @@ pub fn rsa_encrypt(key: &K, m: &BigUint) -> Result { pub fn rsa_decrypt( mut rng: Option<&mut R>, priv_key: &impl PrivateKeyPartsNew, - c_orig: &BigUint, + c: &BoxedUint, ) -> Result { let n = priv_key.n(); - let nbits = n.bits_precision(); - let c = to_uint_exact(c_orig.clone(), nbits); let d = priv_key.d(); - if c >= **n { + if c >= n { return Err(Error::Decryption); } @@ -62,9 +61,9 @@ pub fn rsa_decrypt( let c = if let Some(ref mut rng) = rng { let (blinded, unblinder) = blind(rng, priv_key, &c, &n_params); ir = Some(unblinder); - blinded + Cow::Owned(blinded) } else { - c + Cow::Borrowed(c) }; let has_precomputes = priv_key.dp().is_some(); @@ -126,7 +125,7 @@ pub fn rsa_decrypt( pub fn rsa_decrypt_and_check( priv_key: &impl PrivateKeyPartsNew, rng: Option<&mut R>, - c: &BigUint, + c: &BoxedUint, ) -> Result { let m = rsa_decrypt(rng, priv_key, c)?; @@ -134,7 +133,7 @@ pub fn rsa_decrypt_and_check( // calculated, which should match the original ciphertext. let check = rsa_encrypt(priv_key, &m)?; - if c != &check { + if to_biguint(c) != check { return Err(Error::Internal); } diff --git a/src/key.rs b/src/key.rs index 452d6954..215bf991 100644 --- a/src/key.rs +++ b/src/key.rs @@ -674,6 +674,8 @@ mod tests { let pub_key: RsaPublicKey = private_key.clone().into(); let m = BigUint::from_u64(42).expect("invalid 42"); let c = rsa_encrypt(&pub_key, &m).expect("encryption successfull"); + let c = to_uint_exact(c, PublicKeyPartsNew::n(&pub_key).bits_precision()); + let m2 = rsa_decrypt_and_check::(private_key, None, &c) .expect("unable to decrypt without blinding"); assert_eq!(m, m2); diff --git a/src/oaep.rs b/src/oaep.rs index 0cbd1e3b..959a22df 100644 --- a/src/oaep.rs +++ b/src/oaep.rs @@ -23,7 +23,7 @@ use crate::algorithms::oaep::*; use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; -use crate::key::{self, RsaPrivateKey, RsaPublicKey}; +use crate::key::{self, to_uint_exact, RsaPrivateKey, RsaPublicKey}; use crate::traits::{PaddingScheme, PublicKeyParts}; /// Encryption and Decryption using [OAEP padding](https://datatracker.ietf.org/doc/html/rfc8017#section-7.1). @@ -246,7 +246,11 @@ fn decrypt( return Err(Error::Decryption); } - let em = rsa_decrypt_and_check(priv_key, rng, &BigUint::from_bytes_be(ciphertext))?; + let ciphertext = to_uint_exact( + BigUint::from_bytes_be(ciphertext), + crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(), + ); + let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?; let mut em = uint_to_zeroizing_be_pad(em, priv_key.size())?; oaep_decrypt(&mut em, digest, mgf_digest, label, priv_key.size()) @@ -277,7 +281,11 @@ fn decrypt_digest(&mut em, label, priv_key.size()) diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index 2fc3f787..478fa624 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -29,7 +29,7 @@ use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; use crate::algorithms::pkcs1v15::*; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; -use crate::key::{self, RsaPrivateKey, RsaPublicKey}; +use crate::key::{self, to_uint_exact, RsaPrivateKey, RsaPublicKey}; use crate::traits::{PaddingScheme, PublicKeyParts, SignatureScheme}; /// Encryption using PKCS#1 v1.5 padding. @@ -166,7 +166,11 @@ fn decrypt( ) -> Result> { key::check_public(priv_key)?; - let em = rsa_decrypt_and_check(priv_key, rng, &BigUint::from_bytes_be(ciphertext))?; + let ciphertext = to_uint_exact( + BigUint::from_bytes_be(ciphertext), + crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(), + ); + let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?; let em = uint_to_zeroizing_be_pad(em, priv_key.size())?; pkcs1v15_encrypt_unpad(em, priv_key.size()) @@ -194,10 +198,11 @@ fn sign( ) -> Result> { let em = pkcs1v15_sign_pad(prefix, hashed, priv_key.size())?; - uint_to_zeroizing_be_pad( - rsa_decrypt_and_check(priv_key, rng, &BigUint::from_bytes_be(&em))?, - priv_key.size(), - ) + let em = to_uint_exact( + BigUint::from_bytes_be(&em), + crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(), + ); + uint_to_zeroizing_be_pad(rsa_decrypt_and_check(priv_key, rng, &em)?, priv_key.size()) } /// Verifies an RSA PKCS#1 v1.5 signature. diff --git a/src/pss.rs b/src/pss.rs index c7535872..43cbc288 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -33,6 +33,7 @@ use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; use crate::algorithms::pss::*; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; +use crate::key::to_uint_exact; use crate::traits::PublicKeyParts; use crate::traits::SignatureScheme; use crate::{RsaPrivateKey, RsaPublicKey}; @@ -206,8 +207,12 @@ fn sign_pss_with_salt( let em_bits = priv_key.n().bits() - 1; let em = emsa_pss_encode(hashed, em_bits, salt, digest)?; + let em = to_uint_exact( + BigUint::from_bytes_be(&em), + crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(), + ); uint_to_zeroizing_be_pad( - rsa_decrypt_and_check(priv_key, blind_rng, &BigUint::from_bytes_be(&em))?, + rsa_decrypt_and_check(priv_key, blind_rng, &em)?, priv_key.size(), ) } @@ -221,8 +226,12 @@ fn sign_pss_with_salt_digest(hashed, em_bits, salt)?; + let em = to_uint_exact( + BigUint::from_bytes_be(&em), + crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(), + ); uint_to_zeroizing_be_pad( - rsa_decrypt_and_check(priv_key, blind_rng, &BigUint::from_bytes_be(&em))?, + rsa_decrypt_and_check(priv_key, blind_rng, &em)?, priv_key.size(), ) } From 97f8fa4b9364e9557a75fe32ba1eb629cded4be6 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 1 Dec 2023 10:33:23 +0100 Subject: [PATCH 15/51] use crypto-bigint for encryption --- src/algorithms/rsa.rs | 14 +++++------ src/key.rs | 56 +++++++++++++++++++++++++++---------------- src/traits/keys.rs | 4 ++-- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index ca53b243..e2531443 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -10,9 +10,8 @@ use rand_core::CryptoRngCore; use zeroize::{Zeroize, Zeroizing}; use crate::errors::{Error, Result}; -use crate::key::{reduce, to_biguint}; +use crate::key::{reduce, to_biguint, to_uint_exact}; use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew}; -use crate::traits::PublicKeyParts; /// ⚠️ Raw RSA encryption of m with the public key. No padding is performed. /// @@ -21,8 +20,10 @@ use crate::traits::PublicKeyParts; /// Use this function with great care! Raw RSA should never be used without an appropriate padding /// or signature scheme. See the [module-level documentation][crate::hazmat] for more information. #[inline] -pub fn rsa_encrypt(key: &K, m: &BigUint) -> Result { - Ok(m.modpow(&key.e(), &key.n())) +pub fn rsa_encrypt(key: &K, m: &BigUint) -> Result { + let m = to_uint_exact(m.clone(), key.n().bits_precision()); // TODO: change input + let res = pow_mod_params(&m, key.e(), key.n_params()); + Ok(to_biguint(&res)) } /// ⚠️ Performs raw RSA decryption with no padding or error checking. @@ -53,10 +54,7 @@ pub fn rsa_decrypt( let mut ir = None; - let n_params = priv_key - .residue_params() - .cloned() - .unwrap_or_else(|| BoxedResidueParams::new(n.clone().get()).unwrap()); + let n_params = priv_key.n_params(); let c = if let Some(ref mut rng) = rng { let (blinded, unblinder) = blind(rng, priv_key, &c, &n_params); diff --git a/src/key.rs b/src/key.rs index 215bf991..2e850edb 100644 --- a/src/key.rs +++ b/src/key.rs @@ -33,6 +33,8 @@ pub struct RsaPublicKey { /// /// Typically 0x10001 (65537) e: BoxedUint, + + n_params: BoxedResidueParams, } // TODO: derive `Hash` impl when `BoxedUint` supports it @@ -103,8 +105,6 @@ pub(crate) struct PrecomputedValues { /// Q^-1 mod P pub(crate) qinv: BoxedUint, - pub(crate) residue_params: BoxedResidueParams, - pub(crate) p_params: BoxedResidueParams, pub(crate) q_params: BoxedResidueParams, } @@ -133,9 +133,11 @@ impl From<&RsaPrivateKey> for RsaPublicKey { fn from(private_key: &RsaPrivateKey) -> Self { let n = PublicKeyPartsNew::n(private_key); let e = PublicKeyPartsNew::e(private_key); + let n_params = PublicKeyPartsNew::n_params(private_key); RsaPublicKey { n: n.clone(), e: e.clone(), + n_params, } } } @@ -148,6 +150,10 @@ impl PublicKeyPartsNew for RsaPublicKey { fn e(&self) -> &BoxedUint { &self.e } + + fn n_params(&self) -> BoxedResidueParams { + self.n_params.clone() + } } impl RsaPublicKey { @@ -194,10 +200,13 @@ impl RsaPublicKey { pub fn new_with_max_size(n: BigUint, e: BigUint, max_size: usize) -> Result { check_public_with_max_size(&n, &e, max_size)?; - let n = NonZero::new(to_uint(n)).unwrap(); + let raw_n = to_uint(n); + let n_params = BoxedResidueParams::new(raw_n.clone()).unwrap(); + let n = NonZero::new(raw_n).unwrap(); + // widen to 64bit let e = to_uint_exact(e, 64); - let k = Self { n, e }; + let k = Self { n, e, n_params }; Ok(k) } @@ -209,10 +218,11 @@ impl RsaPublicKey { /// Most applications should use [`RsaPublicKey::new`] or /// [`RsaPublicKey::new_with_max_size`] instead. pub fn new_unchecked(n: BigUint, e: BigUint) -> Self { - // TODO: widen? - let n = NonZero::new(to_uint(n)).unwrap(); + let raw_n = to_uint(n); + let n_params = BoxedResidueParams::new(raw_n.clone()).unwrap(); + let n = NonZero::new(raw_n).unwrap(); let e = to_uint_exact(e, 64); - Self { n, e } + Self { n, e, n_params } } } @@ -250,6 +260,10 @@ impl PublicKeyPartsNew for RsaPrivateKey { fn e(&self) -> &BoxedUint { &self.pubkey_components.e } + + fn n_params(&self) -> BoxedResidueParams { + self.pubkey_components.n_params.clone() + } } impl RsaPrivateKey { @@ -294,7 +308,9 @@ impl RsaPrivateKey { d: BigUint, primes: Vec, ) -> Result { - let n_c = NonZero::new(to_uint(n.clone())).unwrap(); + let raw_n = to_uint(n.clone()); + let n_params = BoxedResidueParams::new(raw_n.clone()).unwrap(); + let n_c = NonZero::new(raw_n).unwrap(); let nbits = n_c.bits_precision(); let mut should_validate = false; @@ -317,7 +333,11 @@ impl RsaPrivateKey { let e = to_uint_exact(e, 64); let mut k = RsaPrivateKey { - pubkey_components: RsaPublicKey { n: n_c, e }, + pubkey_components: RsaPublicKey { + n: n_c, + e, + n_params, + }, d: to_uint_exact(d, nbits), primes, precomputed: None, @@ -404,9 +424,6 @@ impl RsaPrivateKey { } let qinv = qinv.unwrap(); - let residue_params = - BoxedResidueParams::new(self.pubkey_components.n.clone().get()).unwrap(); - let p_params = BoxedResidueParams::new(p.clone()).unwrap(); let q_params = BoxedResidueParams::new(q.clone()).unwrap(); @@ -414,7 +431,6 @@ impl RsaPrivateKey { dp, dq, qinv, - residue_params, p_params, q_params, }); @@ -540,10 +556,6 @@ impl PrivateKeyPartsNew for RsaPrivateKey { None } - fn residue_params(&self) -> Option<&BoxedResidueParams> { - self.precomputed.as_ref().map(|p| &p.residue_params) - } - fn p_params(&self) -> Option<&BoxedResidueParams> { self.precomputed.as_ref().map(|p| &p.p_params) } @@ -648,18 +660,20 @@ mod tests { #[test] fn test_from_into() { + let raw_n = BoxedUint::from(101u64); let private_key = RsaPrivateKey { pubkey_components: RsaPublicKey { - n: NonZero::new(to_uint_exact(BigUint::from_u64(100).unwrap(), 64)).unwrap(), - e: to_uint_exact(BigUint::from_u64(200).unwrap(), 64), + n: NonZero::new(raw_n.clone()).unwrap(), + e: BoxedUint::from(200u64), + n_params: BoxedResidueParams::new(raw_n).unwrap(), }, - d: to_uint_exact(BigUint::from_u64(123).unwrap(), 64), + d: BoxedUint::from(123u64), primes: vec![], precomputed: None, }; let public_key: RsaPublicKey = private_key.into(); - assert_eq!(PublicKeyParts::n(&public_key).to_u64(), Some(100)); + assert_eq!(PublicKeyParts::n(&public_key).to_u64(), Some(101)); assert_eq!(PublicKeyParts::e(&public_key).to_u64(), Some(200)); } diff --git a/src/traits/keys.rs b/src/traits/keys.rs index 5912ed01..433e668e 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -30,6 +30,8 @@ pub trait PublicKeyPartsNew { /// Returns the public exponent of the key. fn e(&self) -> &BoxedUint; + fn n_params(&self) -> BoxedResidueParams; + /// Returns the modulus size in bytes. Raw signatures and ciphertexts for /// or by this public key will have the same size. fn size(&self) -> usize { @@ -119,8 +121,6 @@ pub trait PrivateKeyPartsNew: PublicKeyPartsNew { /// Returns an iterator over the CRT Values fn crt_values(&self) -> Option<&[CrtValueNew]>; - fn residue_params(&self) -> Option<&BoxedResidueParams>; - fn p_params(&self) -> Option<&BoxedResidueParams>; fn q_params(&self) -> Option<&BoxedResidueParams>; From cc3f03ba63fa3660e81685551c55be004c9de002 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 1 Dec 2023 10:52:00 +0100 Subject: [PATCH 16/51] convert more internal use to crypto-bigint --- src/algorithms/pad.rs | 11 +++++++++-- src/algorithms/rsa.rs | 19 +++++++++---------- src/errors.rs | 9 +++++++++ src/key.rs | 3 +-- src/oaep.rs | 42 ++++++++++++++++++++++++------------------ src/pkcs1v15.rs | 37 ++++++++++++++++++++++--------------- src/pss.rs | 35 ++++++++++++++++++++++------------- src/traits/keys.rs | 4 ++++ 8 files changed, 100 insertions(+), 60 deletions(-) diff --git a/src/algorithms/pad.rs b/src/algorithms/pad.rs index b89c8c2e..e739ff63 100644 --- a/src/algorithms/pad.rs +++ b/src/algorithms/pad.rs @@ -1,6 +1,7 @@ //! Special handling for converting the BigUint to u8 vectors use alloc::vec::Vec; +use crypto_bigint::BoxedUint; use num_bigint::BigUint; use zeroize::Zeroizing; @@ -26,9 +27,15 @@ pub(crate) fn uint_to_be_pad(input: BigUint, padded_len: usize) -> Result Result> { +pub(crate) fn uint_to_be_pad_new(input: BoxedUint, padded_len: usize) -> Result> { + left_pad(&input.to_be_bytes(), padded_len) +} + +/// Converts input to the new vector of the given length, using BE and with 0s left padded. +#[inline] +pub(crate) fn uint_to_zeroizing_be_pad_new(input: BoxedUint, padded_len: usize) -> Result> { let m = Zeroizing::new(input); - let m = Zeroizing::new(m.to_bytes_be()); + let m = Zeroizing::new(m.to_be_bytes()); left_pad(&m, padded_len) } diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index e2531443..8d1a26a4 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -10,7 +10,7 @@ use rand_core::CryptoRngCore; use zeroize::{Zeroize, Zeroizing}; use crate::errors::{Error, Result}; -use crate::key::{reduce, to_biguint, to_uint_exact}; +use crate::key::reduce; use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew}; /// ⚠️ Raw RSA encryption of m with the public key. No padding is performed. @@ -20,10 +20,9 @@ use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew}; /// Use this function with great care! Raw RSA should never be used without an appropriate padding /// or signature scheme. See the [module-level documentation][crate::hazmat] for more information. #[inline] -pub fn rsa_encrypt(key: &K, m: &BigUint) -> Result { - let m = to_uint_exact(m.clone(), key.n().bits_precision()); // TODO: change input - let res = pow_mod_params(&m, key.e(), key.n_params()); - Ok(to_biguint(&res)) +pub fn rsa_encrypt(key: &K, m: &BoxedUint) -> Result { + let res = pow_mod_params(m, key.e(), key.n_params()); + Ok(res) } /// ⚠️ Performs raw RSA decryption with no padding or error checking. @@ -39,7 +38,7 @@ pub fn rsa_decrypt( mut rng: Option<&mut R>, priv_key: &impl PrivateKeyPartsNew, c: &BoxedUint, -) -> Result { +) -> Result { let n = priv_key.n(); let d = priv_key.d(); @@ -103,10 +102,10 @@ pub fn rsa_decrypt( match ir { Some(ref ir) => { // unblind - let res = to_biguint(&unblind(&m, ir, n_params)); + let res = unblind(&m, ir, n_params); Ok(res) } - None => Ok(to_biguint(&m)), + None => Ok(m), } } @@ -124,14 +123,14 @@ pub fn rsa_decrypt_and_check( priv_key: &impl PrivateKeyPartsNew, rng: Option<&mut R>, c: &BoxedUint, -) -> Result { +) -> Result { let m = rsa_decrypt(rng, priv_key, c)?; // In order to defend against errors in the CRT computation, m^e is // calculated, which should match the original ciphertext. let check = rsa_encrypt(priv_key, &m)?; - if to_biguint(c) != check { + if c != &check { return Err(Error::Internal); } diff --git a/src/errors.rs b/src/errors.rs index 7a0116bd..50ea15ed 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -66,6 +66,9 @@ pub enum Error { /// Invalid arguments. InvalidArguments, + + /// Decoding error. + Decode(crypto_bigint::DecodeError), } #[cfg(feature = "std")] @@ -95,6 +98,7 @@ impl core::fmt::Display for Error { Error::LabelTooLong => write!(f, "label too long"), Error::InvalidPadLen => write!(f, "invalid padding length"), Error::InvalidArguments => write!(f, "invalid arguments"), + Error::Decode(err) => write!(f, "{:?}", err), } } } @@ -110,6 +114,11 @@ impl From for Error { Error::Pkcs8(err) } } +impl From for Error { + fn from(err: crypto_bigint::DecodeError) -> Error { + Error::Decode(err) + } +} #[cfg(feature = "std")] impl From for signature::Error { diff --git a/src/key.rs b/src/key.rs index 2e850edb..f9889ef9 100644 --- a/src/key.rs +++ b/src/key.rs @@ -686,9 +686,8 @@ mod tests { ); let pub_key: RsaPublicKey = private_key.clone().into(); - let m = BigUint::from_u64(42).expect("invalid 42"); + let m = BoxedUint::from(42u64); let c = rsa_encrypt(&pub_key, &m).expect("encryption successfull"); - let c = to_uint_exact(c, PublicKeyPartsNew::n(&pub_key).bits_precision()); let m2 = rsa_decrypt_and_check::(private_key, None, &c) .expect("unable to decrypt without blinding"); diff --git a/src/oaep.rs b/src/oaep.rs index 959a22df..8739eabf 100644 --- a/src/oaep.rs +++ b/src/oaep.rs @@ -13,17 +13,16 @@ use alloc::boxed::Box; use alloc::string::{String, ToString}; use alloc::vec::Vec; use core::fmt; +use crypto_bigint::BoxedUint; use digest::{Digest, DynDigest, FixedOutputReset}; -use num_bigint::BigUint; use rand_core::CryptoRngCore; -use zeroize::Zeroizing; use crate::algorithms::oaep::*; -use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; +use crate::algorithms::pad::{uint_to_be_pad_new, uint_to_zeroizing_be_pad_new}; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; -use crate::key::{self, to_uint_exact, RsaPrivateKey, RsaPublicKey}; +use crate::key::{self, RsaPrivateKey, RsaPublicKey}; use crate::traits::{PaddingScheme, PublicKeyParts}; /// Encryption and Decryption using [OAEP padding](https://datatracker.ietf.org/doc/html/rfc8017#section-7.1). @@ -194,8 +193,11 @@ fn encrypt( let em = oaep_encrypt(rng, msg, digest, mgf_digest, label, pub_key.size())?; - let int = Zeroizing::new(BigUint::from_bytes_be(&em)); - uint_to_be_pad(rsa_encrypt(pub_key, &int)?, pub_key.size()) + let int = BoxedUint::from_be_slice( + &em, + crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), + )?; + uint_to_be_pad_new(rsa_encrypt(pub_key, &int)?, pub_key.size()) } /// Encrypts the given message with RSA and the padding scheme from @@ -215,8 +217,11 @@ fn encrypt_digest(rng, msg, label, pub_key.size())?; - let int = Zeroizing::new(BigUint::from_bytes_be(&em)); - uint_to_be_pad(rsa_encrypt(pub_key, &int)?, pub_key.size()) + let int = BoxedUint::from_be_slice( + &em, + crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), + )?; + uint_to_be_pad_new(rsa_encrypt(pub_key, &int)?, pub_key.size()) } /// Decrypts a plaintext using RSA and the padding scheme from [PKCS#1 OAEP]. @@ -246,12 +251,13 @@ fn decrypt( return Err(Error::Decryption); } - let ciphertext = to_uint_exact( - BigUint::from_bytes_be(ciphertext), - crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(), - ); + let ciphertext = BoxedUint::from_be_slice( + ciphertext, + crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), + )?; + let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?; - let mut em = uint_to_zeroizing_be_pad(em, priv_key.size())?; + let mut em = uint_to_zeroizing_be_pad_new(em, priv_key.size())?; oaep_decrypt(&mut em, digest, mgf_digest, label, priv_key.size()) } @@ -281,12 +287,12 @@ fn decrypt_digest(&mut em, label, priv_key.size()) } diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index 478fa624..3cda1d38 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -19,13 +19,13 @@ pub use self::{ use alloc::{boxed::Box, vec::Vec}; use core::fmt::Debug; +use crypto_bigint::BoxedUint; use digest::Digest; use num_bigint::BigUint; use pkcs8::AssociatedOid; use rand_core::CryptoRngCore; -use zeroize::Zeroizing; -use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; +use crate::algorithms::pad::{uint_to_be_pad_new, uint_to_zeroizing_be_pad_new}; use crate::algorithms::pkcs1v15::*; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; @@ -145,8 +145,11 @@ fn encrypt( key::check_public(pub_key)?; let em = pkcs1v15_encrypt_pad(rng, msg, pub_key.size())?; - let int = Zeroizing::new(BigUint::from_bytes_be(&em)); - uint_to_be_pad(rsa_encrypt(pub_key, &int)?, pub_key.size()) + let int = BoxedUint::from_be_slice( + &em, + crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), + )?; + uint_to_be_pad_new(rsa_encrypt(pub_key, &int)?, pub_key.size()) } /// Decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5. @@ -166,12 +169,12 @@ fn decrypt( ) -> Result> { key::check_public(priv_key)?; - let ciphertext = to_uint_exact( - BigUint::from_bytes_be(ciphertext), - crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(), - ); + let ciphertext = BoxedUint::from_be_slice( + ciphertext, + crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), + )?; let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?; - let em = uint_to_zeroizing_be_pad(em, priv_key.size())?; + let em = uint_to_zeroizing_be_pad_new(em, priv_key.size())?; pkcs1v15_encrypt_unpad(em, priv_key.size()) } @@ -198,11 +201,11 @@ fn sign( ) -> Result> { let em = pkcs1v15_sign_pad(prefix, hashed, priv_key.size())?; - let em = to_uint_exact( - BigUint::from_bytes_be(&em), - crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(), - ); - uint_to_zeroizing_be_pad(rsa_decrypt_and_check(priv_key, rng, &em)?, priv_key.size()) + let em = BoxedUint::from_be_slice( + &em, + crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), + )?; + uint_to_zeroizing_be_pad_new(rsa_decrypt_and_check(priv_key, rng, &em)?, priv_key.size()) } /// Verifies an RSA PKCS#1 v1.5 signature. @@ -218,7 +221,11 @@ fn verify( return Err(Error::Verification); } - let em = uint_to_be_pad(rsa_encrypt(pub_key, sig)?, pub_key.size())?; + let sig = to_uint_exact( + sig.clone(), + crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), + ); + let em = uint_to_be_pad_new(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; pkcs1v15_sign_unpad(prefix, hashed, &em, pub_key.size()) } diff --git a/src/pss.rs b/src/pss.rs index 43cbc288..eee4f5d8 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -21,6 +21,7 @@ pub use self::{ use alloc::{boxed::Box, vec::Vec}; use core::fmt::{self, Debug}; +use crypto_bigint::BoxedUint; use const_oid::{AssociatedOid, ObjectIdentifier}; use digest::{Digest, DynDigest, FixedOutputReset}; @@ -29,7 +30,7 @@ use pkcs1::RsaPssParams; use pkcs8::spki::{der::Any, AlgorithmIdentifierOwned}; use rand_core::CryptoRngCore; -use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; +use crate::algorithms::pad::{uint_to_be_pad_new, uint_to_zeroizing_be_pad_new}; use crate::algorithms::pss::*; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; @@ -136,7 +137,11 @@ pub(crate) fn verify( return Err(Error::Verification); } - let mut em = uint_to_be_pad(rsa_encrypt(pub_key, sig)?, pub_key.size())?; + let sig = to_uint_exact( + sig.clone(), + crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), + ); + let mut em = uint_to_be_pad_new(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; emsa_pss_verify(hashed, &mut em, salt_len, digest, pub_key.n().bits()) } @@ -155,7 +160,11 @@ where return Err(Error::Verification); } - let mut em = uint_to_be_pad(rsa_encrypt(pub_key, sig)?, pub_key.size())?; + let sig = to_uint_exact( + sig.clone(), + crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), + ); + let mut em = uint_to_be_pad_new(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; emsa_pss_verify_digest::(hashed, &mut em, salt_len, pub_key.n().bits()) } @@ -207,11 +216,11 @@ fn sign_pss_with_salt( let em_bits = priv_key.n().bits() - 1; let em = emsa_pss_encode(hashed, em_bits, salt, digest)?; - let em = to_uint_exact( - BigUint::from_bytes_be(&em), - crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(), - ); - uint_to_zeroizing_be_pad( + let em = BoxedUint::from_be_slice( + &em, + crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), + )?; + uint_to_zeroizing_be_pad_new( rsa_decrypt_and_check(priv_key, blind_rng, &em)?, priv_key.size(), ) @@ -226,11 +235,11 @@ fn sign_pss_with_salt_digest(hashed, em_bits, salt)?; - let em = to_uint_exact( - BigUint::from_bytes_be(&em), - crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(), - ); - uint_to_zeroizing_be_pad( + let em = BoxedUint::from_be_slice( + &em, + crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), + )?; + uint_to_zeroizing_be_pad_new( rsa_decrypt_and_check(priv_key, blind_rng, &em)?, priv_key.size(), ) diff --git a/src/traits/keys.rs b/src/traits/keys.rs index 433e668e..a6b26630 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -32,6 +32,10 @@ pub trait PublicKeyPartsNew { fn n_params(&self) -> BoxedResidueParams; + fn n_bits_precision(&self) -> usize { + self.n().bits_precision() + } + /// Returns the modulus size in bytes. Raw signatures and ciphertexts for /// or by this public key will have the same size. fn size(&self) -> usize { From d02fbe7fc8a37dfffab01882669e1f037c3ceaf0 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 1 Dec 2023 10:59:03 +0100 Subject: [PATCH 17/51] use crypto-bigint in signatuers --- src/algorithms/pad.rs | 11 ++--------- src/oaep.rs | 10 +++++----- src/pkcs1v15.rs | 23 +++++++++-------------- src/pkcs1v15/signature.rs | 10 ++++++---- src/pss.rs | 18 +++++++----------- src/pss/signature.rs | 10 ++++++---- 6 files changed, 35 insertions(+), 47 deletions(-) diff --git a/src/algorithms/pad.rs b/src/algorithms/pad.rs index e739ff63..9191e4a8 100644 --- a/src/algorithms/pad.rs +++ b/src/algorithms/pad.rs @@ -2,7 +2,6 @@ use alloc::vec::Vec; use crypto_bigint::BoxedUint; -use num_bigint::BigUint; use zeroize::Zeroizing; use crate::errors::{Error, Result}; @@ -21,19 +20,13 @@ fn left_pad(input: &[u8], padded_len: usize) -> Result> { /// Converts input to the new vector of the given length, using BE and with 0s left padded. #[inline] -pub(crate) fn uint_to_be_pad(input: BigUint, padded_len: usize) -> Result> { - left_pad(&input.to_bytes_be(), padded_len) -} - -/// Converts input to the new vector of the given length, using BE and with 0s left padded. -#[inline] -pub(crate) fn uint_to_be_pad_new(input: BoxedUint, padded_len: usize) -> Result> { +pub(crate) fn uint_to_be_pad(input: BoxedUint, padded_len: usize) -> Result> { left_pad(&input.to_be_bytes(), padded_len) } /// Converts input to the new vector of the given length, using BE and with 0s left padded. #[inline] -pub(crate) fn uint_to_zeroizing_be_pad_new(input: BoxedUint, padded_len: usize) -> Result> { +pub(crate) fn uint_to_zeroizing_be_pad(input: BoxedUint, padded_len: usize) -> Result> { let m = Zeroizing::new(input); let m = Zeroizing::new(m.to_be_bytes()); left_pad(&m, padded_len) diff --git a/src/oaep.rs b/src/oaep.rs index 8739eabf..20749a95 100644 --- a/src/oaep.rs +++ b/src/oaep.rs @@ -19,7 +19,7 @@ use digest::{Digest, DynDigest, FixedOutputReset}; use rand_core::CryptoRngCore; use crate::algorithms::oaep::*; -use crate::algorithms::pad::{uint_to_be_pad_new, uint_to_zeroizing_be_pad_new}; +use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; use crate::key::{self, RsaPrivateKey, RsaPublicKey}; @@ -197,7 +197,7 @@ fn encrypt( &em, crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), )?; - uint_to_be_pad_new(rsa_encrypt(pub_key, &int)?, pub_key.size()) + uint_to_be_pad(rsa_encrypt(pub_key, &int)?, pub_key.size()) } /// Encrypts the given message with RSA and the padding scheme from @@ -221,7 +221,7 @@ fn encrypt_digest( )?; let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?; - let mut em = uint_to_zeroizing_be_pad_new(em, priv_key.size())?; + let mut em = uint_to_zeroizing_be_pad(em, priv_key.size())?; oaep_decrypt(&mut em, digest, mgf_digest, label, priv_key.size()) } @@ -292,7 +292,7 @@ fn decrypt_digest(&mut em, label, priv_key.size()) } diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index 3cda1d38..7488dab7 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -21,15 +21,14 @@ use alloc::{boxed::Box, vec::Vec}; use core::fmt::Debug; use crypto_bigint::BoxedUint; use digest::Digest; -use num_bigint::BigUint; use pkcs8::AssociatedOid; use rand_core::CryptoRngCore; -use crate::algorithms::pad::{uint_to_be_pad_new, uint_to_zeroizing_be_pad_new}; +use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; use crate::algorithms::pkcs1v15::*; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; -use crate::key::{self, to_uint_exact, RsaPrivateKey, RsaPublicKey}; +use crate::key::{self, RsaPrivateKey, RsaPublicKey}; use crate::traits::{PaddingScheme, PublicKeyParts, SignatureScheme}; /// Encryption using PKCS#1 v1.5 padding. @@ -127,7 +126,7 @@ impl SignatureScheme for Pkcs1v15Sign { pub_key, self.prefix.as_ref(), hashed, - &BigUint::from_bytes_be(sig), + &BoxedUint::from_be_slice(sig, sig.len() * 8)?, sig.len(), ) } @@ -149,7 +148,7 @@ fn encrypt( &em, crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), )?; - uint_to_be_pad_new(rsa_encrypt(pub_key, &int)?, pub_key.size()) + uint_to_be_pad(rsa_encrypt(pub_key, &int)?, pub_key.size()) } /// Decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5. @@ -174,7 +173,7 @@ fn decrypt( crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), )?; let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?; - let em = uint_to_zeroizing_be_pad_new(em, priv_key.size())?; + let em = uint_to_zeroizing_be_pad(em, priv_key.size())?; pkcs1v15_encrypt_unpad(em, priv_key.size()) } @@ -205,7 +204,7 @@ fn sign( &em, crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), )?; - uint_to_zeroizing_be_pad_new(rsa_decrypt_and_check(priv_key, rng, &em)?, priv_key.size()) + uint_to_zeroizing_be_pad(rsa_decrypt_and_check(priv_key, rng, &em)?, priv_key.size()) } /// Verifies an RSA PKCS#1 v1.5 signature. @@ -214,18 +213,14 @@ fn verify( pub_key: &RsaPublicKey, prefix: &[u8], hashed: &[u8], - sig: &BigUint, + sig: &BoxedUint, sig_len: usize, ) -> Result<()> { - if sig >= &pub_key.n() || sig_len != pub_key.size() { + if sig >= crate::traits::keys::PublicKeyPartsNew::n(pub_key) || sig_len != pub_key.size() { return Err(Error::Verification); } - let sig = to_uint_exact( - sig.clone(), - crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), - ); - let em = uint_to_be_pad_new(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; + let em = uint_to_be_pad(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; pkcs1v15_sign_unpad(prefix, hashed, &em, pub_key.size()) } diff --git a/src/pkcs1v15/signature.rs b/src/pkcs1v15/signature.rs index a640da32..89017ff1 100644 --- a/src/pkcs1v15/signature.rs +++ b/src/pkcs1v15/signature.rs @@ -3,6 +3,7 @@ pub use ::signature::{ DigestSigner, DigestVerifier, Error, Keypair, RandomizedDigestSigner, RandomizedSigner, Result, SignatureEncoding, Signer, Verifier, }; +use crypto_bigint::BoxedUint; use spki::{ der::{asn1::BitString, Result as DerResult}, SignatureBitStringEncoding, @@ -11,14 +12,13 @@ use spki::{ use crate::algorithms::pad::uint_to_be_pad; use alloc::{boxed::Box, string::ToString}; use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex}; -use num_bigint::BigUint; /// `RSASSA-PKCS1-v1_5` signatures as described in [RFC8017 § 8.2]. /// /// [RFC8017 § 8.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2 #[derive(Clone, PartialEq, Eq)] pub struct Signature { - pub(super) inner: BigUint, + pub(super) inner: BoxedUint, pub(super) len: usize, } @@ -36,9 +36,11 @@ impl TryFrom<&[u8]> for Signature { type Error = signature::Error; fn try_from(bytes: &[u8]) -> signature::Result { + let len = bytes.len(); Ok(Self { - inner: BigUint::from_bytes_be(bytes), - len: bytes.len(), + // TODO: how to convert error? + inner: BoxedUint::from_be_slice(bytes, len * 8).unwrap(), + len, }) } } diff --git a/src/pss.rs b/src/pss.rs index eee4f5d8..67c2141b 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -30,7 +30,7 @@ use pkcs1::RsaPssParams; use pkcs8::spki::{der::Any, AlgorithmIdentifierOwned}; use rand_core::CryptoRngCore; -use crate::algorithms::pad::{uint_to_be_pad_new, uint_to_zeroizing_be_pad_new}; +use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; use crate::algorithms::pss::*; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; @@ -141,7 +141,7 @@ pub(crate) fn verify( sig.clone(), crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), ); - let mut em = uint_to_be_pad_new(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; + let mut em = uint_to_be_pad(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; emsa_pss_verify(hashed, &mut em, salt_len, digest, pub_key.n().bits()) } @@ -149,22 +149,18 @@ pub(crate) fn verify( pub(crate) fn verify_digest( pub_key: &RsaPublicKey, hashed: &[u8], - sig: &BigUint, + sig: &BoxedUint, sig_len: usize, salt_len: usize, ) -> Result<()> where D: Digest + FixedOutputReset, { - if sig >= &pub_key.n() || sig_len != pub_key.size() { + if sig >= crate::traits::keys::PublicKeyPartsNew::n(pub_key) || sig_len != pub_key.size() { return Err(Error::Verification); } - let sig = to_uint_exact( - sig.clone(), - crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), - ); - let mut em = uint_to_be_pad_new(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; + let mut em = uint_to_be_pad(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; emsa_pss_verify_digest::(hashed, &mut em, salt_len, pub_key.n().bits()) } @@ -220,7 +216,7 @@ fn sign_pss_with_salt( &em, crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), )?; - uint_to_zeroizing_be_pad_new( + uint_to_zeroizing_be_pad( rsa_decrypt_and_check(priv_key, blind_rng, &em)?, priv_key.size(), ) @@ -239,7 +235,7 @@ fn sign_pss_with_salt_digest for Signature { type Error = signature::Error; fn try_from(bytes: &[u8]) -> signature::Result { + let len = bytes.len(); Ok(Self { - len: bytes.len(), - inner: BigUint::from_bytes_be(bytes), + len, + // TODO: how to convert the error? + inner: BoxedUint::from_be_slice(bytes, len * 8).unwrap(), }) } } From a5fc6164e568ca74e95200755bbca1f8ba48a012 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 1 Dec 2023 11:25:14 +0100 Subject: [PATCH 18/51] convert from_components internally and pss signature --- Cargo.lock | 118 ++++++++++++++++++++++++++++++++---------- src/algorithms/rsa.rs | 4 +- src/key.rs | 31 +++++++---- src/pss.rs | 10 +--- 4 files changed, 117 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61ae1cf5..a053c0da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,7 +125,7 @@ dependencies = [ [[package]] name = "crypto-bigint" version = "0.6.0-pre.0" -source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#f09c9ab948a695f2053370b4adccc3cbe65ae976" +source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#31d9373e632da6dc3dcf4e61e83a8931839ba721" dependencies = [ "rand_core", "serdect", @@ -168,12 +168,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -266,9 +266,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "num-bigint-dig" @@ -384,9 +384,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -512,15 +512,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.25" +version = "0.38.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" dependencies = [ "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -557,18 +557,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", @@ -650,9 +650,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", @@ -685,7 +685,7 @@ dependencies = [ "fastrand", "redox_syscall", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -733,7 +733,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -742,13 +751,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -757,42 +781,84 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "zeroize" version = "1.7.0" diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 8d1a26a4..160f93ca 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -27,7 +27,7 @@ pub fn rsa_encrypt(key: &K, m: &BoxedUint) -> Result( /// ⚠️ Performs raw RSA decryption with no padding. /// -/// Returns a plaintext `BigUint`. Performs RSA blinding if an `Rng` is passed. This will also +/// Returns a plaintext `BoxedUint`. Performs RSA blinding if an `Rng` is passed. This will also /// check for errors in the CRT computation. /// /// # ☢️️ WARNING: HAZARDOUS API ☢️ diff --git a/src/key.rs b/src/key.rs index f9889ef9..6d4fd316 100644 --- a/src/key.rs +++ b/src/key.rs @@ -308,16 +308,28 @@ impl RsaPrivateKey { d: BigUint, primes: Vec, ) -> Result { - let raw_n = to_uint(n.clone()); - let n_params = BoxedResidueParams::new(raw_n.clone()).unwrap(); - let n_c = NonZero::new(raw_n).unwrap(); - let nbits = n_c.bits_precision(); - - let mut should_validate = false; - let mut primes: Vec<_> = primes + let n = to_uint(n.clone()); + let nbits = n.bits_precision(); + let e = to_uint_exact(e, 64); + let d = to_uint_exact(d, nbits); + let primes = primes .into_iter() .map(|p| to_uint_exact(p, nbits)) .collect(); + Self::from_components_new(n, e, d, primes) + } + + pub(crate) fn from_components_new( + n: BoxedUint, + e: BoxedUint, + d: BoxedUint, + mut primes: Vec, + ) -> Result { + let n_params = BoxedResidueParams::new(n.clone()).unwrap(); + let n_c = NonZero::new(n.clone()).unwrap(); + let nbits = n_c.bits_precision(); + + let mut should_validate = false; if primes.len() < 2 { if !primes.is_empty() { @@ -325,20 +337,19 @@ impl RsaPrivateKey { } // Recover `p` and `q` from `d`. // See method in Appendix C.2: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf - let (p, q) = recover_primes(&n, &e, &d)?; + let (p, q) = recover_primes(&to_biguint(&n), &to_biguint(&e), &to_biguint(&d))?; primes.push(to_uint_exact(p, nbits)); primes.push(to_uint_exact(q, nbits)); should_validate = true; } - let e = to_uint_exact(e, 64); let mut k = RsaPrivateKey { pubkey_components: RsaPublicKey { n: n_c, e, n_params, }, - d: to_uint_exact(d, nbits), + d, primes, precomputed: None, }; diff --git a/src/pss.rs b/src/pss.rs index 67c2141b..454c6426 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -25,7 +25,6 @@ use crypto_bigint::BoxedUint; use const_oid::{AssociatedOid, ObjectIdentifier}; use digest::{Digest, DynDigest, FixedOutputReset}; -use num_bigint::BigUint; use pkcs1::RsaPssParams; use pkcs8::spki::{der::Any, AlgorithmIdentifierOwned}; use rand_core::CryptoRngCore; @@ -34,7 +33,6 @@ use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; use crate::algorithms::pss::*; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; -use crate::key::to_uint_exact; use crate::traits::PublicKeyParts; use crate::traits::SignatureScheme; use crate::{RsaPrivateKey, RsaPublicKey}; @@ -107,7 +105,7 @@ impl SignatureScheme for Pss { verify( pub_key, hashed, - &BigUint::from_bytes_be(sig), + &BoxedUint::from_be_slice(sig, sig.len() * 8)?, sig.len(), &mut *self.digest, self.salt_len, @@ -128,7 +126,7 @@ impl Debug for Pss { pub(crate) fn verify( pub_key: &RsaPublicKey, hashed: &[u8], - sig: &BigUint, + sig: &BoxedUint, sig_len: usize, digest: &mut dyn DynDigest, salt_len: usize, @@ -137,10 +135,6 @@ pub(crate) fn verify( return Err(Error::Verification); } - let sig = to_uint_exact( - sig.clone(), - crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), - ); let mut em = uint_to_be_pad(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; emsa_pss_verify(hashed, &mut em, salt_len, digest, pub_key.n().bits()) From 7211bfabd4883f90ee15e44daae1ddcfef572de3 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 1 Dec 2023 11:27:50 +0100 Subject: [PATCH 19/51] cleanup rsapublickey --- src/key.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/key.rs b/src/key.rs index 6d4fd316..4d5161a0 100644 --- a/src/key.rs +++ b/src/key.rs @@ -23,7 +23,7 @@ use crate::traits::keys::{CrtValueNew, PrivateKeyPartsNew, PublicKeyPartsNew}; use crate::traits::{PaddingScheme, PublicKeyParts, SignatureScheme}; /// Represents the public part of an RSA key. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct RsaPublicKey { /// Modulus: product of prime numbers `p` and `q` @@ -34,16 +34,24 @@ pub struct RsaPublicKey { /// Typically 0x10001 (65537) e: BoxedUint, + #[cfg_attr(feature = "serde", serde(skip))] n_params: BoxedResidueParams, } -// TODO: derive `Hash` impl when `BoxedUint` supports it +impl Eq for RsaPublicKey {} +impl PartialEq for RsaPublicKey { + #[inline] + fn eq(&self, other: &RsaPublicKey) -> bool { + self.n == other.n && self.e == other.e + } +} + impl Hash for RsaPublicKey { fn hash(&self, state: &mut H) { // Domain separator for RSA private keys state.write(b"RsaPublicKey"); - Hash::hash(&self.n.as_words(), state); - Hash::hash(&self.e.as_words(), state); + Hash::hash(&self.n, state); + Hash::hash(&self.e, state); } } From c071ba1703d2baab0d4489d6cde96341f2aa178a Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 1 Dec 2023 11:35:18 +0100 Subject: [PATCH 20/51] store exponent as u64 --- src/algorithms/rsa.rs | 4 ++-- src/key.rs | 29 ++++++++++++++++------------- src/traits/keys.rs | 5 +++-- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 160f93ca..e217006d 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -21,7 +21,7 @@ use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew}; /// or signature scheme. See the [module-level documentation][crate::hazmat] for more information. #[inline] pub fn rsa_encrypt(key: &K, m: &BoxedUint) -> Result { - let res = pow_mod_params(m, key.e(), key.n_params()); + let res = pow_mod_params(m, &BoxedUint::from(key.e()), key.n_params()); Ok(res) } @@ -164,7 +164,7 @@ fn blind( let blinded = { // r^e (mod n) - let mut rpowe = pow_mod_params(&r, key.e(), n_params.clone()); + let mut rpowe = pow_mod_params(&r, &BoxedUint::from(key.e()), n_params.clone()); // c * r^e (mod n) let c = mul_mod_params(c, &rpowe, n_params.clone()); rpowe.zeroize(); diff --git a/src/key.rs b/src/key.rs index 4d5161a0..d75309a5 100644 --- a/src/key.rs +++ b/src/key.rs @@ -32,7 +32,7 @@ pub struct RsaPublicKey { /// order to encrypt it. /// /// Typically 0x10001 (65537) - e: BoxedUint, + e: u64, #[cfg_attr(feature = "serde", serde(skip))] n_params: BoxedResidueParams, @@ -155,8 +155,8 @@ impl PublicKeyPartsNew for RsaPublicKey { &self.n } - fn e(&self) -> &BoxedUint { - &self.e + fn e(&self) -> u64 { + self.e } fn n_params(&self) -> BoxedResidueParams { @@ -207,13 +207,12 @@ impl RsaPublicKey { /// Create a new public key from its components. pub fn new_with_max_size(n: BigUint, e: BigUint, max_size: usize) -> Result { check_public_with_max_size(&n, &e, max_size)?; + let e = e.to_u64().unwrap(); let raw_n = to_uint(n); let n_params = BoxedResidueParams::new(raw_n.clone()).unwrap(); let n = NonZero::new(raw_n).unwrap(); - // widen to 64bit - let e = to_uint_exact(e, 64); let k = Self { n, e, n_params }; Ok(k) @@ -229,7 +228,7 @@ impl RsaPublicKey { let raw_n = to_uint(n); let n_params = BoxedResidueParams::new(raw_n.clone()).unwrap(); let n = NonZero::new(raw_n).unwrap(); - let e = to_uint_exact(e, 64); + let e = e.to_u64().unwrap(); Self { n, e, n_params } } } @@ -265,8 +264,8 @@ impl PublicKeyPartsNew for RsaPrivateKey { &self.pubkey_components.n } - fn e(&self) -> &BoxedUint { - &self.pubkey_components.e + fn e(&self) -> u64 { + self.pubkey_components.e } fn n_params(&self) -> BoxedResidueParams { @@ -317,8 +316,8 @@ impl RsaPrivateKey { primes: Vec, ) -> Result { let n = to_uint(n.clone()); + let e = e.to_u64().ok_or_else(|| Error::InvalidExponent)?; let nbits = n.bits_precision(); - let e = to_uint_exact(e, 64); let d = to_uint_exact(d, nbits); let primes = primes .into_iter() @@ -329,7 +328,7 @@ impl RsaPrivateKey { pub(crate) fn from_components_new( n: BoxedUint, - e: BoxedUint, + e: u64, d: BoxedUint, mut primes: Vec, ) -> Result { @@ -345,7 +344,11 @@ impl RsaPrivateKey { } // Recover `p` and `q` from `d`. // See method in Appendix C.2: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf - let (p, q) = recover_primes(&to_biguint(&n), &to_biguint(&e), &to_biguint(&d))?; + let (p, q) = recover_primes( + &to_biguint(&n), + &BigUint::from_u64(e).unwrap(), + &to_biguint(&d), + )?; primes.push(to_uint_exact(p, nbits)); primes.push(to_uint_exact(q, nbits)); should_validate = true; @@ -494,7 +497,7 @@ impl RsaPrivateKey { // exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1 // mod p. Thus a^de ≡ a mod n for all a coprime to n, as required. let d = self.d.widen(2 * self.d.bits_precision()); - let de = d.wrapping_mul(&self.pubkey_components.e); + let de = d.wrapping_mul(&BoxedUint::from(self.pubkey_components.e)); for prime in &self.primes { let prime = prime.widen(d.bits_precision()); @@ -683,7 +686,7 @@ mod tests { let private_key = RsaPrivateKey { pubkey_components: RsaPublicKey { n: NonZero::new(raw_n.clone()).unwrap(), - e: BoxedUint::from(200u64), + e: 200u64, n_params: BoxedResidueParams::new(raw_n).unwrap(), }, d: BoxedUint::from(123u64), diff --git a/src/traits/keys.rs b/src/traits/keys.rs index a6b26630..7d4afbce 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -4,6 +4,7 @@ use alloc::vec::Vec; use crypto_bigint::{modular::BoxedResidueParams, BoxedUint, NonZero}; use num_bigint::{BigInt, BigUint, IntoBigInt}; +use num_traits::FromPrimitive; use zeroize::Zeroize; use crate::key::to_biguint; @@ -28,7 +29,7 @@ pub trait PublicKeyPartsNew { fn n(&self) -> &NonZero; /// Returns the public exponent of the key. - fn e(&self) -> &BoxedUint; + fn e(&self) -> u64; fn n_params(&self) -> BoxedResidueParams; @@ -49,7 +50,7 @@ impl PublicKeyParts for T { } fn e(&self) -> BigUint { - to_biguint(PublicKeyPartsNew::e(self)) + BigUint::from_u64(PublicKeyPartsNew::e(self)).unwrap() } fn size(&self) -> usize { From a811be0af3e20ef680b3a3defc43ff9c1bcc6c7c Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 2 Dec 2023 13:16:47 +0100 Subject: [PATCH 21/51] fix: handle large m2 --- src/algorithms/rsa.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index e217006d..f626338e 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -78,7 +78,7 @@ pub fn rsa_decrypt( let p_params = priv_key.p_params().unwrap(); let q_params = priv_key.q_params().unwrap(); - let p = &priv_key.primes()[0]; + let _p = &priv_key.primes()[0]; let q = &priv_key.primes()[1]; // precomputed: dP = (1/e) mod (p-1) = d mod (p-1) @@ -89,11 +89,16 @@ pub fn rsa_decrypt( // m2 = c^dQ mod q let m2 = pow_mod_params(&c, &dq, q_params.clone()); + // (m1 - m2) mod p = (m1 mod p) - (m2 mod p) mod p + let m1r = BoxedResidue::new(&m1, p_params.clone()); + let m2r = BoxedResidue::new(&m2, p_params.clone()); + let x = m1r.sub(&m2r); + // precomputed: qInv = (1/q) mod p + let qinv = BoxedResidue::new(&qinv, p_params.clone()); // h = qInv.(m1 - m2) mod p - let x = m1.sub_mod(&m2, p); - let h = mul_mod_params(qinv, &x, p_params.clone()); + let h = qinv.mul(&x).retrieve(); // m = m2 + h.q let m = m2.wrapping_add(&h.wrapping_mul(q)); // TODO: verify wrapping is correct here m From 102953da274c135124f27b5b68a96271786b0f8b Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 2 Dec 2023 13:21:15 +0100 Subject: [PATCH 22/51] cache boxedresiduie for qinv --- src/algorithms/rsa.rs | 1 - src/key.rs | 14 +++++++------- src/traits/keys.rs | 9 ++++++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index f626338e..77cf681a 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -95,7 +95,6 @@ pub fn rsa_decrypt( let x = m1r.sub(&m2r); // precomputed: qInv = (1/q) mod p - let qinv = BoxedResidue::new(&qinv, p_params.clone()); // h = qInv.(m1 - m2) mod p let h = qinv.mul(&x).retrieve(); diff --git a/src/key.rs b/src/key.rs index d75309a5..3f1ee820 100644 --- a/src/key.rs +++ b/src/key.rs @@ -111,7 +111,7 @@ pub(crate) struct PrecomputedValues { /// D mod (Q-1) pub(crate) dq: BoxedUint, /// Q^-1 mod P - pub(crate) qinv: BoxedUint, + pub(crate) qinv: BoxedResidue, pub(crate) p_params: BoxedResidueParams, pub(crate) q_params: BoxedResidueParams, @@ -121,7 +121,6 @@ impl Zeroize for PrecomputedValues { fn zeroize(&mut self) { self.dp.zeroize(); self.dq.zeroize(); - self.qinv.zeroize(); } } @@ -436,19 +435,20 @@ impl RsaPrivateKey { // TODO: error handling + let p_params = BoxedResidueParams::new(p.clone()).unwrap(); + let q_params = BoxedResidueParams::new(q.clone()).unwrap(); + 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 = q.inv_mod(p); + let qinv = BoxedResidue::new(q, p_params.clone()); + let qinv = qinv.invert(); if qinv.is_none().into() { return Err(Error::InvalidPrime); } let qinv = qinv.unwrap(); - let p_params = BoxedResidueParams::new(p.clone()).unwrap(); - let q_params = BoxedResidueParams::new(q.clone()).unwrap(); - self.precomputed = Some(PrecomputedValues { dp, dq, @@ -570,7 +570,7 @@ impl PrivateKeyPartsNew for RsaPrivateKey { self.precomputed.as_ref().map(|p| &p.dq) } - fn qinv(&self) -> Option<&BoxedUint> { + fn qinv(&self) -> Option<&BoxedResidue> { self.precomputed.as_ref().map(|p| &p.qinv) } diff --git a/src/traits/keys.rs b/src/traits/keys.rs index 7d4afbce..671d0647 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -2,7 +2,10 @@ use alloc::vec::Vec; -use crypto_bigint::{modular::BoxedResidueParams, BoxedUint, NonZero}; +use crypto_bigint::{ + modular::{BoxedResidue, BoxedResidueParams}, + BoxedUint, NonZero, +}; use num_bigint::{BigInt, BigUint, IntoBigInt}; use num_traits::FromPrimitive; use zeroize::Zeroize; @@ -98,7 +101,7 @@ impl PrivateKeyParts for T { PrivateKeyPartsNew::dq(self).map(to_biguint) } fn qinv(&self) -> Option { - PrivateKeyPartsNew::qinv(self).and_then(|v| to_biguint(v).into_bigint()) + PrivateKeyPartsNew::qinv(self).and_then(|v| to_biguint(&v.retrieve()).into_bigint()) } fn crt_values(&self) -> Option> { @@ -121,7 +124,7 @@ pub trait PrivateKeyPartsNew: PublicKeyPartsNew { fn dq(&self) -> Option<&BoxedUint>; /// Returns the precomputed qinv value, Q^-1 mod P - fn qinv(&self) -> Option<&BoxedUint>; + fn qinv(&self) -> Option<&BoxedResidue>; /// Returns an iterator over the CRT Values fn crt_values(&self) -> Option<&[CrtValueNew]>; From 57d6f95f9d9ddec44088a6002d6296b4c24b8bfe Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 2 Dec 2023 17:28:38 +0100 Subject: [PATCH 23/51] use some assign operations --- Cargo.lock | 2 +- src/algorithms/rsa.rs | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a053c0da..cb52c0f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,7 +125,7 @@ dependencies = [ [[package]] name = "crypto-bigint" version = "0.6.0-pre.0" -source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#31d9373e632da6dc3dcf4e61e83a8931839ba721" +source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#0cd01b7a210adfe0e8da7e0c875cc06360f3f934" dependencies = [ "rand_core", "serdect", diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 77cf681a..85c4f305 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -2,7 +2,7 @@ use alloc::borrow::Cow; use crypto_bigint::modular::{BoxedResidue, BoxedResidueParams}; -use crypto_bigint::{BoxedUint, RandomMod}; +use crypto_bigint::{BoxedUint, RandomMod, Wrapping}; use num_bigint::{BigUint, ModInverse}; use num_integer::{sqrt, Integer}; use num_traits::{FromPrimitive, One, Pow, Zero as _}; @@ -85,22 +85,25 @@ pub fn rsa_decrypt( // precomputed: dQ = (1/e) mod (q-1) = d mod (q-1) // m1 = c^dP mod p - let m1 = pow_mod_params(&c, &dp, p_params.clone()); + let cp = BoxedResidue::new(&c, p_params.clone()); + let mut m1 = cp.pow(&dp); // m2 = c^dQ mod q - let m2 = pow_mod_params(&c, &dq, q_params.clone()); + let cq = BoxedResidue::new(&c, q_params.clone()); + let m2 = cq.pow(&dq).retrieve(); // (m1 - m2) mod p = (m1 mod p) - (m2 mod p) mod p - let m1r = BoxedResidue::new(&m1, p_params.clone()); let m2r = BoxedResidue::new(&m2, p_params.clone()); - let x = m1r.sub(&m2r); + m1 -= &m2r; // precomputed: qInv = (1/q) mod p // h = qInv.(m1 - m2) mod p - let h = qinv.mul(&x).retrieve(); + let mut m: Wrapping = Wrapping(qinv.mul(&m1).retrieve()); + // m = m2 + h.q - let m = m2.wrapping_add(&h.wrapping_mul(q)); // TODO: verify wrapping is correct here - m + m *= Wrapping(q.clone()); + m += Wrapping(m2); + m.0 }; match ir { From 2cdd37c7b924a2eabf6a1d91412ae2833f68bb79 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 4 Dec 2023 22:22:48 +0100 Subject: [PATCH 24/51] update to latest crypto-bigint --- Cargo.lock | 2 +- src/key.rs | 8 ++++---- src/pkcs1v15.rs | 2 +- src/pkcs1v15/signature.rs | 2 +- src/pss.rs | 2 +- src/pss/signature.rs | 2 +- src/traits/keys.rs | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb52c0f4..866cdae8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,7 +125,7 @@ dependencies = [ [[package]] name = "crypto-bigint" version = "0.6.0-pre.0" -source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#0cd01b7a210adfe0e8da7e0c875cc06360f3f934" +source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#124b8cf79cc4532d0e27805cb390a642784d7ac2" dependencies = [ "rand_core", "serdect", diff --git a/src/key.rs b/src/key.rs index 3f1ee820..30ce80ad 100644 --- a/src/key.rs +++ b/src/key.rs @@ -232,7 +232,7 @@ impl RsaPublicKey { } } -fn needed_bits(n: &BigUint) -> usize { +fn needed_bits(n: &BigUint) -> u32 { // widen to the max size bits let n_bits = n.bits(); @@ -625,7 +625,7 @@ pub(crate) fn to_biguint(uint: &BoxedUint) -> BigUint { BigUint::from_bytes_be(&uint.to_be_bytes()) } -pub(crate) fn to_uint_exact(big_uint: BigUint, nbits: usize) -> BoxedUint { +pub(crate) fn to_uint_exact(big_uint: BigUint, nbits: u32) -> BoxedUint { let res = inner_to_uint(big_uint); match res.bits_precision().cmp(&nbits) { @@ -643,13 +643,13 @@ fn inner_to_uint(big_uint: BigUint) -> BoxedUint { let mut padded_bytes = vec![0u8; pad_count]; padded_bytes.extend_from_slice(&bytes); - BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() * 8).unwrap() + BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() as u32 * 8).unwrap() } pub(crate) fn to_uint(big_uint: BigUint) -> BoxedUint { let nbits = needed_bits(&big_uint); let res = inner_to_uint(big_uint); - if res.bits_precision() < nbits { + if (res.bits_precision() as u32) < nbits { return res.widen(nbits); } res diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index 7488dab7..d974537e 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -126,7 +126,7 @@ impl SignatureScheme for Pkcs1v15Sign { pub_key, self.prefix.as_ref(), hashed, - &BoxedUint::from_be_slice(sig, sig.len() * 8)?, + &BoxedUint::from_be_slice(sig, sig.len() as u32 * 8)?, sig.len(), ) } diff --git a/src/pkcs1v15/signature.rs b/src/pkcs1v15/signature.rs index 89017ff1..4e3528bc 100644 --- a/src/pkcs1v15/signature.rs +++ b/src/pkcs1v15/signature.rs @@ -39,7 +39,7 @@ impl TryFrom<&[u8]> for Signature { let len = bytes.len(); Ok(Self { // TODO: how to convert error? - inner: BoxedUint::from_be_slice(bytes, len * 8).unwrap(), + inner: BoxedUint::from_be_slice(bytes, len as u32 * 8).unwrap(), len, }) } diff --git a/src/pss.rs b/src/pss.rs index 454c6426..1ec0447d 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -105,7 +105,7 @@ impl SignatureScheme for Pss { verify( pub_key, hashed, - &BoxedUint::from_be_slice(sig, sig.len() * 8)?, + &BoxedUint::from_be_slice(sig, sig.len() as u32 * 8)?, sig.len(), &mut *self.digest, self.salt_len, diff --git a/src/pss/signature.rs b/src/pss/signature.rs index 38d178e5..e135a870 100644 --- a/src/pss/signature.rs +++ b/src/pss/signature.rs @@ -40,7 +40,7 @@ impl TryFrom<&[u8]> for Signature { Ok(Self { len, // TODO: how to convert the error? - inner: BoxedUint::from_be_slice(bytes, len * 8).unwrap(), + inner: BoxedUint::from_be_slice(bytes, len as u32 * 8).unwrap(), }) } } diff --git a/src/traits/keys.rs b/src/traits/keys.rs index 671d0647..6beb52a6 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -36,14 +36,14 @@ pub trait PublicKeyPartsNew { fn n_params(&self) -> BoxedResidueParams; - fn n_bits_precision(&self) -> usize { + fn n_bits_precision(&self) -> u32 { self.n().bits_precision() } /// Returns the modulus size in bytes. Raw signatures and ciphertexts for /// or by this public key will have the same size. fn size(&self) -> usize { - (self.n().bits() + 7) / 8 + (self.n().bits() as usize + 7) / 8 } } From f7fa66985a1375ff7f7df76cf3dc142098d93ed6 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Tue, 5 Dec 2023 11:18:06 +0100 Subject: [PATCH 25/51] update crypto-bigint --- Cargo.lock | 2 +- src/algorithms/rsa.rs | 10 +++++----- src/key.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 866cdae8..ae2080fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,7 +125,7 @@ dependencies = [ [[package]] name = "crypto-bigint" version = "0.6.0-pre.0" -source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#124b8cf79cc4532d0e27805cb390a642784d7ac2" +source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#bc53cfee094d66f4fbcc7e44139ef78117550b0b" dependencies = [ "rand_core", "serdect", diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 85c4f305..671d3bc4 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -85,14 +85,14 @@ pub fn rsa_decrypt( // precomputed: dQ = (1/e) mod (q-1) = d mod (q-1) // m1 = c^dP mod p - let cp = BoxedResidue::new(&c, p_params.clone()); + let cp = BoxedResidue::new(c.clone().into_owned(), p_params.clone()); let mut m1 = cp.pow(&dp); // m2 = c^dQ mod q - let cq = BoxedResidue::new(&c, q_params.clone()); + let cq = BoxedResidue::new(c.into_owned(), q_params.clone()); let m2 = cq.pow(&dq).retrieve(); // (m1 - m2) mod p = (m1 mod p) - (m2 mod p) mod p - let m2r = BoxedResidue::new(&m2, p_params.clone()); + let m2r = BoxedResidue::new(m2.clone(), p_params.clone()); m1 -= &m2r; // precomputed: qInv = (1/q) mod p @@ -197,8 +197,8 @@ fn pow_mod_params(base: &BoxedUint, exp: &BoxedUint, n_params: BoxedResidueParam /// Computes `lhs.mul_mod(rhs, n)` with precomputed `n_params`. fn mul_mod_params(lhs: &BoxedUint, rhs: &BoxedUint, n_params: BoxedResidueParams) -> BoxedUint { // TODO: nicer api in crypto-bigint? - let lhs = BoxedResidue::new(lhs, n_params.clone()); - let rhs = BoxedResidue::new(rhs, n_params); + let lhs = BoxedResidue::new(lhs.clone(), n_params.clone()); + let rhs = BoxedResidue::new(rhs.clone(), n_params); (lhs * rhs).retrieve() } diff --git a/src/key.rs b/src/key.rs index 30ce80ad..a5932e35 100644 --- a/src/key.rs +++ b/src/key.rs @@ -442,7 +442,7 @@ impl RsaPrivateKey { let dp = d.rem_vartime(&x); let x = NonZero::new(q.wrapping_sub(&BoxedUint::one())).unwrap(); let dq = d.rem_vartime(&x); - let qinv = BoxedResidue::new(q, p_params.clone()); + let qinv = BoxedResidue::new(q.clone(), p_params.clone()); let qinv = qinv.invert(); if qinv.is_none().into() { return Err(Error::InvalidPrime); @@ -666,7 +666,7 @@ pub(crate) fn reduce(n: &BoxedUint, p: BoxedResidueParams) -> BoxedResidue { }; let n_reduced = n.rem_vartime(&modulus).widen(p.bits_precision()); - BoxedResidue::new(&n_reduced, p) + BoxedResidue::new(n_reduced, p) } #[cfg(test)] From 851cbac2123aebe1f0404de671ed59693178ff3b Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Thu, 7 Dec 2023 13:50:53 +0100 Subject: [PATCH 26/51] use branch --- Cargo.lock | 2 +- Cargo.toml | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae2080fe..e5964117 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,7 +125,7 @@ dependencies = [ [[package]] name = "crypto-bigint" version = "0.6.0-pre.0" -source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#bc53cfee094d66f4fbcc7e44139ef78117550b0b" +source = "git+https://github.com/RustCrypto/crypto-bigint?branch=boxed-residue/almost-montgomery-multiplication#7551b5aeae6ca1fa4d4a77a9c11f616700ff98d9" dependencies = [ "rand_core", "serdect", diff --git a/Cargo.toml b/Cargo.toml index f9612117..91547222 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,5 +66,9 @@ rustdoc-args = ["--cfg", "docsrs"] [profile.dev] opt-level = 2 +[profile.bench] +debug = true + [patch.crates-io] -crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint", branch = "master" } \ No newline at end of file +crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint", branch = "boxed-residue/almost-montgomery-multiplication" } +# crypto-bigint = { path = "../rustcrypto/crypto-bigint" } \ No newline at end of file From 37558f6e8575830cb0644783c8f71d3d509de930 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Thu, 7 Dec 2023 20:45:19 +0100 Subject: [PATCH 27/51] use BoxedResidueParams::new_vartime --- src/key.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/key.rs b/src/key.rs index a5932e35..b4b286f1 100644 --- a/src/key.rs +++ b/src/key.rs @@ -209,7 +209,7 @@ impl RsaPublicKey { let e = e.to_u64().unwrap(); let raw_n = to_uint(n); - let n_params = BoxedResidueParams::new(raw_n.clone()).unwrap(); + let n_params = BoxedResidueParams::new_vartime(raw_n.clone()).unwrap(); let n = NonZero::new(raw_n).unwrap(); let k = Self { n, e, n_params }; @@ -225,7 +225,7 @@ impl RsaPublicKey { /// [`RsaPublicKey::new_with_max_size`] instead. pub fn new_unchecked(n: BigUint, e: BigUint) -> Self { let raw_n = to_uint(n); - let n_params = BoxedResidueParams::new(raw_n.clone()).unwrap(); + let n_params = BoxedResidueParams::new_vartime(raw_n.clone()).unwrap(); let n = NonZero::new(raw_n).unwrap(); let e = e.to_u64().unwrap(); Self { n, e, n_params } @@ -331,7 +331,7 @@ impl RsaPrivateKey { d: BoxedUint, mut primes: Vec, ) -> Result { - let n_params = BoxedResidueParams::new(n.clone()).unwrap(); + let n_params = BoxedResidueParams::new_vartime(n.clone()).unwrap(); let n_c = NonZero::new(n.clone()).unwrap(); let nbits = n_c.bits_precision(); @@ -435,8 +435,8 @@ impl RsaPrivateKey { // TODO: error handling - let p_params = BoxedResidueParams::new(p.clone()).unwrap(); - let q_params = BoxedResidueParams::new(q.clone()).unwrap(); + let p_params = BoxedResidueParams::new_vartime(p.clone()).unwrap(); + let q_params = BoxedResidueParams::new_vartime(q.clone()).unwrap(); let x = NonZero::new(p.wrapping_sub(&BoxedUint::one())).unwrap(); let dp = d.rem_vartime(&x); @@ -687,7 +687,7 @@ mod tests { pubkey_components: RsaPublicKey { n: NonZero::new(raw_n.clone()).unwrap(), e: 200u64, - n_params: BoxedResidueParams::new(raw_n).unwrap(), + n_params: BoxedResidueParams::new_vartime(raw_n).unwrap(), }, d: BoxedUint::from(123u64), primes: vec![], From 2634f6507ab18e63939d2e6c34b79795c4fdcac3 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Thu, 14 Dec 2023 13:55:33 +0100 Subject: [PATCH 28/51] update to latest master --- Cargo.lock | 16 ++++++++-------- Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e5964117..ffac2b21 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -124,8 +124,8 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.6.0-pre.0" -source = "git+https://github.com/RustCrypto/crypto-bigint?branch=boxed-residue/almost-montgomery-multiplication#7551b5aeae6ca1fa4d4a77a9c11f616700ff98d9" +version = "0.6.0-pre.1" +source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#4bf6932cee08af70d0a05625b540242522cc77f3" dependencies = [ "rand_core", "serdect", @@ -254,9 +254,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.150" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libm" @@ -512,9 +512,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.26" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ "bitflags 2.4.1", "errno", @@ -666,9 +666,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.39" +version = "2.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 91547222..f8d23c42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,5 +70,5 @@ opt-level = 2 debug = true [patch.crates-io] -crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint", branch = "boxed-residue/almost-montgomery-multiplication" } +crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint", branch = "master" } # crypto-bigint = { path = "../rustcrypto/crypto-bigint" } \ No newline at end of file From 56f6f27008b91fb21ae74cd42691d1a854778480 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 22 Mar 2024 23:31:58 +0100 Subject: [PATCH 29/51] switch to latest crypto-bigint --- Cargo.lock | 223 ++++++++++++++---------------------------- Cargo.toml | 6 +- src/algorithms/rsa.rs | 29 +++--- src/key.rs | 55 ++++++----- src/pkcs1v15.rs | 3 +- src/pss.rs | 3 +- src/traits/keys.rs | 10 +- 7 files changed, 126 insertions(+), 203 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ffac2b21..3c672c1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", @@ -48,15 +48,9 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "block-buffer" @@ -109,24 +103,26 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crypto-bigint" -version = "0.6.0-pre.1" -source = "git+https://github.com/RustCrypto/crypto-bigint?branch=master#4bf6932cee08af70d0a05625b540242522cc77f3" +version = "0.6.0-pre.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1943d7beadd9ce2b25f3bae73b9e9336fccc1edf38bdec1ed58d3aa183989e11" dependencies = [ + "num-traits", "rand_core", "serdect", "subtle", @@ -173,7 +169,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -200,9 +196,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -236,9 +232,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -254,9 +250,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.151" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libm" @@ -266,9 +262,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "num-bigint-dig" @@ -290,19 +286,18 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg", "num-integer", @@ -311,9 +306,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", "libm", @@ -384,9 +379,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -399,7 +394,7 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.1", + "bitflags", "lazy_static", "num-traits", "rand", @@ -419,9 +414,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -465,15 +460,6 @@ dependencies = [ "rand_core", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "regex-syntax" version = "0.8.2" @@ -512,15 +498,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.1", + "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -557,18 +543,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", @@ -638,9 +624,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "spin" @@ -666,9 +652,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.41" +version = "2.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" dependencies = [ "proc-macro2", "quote", @@ -677,15 +663,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -727,137 +712,71 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "zeroize" diff --git a/Cargo.toml b/Cargo.toml index f8d23c42..80925811 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ pkcs8 = { version = "0.10.2", default-features = false, features = ["alloc"] } signature = { version = ">2.0, <2.3", default-features = false , features = ["alloc", "digest", "rand_core"] } spki = { version = "0.7.2", default-features = false, features = ["alloc"] } zeroize = { version = "1.5", features = ["alloc"] } -crypto-bigint = { version = "0.6.0-pre.0", features = ["zeroize", "alloc"] } +crypto-bigint = { version = "0.6.0-pre.12", features = ["zeroize", "alloc"] } # optional dependencies sha1 = { version = "0.10.5", optional = true, default-features = false, features = ["oid"] } @@ -70,5 +70,5 @@ opt-level = 2 debug = true [patch.crates-io] -crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint", branch = "master" } -# crypto-bigint = { path = "../rustcrypto/crypto-bigint" } \ No newline at end of file +# crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint", branch = "master" } +# crypto-bigint = { path = "../rustcrypto/crypto-bigint" } diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 671d3bc4..da7b8d7d 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -1,8 +1,8 @@ //! Generic RSA implementation use alloc::borrow::Cow; -use crypto_bigint::modular::{BoxedResidue, BoxedResidueParams}; -use crypto_bigint::{BoxedUint, RandomMod, Wrapping}; +use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams}; +use crypto_bigint::{BoxedUint, InvMod, NonZero, RandomMod, Wrapping}; use num_bigint::{BigUint, ModInverse}; use num_integer::{sqrt, Integer}; use num_traits::{FromPrimitive, One, Pow, Zero as _}; @@ -42,12 +42,7 @@ pub fn rsa_decrypt( let n = priv_key.n(); let d = priv_key.d(); - if c >= n { - return Err(Error::Decryption); - } - - // TODO: is this fine? - if n.is_zero().into() { + if c >= n.as_ref() { return Err(Error::Decryption); } @@ -85,14 +80,14 @@ pub fn rsa_decrypt( // precomputed: dQ = (1/e) mod (q-1) = d mod (q-1) // m1 = c^dP mod p - let cp = BoxedResidue::new(c.clone().into_owned(), p_params.clone()); + let cp = BoxedMontyForm::new(c.clone().into_owned(), p_params.clone()); let mut m1 = cp.pow(&dp); // m2 = c^dQ mod q - let cq = BoxedResidue::new(c.into_owned(), q_params.clone()); + let cq = BoxedMontyForm::new(c.into_owned(), q_params.clone()); let m2 = cq.pow(&dq).retrieve(); // (m1 - m2) mod p = (m1 mod p) - (m2 mod p) mod p - let m2r = BoxedResidue::new(m2.clone(), p_params.clone()); + let m2r = BoxedMontyForm::new(m2.clone(), p_params.clone()); m1 -= &m2r; // precomputed: qInv = (1/q) mod p @@ -149,7 +144,7 @@ fn blind( rng: &mut R, key: &K, c: &BoxedUint, - n_params: &BoxedResidueParams, + n_params: &BoxedMontyParams, ) -> (BoxedUint, BoxedUint) { // Blinding involves multiplying c by r^e. // Then the decryption operation performs (m^e * r^e)^d mod n @@ -183,22 +178,22 @@ fn blind( } /// Given an m and and unblinding factor, unblind the m. -fn unblind(m: &BoxedUint, unblinder: &BoxedUint, n_params: BoxedResidueParams) -> BoxedUint { +fn unblind(m: &BoxedUint, unblinder: &BoxedUint, n_params: BoxedMontyParams) -> BoxedUint { // m * r^-1 (mod n) mul_mod_params(m, unblinder, n_params) } /// Computes `base.pow_mod(exp, n)` with precomputed `n_params`. -fn pow_mod_params(base: &BoxedUint, exp: &BoxedUint, n_params: BoxedResidueParams) -> BoxedUint { +fn pow_mod_params(base: &BoxedUint, exp: &BoxedUint, n_params: BoxedMontyParams) -> BoxedUint { let base = reduce(&base, n_params); base.pow(exp).retrieve() } /// Computes `lhs.mul_mod(rhs, n)` with precomputed `n_params`. -fn mul_mod_params(lhs: &BoxedUint, rhs: &BoxedUint, n_params: BoxedResidueParams) -> BoxedUint { +fn mul_mod_params(lhs: &BoxedUint, rhs: &BoxedUint, n_params: BoxedMontyParams) -> BoxedUint { // TODO: nicer api in crypto-bigint? - let lhs = BoxedResidue::new(lhs.clone(), n_params.clone()); - let rhs = BoxedResidue::new(rhs.clone(), n_params); + let lhs = BoxedMontyForm::new(lhs.clone(), n_params.clone()); + let rhs = BoxedMontyForm::new(rhs.clone(), n_params); (lhs * rhs).retrieve() } diff --git a/src/key.rs b/src/key.rs index b4b286f1..df199cd6 100644 --- a/src/key.rs +++ b/src/key.rs @@ -1,8 +1,8 @@ use alloc::vec::Vec; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; -use crypto_bigint::modular::{BoxedResidue, BoxedResidueParams}; -use crypto_bigint::{BoxedUint, Limb, NonZero}; +use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams}; +use crypto_bigint::{BoxedUint, InvMod, Limb, NonZero, Odd}; use num_bigint::BigUint; use num_integer::Integer; use num_traits::{FromPrimitive, ToPrimitive}; @@ -35,7 +35,7 @@ pub struct RsaPublicKey { e: u64, #[cfg_attr(feature = "serde", serde(skip))] - n_params: BoxedResidueParams, + n_params: BoxedMontyParams, } impl Eq for RsaPublicKey {} @@ -111,10 +111,10 @@ pub(crate) struct PrecomputedValues { /// D mod (Q-1) pub(crate) dq: BoxedUint, /// Q^-1 mod P - pub(crate) qinv: BoxedResidue, + pub(crate) qinv: BoxedMontyForm, - pub(crate) p_params: BoxedResidueParams, - pub(crate) q_params: BoxedResidueParams, + pub(crate) p_params: BoxedMontyParams, + pub(crate) q_params: BoxedMontyParams, } impl Zeroize for PrecomputedValues { @@ -158,7 +158,7 @@ impl PublicKeyPartsNew for RsaPublicKey { self.e } - fn n_params(&self) -> BoxedResidueParams { + fn n_params(&self) -> BoxedMontyParams { self.n_params.clone() } } @@ -209,7 +209,8 @@ impl RsaPublicKey { let e = e.to_u64().unwrap(); let raw_n = to_uint(n); - let n_params = BoxedResidueParams::new_vartime(raw_n.clone()).unwrap(); + let n_odd = Odd::new(raw_n.clone()).unwrap(); + let n_params = BoxedMontyParams::new(n_odd); let n = NonZero::new(raw_n).unwrap(); let k = Self { n, e, n_params }; @@ -225,7 +226,8 @@ impl RsaPublicKey { /// [`RsaPublicKey::new_with_max_size`] instead. pub fn new_unchecked(n: BigUint, e: BigUint) -> Self { let raw_n = to_uint(n); - let n_params = BoxedResidueParams::new_vartime(raw_n.clone()).unwrap(); + let n_odd = Odd::new(raw_n.clone()).unwrap(); + let n_params = BoxedMontyParams::new(n_odd); let n = NonZero::new(raw_n).unwrap(); let e = e.to_u64().unwrap(); Self { n, e, n_params } @@ -267,7 +269,7 @@ impl PublicKeyPartsNew for RsaPrivateKey { self.pubkey_components.e } - fn n_params(&self) -> BoxedResidueParams { + fn n_params(&self) -> BoxedMontyParams { self.pubkey_components.n_params.clone() } } @@ -322,17 +324,19 @@ impl RsaPrivateKey { .into_iter() .map(|p| to_uint_exact(p, nbits)) .collect(); - Self::from_components_new(n, e, d, primes) + + let n_odd = Odd::new(n).unwrap(); + Self::from_components_new(n_odd, e, d, primes) } pub(crate) fn from_components_new( - n: BoxedUint, + n: Odd, e: u64, d: BoxedUint, mut primes: Vec, ) -> Result { - let n_params = BoxedResidueParams::new_vartime(n.clone()).unwrap(); - let n_c = NonZero::new(n.clone()).unwrap(); + let n_params = BoxedMontyParams::new(n.clone()); + let n_c = NonZero::new(n.as_ref().clone()).unwrap(); let nbits = n_c.bits_precision(); let mut should_validate = false; @@ -435,14 +439,16 @@ impl RsaPrivateKey { // TODO: error handling - let p_params = BoxedResidueParams::new_vartime(p.clone()).unwrap(); - let q_params = BoxedResidueParams::new_vartime(q.clone()).unwrap(); + let p_odd = Odd::new(p.clone()).unwrap(); + let p_params = BoxedMontyParams::new(p_odd); + let q_odd = Odd::new(q.clone()).unwrap(); + let q_params = BoxedMontyParams::new(q_odd); 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 = BoxedResidue::new(q.clone(), p_params.clone()); + let qinv = BoxedMontyForm::new(q.clone(), p_params.clone()); let qinv = qinv.invert(); if qinv.is_none().into() { return Err(Error::InvalidPrime); @@ -570,7 +576,7 @@ impl PrivateKeyPartsNew for RsaPrivateKey { self.precomputed.as_ref().map(|p| &p.dq) } - fn qinv(&self) -> Option<&BoxedResidue> { + fn qinv(&self) -> Option<&BoxedMontyForm> { self.precomputed.as_ref().map(|p| &p.qinv) } @@ -578,11 +584,11 @@ impl PrivateKeyPartsNew for RsaPrivateKey { None } - fn p_params(&self) -> Option<&BoxedResidueParams> { + fn p_params(&self) -> Option<&BoxedMontyParams> { self.precomputed.as_ref().map(|p| &p.p_params) } - fn q_params(&self) -> Option<&BoxedResidueParams> { + fn q_params(&self) -> Option<&BoxedMontyParams> { self.precomputed.as_ref().map(|p| &p.q_params) } } @@ -655,9 +661,9 @@ pub(crate) fn to_uint(big_uint: BigUint) -> BoxedUint { res } -pub(crate) fn reduce(n: &BoxedUint, p: BoxedResidueParams) -> BoxedResidue { +pub(crate) fn reduce(n: &BoxedUint, p: BoxedMontyParams) -> BoxedMontyForm { let bits_precision = p.modulus().bits_precision(); - let modulus = NonZero::new(p.modulus().clone()).unwrap(); + let modulus = NonZero::new(p.modulus().as_ref().clone()).unwrap(); let n = match n.bits_precision().cmp(&bits_precision) { Ordering::Less => n.widen(bits_precision), @@ -666,7 +672,7 @@ pub(crate) fn reduce(n: &BoxedUint, p: BoxedResidueParams) -> BoxedResidue { }; let n_reduced = n.rem_vartime(&modulus).widen(p.bits_precision()); - BoxedResidue::new(n_reduced, p) + BoxedMontyForm::new(n_reduced, p) } #[cfg(test)] @@ -683,11 +689,12 @@ mod tests { #[test] fn test_from_into() { let raw_n = BoxedUint::from(101u64); + let n_odd = Odd::new(raw_n.clone()).unwrap(); let private_key = RsaPrivateKey { pubkey_components: RsaPublicKey { n: NonZero::new(raw_n.clone()).unwrap(), e: 200u64, - n_params: BoxedResidueParams::new_vartime(raw_n).unwrap(), + n_params: BoxedMontyParams::new(n_odd), }, d: BoxedUint::from(123u64), primes: vec![], diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index d974537e..fadf80cd 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -216,7 +216,8 @@ fn verify( sig: &BoxedUint, sig_len: usize, ) -> Result<()> { - if sig >= crate::traits::keys::PublicKeyPartsNew::n(pub_key) || sig_len != pub_key.size() { + let n = crate::traits::keys::PublicKeyPartsNew::n(pub_key); + if sig >= n.as_ref() || sig_len != pub_key.size() { return Err(Error::Verification); } diff --git a/src/pss.rs b/src/pss.rs index 1ec0447d..ef682630 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -150,7 +150,8 @@ pub(crate) fn verify_digest( where D: Digest + FixedOutputReset, { - if sig >= crate::traits::keys::PublicKeyPartsNew::n(pub_key) || sig_len != pub_key.size() { + let n = crate::traits::keys::PublicKeyPartsNew::n(pub_key); + if sig >= n.as_ref() || sig_len != pub_key.size() { return Err(Error::Verification); } diff --git a/src/traits/keys.rs b/src/traits/keys.rs index 6beb52a6..94d2bb3a 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -3,7 +3,7 @@ use alloc::vec::Vec; use crypto_bigint::{ - modular::{BoxedResidue, BoxedResidueParams}, + modular::{BoxedMontyForm, BoxedMontyParams}, BoxedUint, NonZero, }; use num_bigint::{BigInt, BigUint, IntoBigInt}; @@ -34,7 +34,7 @@ pub trait PublicKeyPartsNew { /// Returns the public exponent of the key. fn e(&self) -> u64; - fn n_params(&self) -> BoxedResidueParams; + fn n_params(&self) -> BoxedMontyParams; fn n_bits_precision(&self) -> u32 { self.n().bits_precision() @@ -124,14 +124,14 @@ pub trait PrivateKeyPartsNew: PublicKeyPartsNew { fn dq(&self) -> Option<&BoxedUint>; /// Returns the precomputed qinv value, Q^-1 mod P - fn qinv(&self) -> Option<&BoxedResidue>; + fn qinv(&self) -> Option<&BoxedMontyForm>; /// Returns an iterator over the CRT Values fn crt_values(&self) -> Option<&[CrtValueNew]>; - fn p_params(&self) -> Option<&BoxedResidueParams>; + fn p_params(&self) -> Option<&BoxedMontyParams>; - fn q_params(&self) -> Option<&BoxedResidueParams>; + fn q_params(&self) -> Option<&BoxedMontyParams>; } /// Contains the precomputed Chinese remainder theorem values. From fab7852b74e868b54109ebee33a58207749187c1 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 22 Mar 2024 23:42:44 +0100 Subject: [PATCH 30/51] cleanup --- src/algorithms/rsa.rs | 2 +- src/pkcs1v15/signature.rs | 6 +----- src/pss/signature.rs | 11 ++++------- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index da7b8d7d..903fa928 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -2,7 +2,7 @@ use alloc::borrow::Cow; use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams}; -use crypto_bigint::{BoxedUint, InvMod, NonZero, RandomMod, Wrapping}; +use crypto_bigint::{BoxedUint, InvMod, RandomMod, Wrapping}; use num_bigint::{BigUint, ModInverse}; use num_integer::{sqrt, Integer}; use num_traits::{FromPrimitive, One, Pow, Zero as _}; diff --git a/src/pkcs1v15/signature.rs b/src/pkcs1v15/signature.rs index 4e3528bc..d17d65de 100644 --- a/src/pkcs1v15/signature.rs +++ b/src/pkcs1v15/signature.rs @@ -1,8 +1,4 @@ -pub use ::signature::{ - hazmat::{PrehashSigner, PrehashVerifier}, - DigestSigner, DigestVerifier, Error, Keypair, RandomizedDigestSigner, RandomizedSigner, Result, - SignatureEncoding, Signer, Verifier, -}; +pub use ::signature::SignatureEncoding; use crypto_bigint::BoxedUint; use spki::{ der::{asn1::BitString, Result as DerResult}, diff --git a/src/pss/signature.rs b/src/pss/signature.rs index e135a870..332c9f13 100644 --- a/src/pss/signature.rs +++ b/src/pss/signature.rs @@ -1,8 +1,6 @@ -pub use ::signature::{ - hazmat::{PrehashSigner, PrehashVerifier}, - DigestSigner, DigestVerifier, Error, Keypair, RandomizedDigestSigner, RandomizedSigner, Result, - SignatureEncoding, Signer, Verifier, -}; +use alloc::{boxed::Box, string::ToString}; +use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex}; + use crypto_bigint::BoxedUint; use spki::{ der::{asn1::BitString, Result as DerResult}, @@ -10,8 +8,7 @@ use spki::{ }; use crate::algorithms::pad::uint_to_be_pad; -use alloc::{boxed::Box, string::ToString}; -use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex}; +pub use crate::signature::SignatureEncoding; /// RSASSA-PSS signatures as described in [RFC8017 § 8.1]. /// From 98f3faa3fa4bd7e576e5aba5becabb468c428b1a Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 22 Mar 2024 23:48:05 +0100 Subject: [PATCH 31/51] chore: update MSRV to 1.73 --- .github/workflows/ci.yml | 4 ++-- Cargo.toml | 2 +- README.md | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74188db1..0d738c57 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: rust: - - 1.72.0 # MSRV + - 1.73.0 # MSRV - stable target: - thumbv7em-none-eabi @@ -35,7 +35,7 @@ jobs: strategy: matrix: rust: - - 1.72.0 # MSRV + - 1.73.0 # MSRV - stable steps: - uses: actions/checkout@v4 diff --git a/Cargo.toml b/Cargo.toml index 68b3bc34..d92976b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/RustCrypto/RSA" keywords = ["rsa", "encryption", "security", "crypto"] categories = ["cryptography"] readme = "README.md" -rust-version = "1.72" +rust-version = "1.73" [dependencies] num-bigint = { version = "0.8.2", features = ["i128", "prime", "zeroize"], default-features = false, package = "num-bigint-dig" } diff --git a/README.md b/README.md index 7a301a68..f47e549b 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ You can follow our work on mitigating this issue in [#390]. ## Minimum Supported Rust Version (MSRV) -This crate supports Rust 1.72 or higher. +This crate supports Rust 1.73 or higher. In the future MSRV can be changed, but it will be done with a minor version bump. @@ -108,7 +108,7 @@ dual licensed as above, without any additional terms or conditions. [doc-link]: https://docs.rs/rsa [build-image]: https://github.com/rustcrypto/RSA/workflows/CI/badge.svg [build-link]: https://github.com/RustCrypto/RSA/actions?query=workflow%3ACI+branch%3Amaster -[msrv-image]: https://img.shields.io/badge/rustc-1.72+-blue.svg +[msrv-image]: https://img.shields.io/badge/rustc-1.73+-blue.svg [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260047-RSA [deps-image]: https://deps.rs/repo/github/RustCrypto/RSA/status.svg From 0db6317ca239ec7c0dbc537f929c945ec26da544 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 25 Mar 2024 11:26:13 +0100 Subject: [PATCH 32/51] refactor: remove remaining usage of num-bigint --- Cargo.lock | 73 ++-------- Cargo.toml | 10 +- src/algorithms/generate.rs | 45 +++--- src/algorithms/rsa.rs | 124 +++++++++-------- src/encoding.rs | 49 ++++--- src/key.rs | 241 ++++++++++++--------------------- src/lib.rs | 1 - src/oaep.rs | 22 +-- src/pkcs1v15.rs | 23 ++-- src/pkcs1v15/signing_key.rs | 12 +- src/pss.rs | 28 ++-- src/pss/blinded_signing_key.rs | 4 +- src/pss/signing_key.rs | 4 +- src/traits/keys.rs | 118 +--------------- tests/pkcs1.rs | 56 ++++---- tests/pkcs8.rs | 28 ++-- 16 files changed, 305 insertions(+), 533 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 194be123..3957220e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,12 +79,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "cbc" version = "0.1.2" @@ -159,6 +153,16 @@ dependencies = [ "rand_core", ] +[[package]] +name = "crypto-primes" +version = "0.6.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31bb1382ea4ef18b2da595f36ca284c7b6366d22264ac02f8baee109361cd6b0" +dependencies = [ + "crypto-bigint", + "rand_core", +] + [[package]] name = "der" version = "0.8.0-pre.0" @@ -283,9 +287,6 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin", -] [[package]] name = "libc" @@ -305,44 +306,6 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" -[[package]] -name = "num-bigint-dig" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" -dependencies = [ - "byteorder", - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand", - "serde", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.18" @@ -512,11 +475,9 @@ dependencies = [ "base64ct", "const-oid", "crypto-bigint", + "crypto-primes", "digest 0.11.0-pre.8", "hex-literal", - "num-bigint-dig", - "num-integer", - "num-traits", "pkcs1", "pkcs8", "proptest", @@ -672,18 +633,6 @@ dependencies = [ "rand_core", ] -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spki" version = "0.8.0-pre.0" diff --git a/Cargo.toml b/Cargo.toml index d92976b0..914c201e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,6 @@ readme = "README.md" rust-version = "1.73" [dependencies] -num-bigint = { version = "0.8.2", features = ["i128", "prime", "zeroize"], default-features = false, package = "num-bigint-dig" } -num-traits = { version= "0.2.9", default-features = false, features = ["libm"] } -num-integer = { version = "0.1.39", default-features = false } rand_core = { version = "0.6.4", default-features = false } const-oid = { version = "=0.10.0-pre.2", default-features = false } subtle = { version = "2.1.1", default-features = false } @@ -26,6 +23,7 @@ signature = { version = "=2.3.0-pre.3", default-features = false , features = [" spki = { version = "=0.8.0-pre.0", default-features = false, features = ["alloc"] } zeroize = { version = "1.5", features = ["alloc"] } crypto-bigint = { version = "0.6.0-pre.12", features = ["zeroize", "alloc"] } +crypto-primes = { version = "0.6.0-pre.0" } # optional dependencies sha1 = { version = "=0.11.0-pre.3", optional = true, default-features = false, features = ["oid"] } @@ -49,14 +47,12 @@ sha3 = { version = "=0.11.0-pre.3", default-features = false, features = ["oid"] name = "key" [features] -default = ["std", "pem", "u64_digit"] +default = ["std", "pem"] hazmat = [] getrandom = ["rand_core/getrandom"] -nightly = ["num-bigint/nightly"] -serde = ["dep:serde", "num-bigint/serde"] +serde = ["dep:serde", "crypto-bigint/serde"] pem = ["pkcs1/pem", "pkcs8/pem"] pkcs5 = ["pkcs8/encryption"] -u64_digit = ["num-bigint/u64_digit"] std = ["digest/std", "pkcs1/std", "pkcs8/std", "rand_core/std", "signature/std"] [package.metadata.docs.rs] diff --git a/src/algorithms/generate.rs b/src/algorithms/generate.rs index 7fa8acc1..ad89bcaf 100644 --- a/src/algorithms/generate.rs +++ b/src/algorithms/generate.rs @@ -1,10 +1,8 @@ //! Generate prime components for the RSA Private Key use alloc::vec::Vec; -use num_bigint::{BigUint, RandPrime}; -#[allow(unused_imports)] -use num_traits::Float; -use num_traits::Zero; +use crypto_bigint::{BoxedUint, Odd}; +use crypto_primes::generate_prime_with_rng; use rand_core::CryptoRngCore; use crate::{ @@ -13,10 +11,10 @@ use crate::{ }; pub struct RsaPrivateKeyComponents { - pub n: BigUint, - pub e: BigUint, - pub d: BigUint, - pub primes: Vec, + pub n: Odd, + pub e: u64, + pub d: BoxedUint, + pub primes: Vec, } /// Generates a multi-prime RSA keypair of the given bit size, public exponent, @@ -30,11 +28,11 @@ pub struct RsaPrivateKeyComponents { /// /// [1]: https://patents.google.com/patent/US4405829A/en /// [2]: http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf -pub(crate) fn generate_multi_prime_key_with_exp( +pub(crate) fn generate_multi_prime_key_with_exp( rng: &mut R, nprimes: usize, bit_size: usize, - exp: &BigUint, + exp: u64, ) -> Result { if nprimes < 2 { return Err(Error::NprimesTooSmall); @@ -56,9 +54,9 @@ pub(crate) fn generate_multi_prime_key_with_exp( } } - let mut primes = vec![BigUint::zero(); nprimes]; - let n_final: BigUint; - let d_final: BigUint; + let mut primes = vec![BoxedUint::zero(); nprimes]; + let n_final: Odd; + let d_final: BoxedUint; 'next: loop { let mut todo = bit_size; @@ -78,8 +76,9 @@ pub(crate) fn generate_multi_prime_key_with_exp( } for (i, prime) in primes.iter_mut().enumerate() { - *prime = rng.gen_prime(todo / (nprimes - i)); - todo -= prime.bits(); + let bits = (todo / (nprimes - i)) as u32; + *prime = generate_prime_with_rng(rng, bits, bits); + todo -= prime.bits() as usize; } // Makes sure that primes is pairwise unequal. @@ -93,7 +92,7 @@ pub(crate) fn generate_multi_prime_key_with_exp( let n = compute_modulus(&primes); - if n.bits() != bit_size { + if n.bits() as usize != bit_size { // This should never happen for nprimes == 2 because // gen_prime should set the top two bits in each prime. // For nprimes > 2 we hope it does not happen often. @@ -118,8 +117,6 @@ pub(crate) fn generate_multi_prime_key_with_exp( #[cfg(test)] mod tests { use super::*; - use num_bigint::BigUint; - use num_traits::FromPrimitive; use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; const EXP: u64 = 65537; @@ -127,12 +124,11 @@ mod tests { #[test] fn test_impossible_keys() { let mut rng = ChaCha8Rng::from_seed([42; 32]); - let exp = BigUint::from_u64(EXP).expect("invalid static exponent"); for i in 0..32 { - let _ = generate_multi_prime_key_with_exp(&mut rng, 2, i, &exp); - let _ = generate_multi_prime_key_with_exp(&mut rng, 3, i, &exp); - let _ = generate_multi_prime_key_with_exp(&mut rng, 4, i, &exp); - let _ = generate_multi_prime_key_with_exp(&mut rng, 5, i, &exp); + let _ = generate_multi_prime_key_with_exp(&mut rng, 2, i, EXP); + let _ = generate_multi_prime_key_with_exp(&mut rng, 3, i, EXP); + let _ = generate_multi_prime_key_with_exp(&mut rng, 4, i, EXP); + let _ = generate_multi_prime_key_with_exp(&mut rng, 5, i, EXP); } } @@ -141,11 +137,10 @@ mod tests { #[test] fn $name() { let mut rng = ChaCha8Rng::from_seed([42; 32]); - let exp = BigUint::from_u64(EXP).expect("invalid static exponent"); for _ in 0..10 { let components = - generate_multi_prime_key_with_exp(&mut rng, $multi, $size, &exp).unwrap(); + generate_multi_prime_key_with_exp(&mut rng, $multi, $size, EXP).unwrap(); assert_eq!(components.n.bits(), $size); assert_eq!(components.primes.len(), $multi); } diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 903fa928..7ca90c79 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -2,16 +2,13 @@ use alloc::borrow::Cow; use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams}; -use crypto_bigint::{BoxedUint, InvMod, RandomMod, Wrapping}; -use num_bigint::{BigUint, ModInverse}; -use num_integer::{sqrt, Integer}; -use num_traits::{FromPrimitive, One, Pow, Zero as _}; +use crypto_bigint::{BoxedUint, Gcd, InvMod, NonZero, Odd, RandomMod, Wrapping}; use rand_core::CryptoRngCore; -use zeroize::{Zeroize, Zeroizing}; +use zeroize::Zeroize; use crate::errors::{Error, Result}; use crate::key::reduce; -use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew}; +use crate::traits::keys::{PrivateKeyParts, PublicKeyParts}; /// ⚠️ Raw RSA encryption of m with the public key. No padding is performed. /// @@ -20,7 +17,7 @@ use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew}; /// Use this function with great care! Raw RSA should never be used without an appropriate padding /// or signature scheme. See the [module-level documentation][crate::hazmat] for more information. #[inline] -pub fn rsa_encrypt(key: &K, m: &BoxedUint) -> Result { +pub fn rsa_encrypt(key: &K, m: &BoxedUint) -> Result { let res = pow_mod_params(m, &BoxedUint::from(key.e()), key.n_params()); Ok(res) } @@ -36,7 +33,7 @@ pub fn rsa_encrypt(key: &K, m: &BoxedUint) -> Result( mut rng: Option<&mut R>, - priv_key: &impl PrivateKeyPartsNew, + priv_key: &impl PrivateKeyParts, c: &BoxedUint, ) -> Result { let n = priv_key.n(); @@ -122,7 +119,7 @@ pub fn rsa_decrypt( /// or signature scheme. See the [module-level documentation][crate::hazmat] for more information. #[inline] pub fn rsa_decrypt_and_check( - priv_key: &impl PrivateKeyPartsNew, + priv_key: &impl PrivateKeyParts, rng: Option<&mut R>, c: &BoxedUint, ) -> Result { @@ -140,7 +137,7 @@ pub fn rsa_decrypt_and_check( } /// Returns the blinded c, along with the unblinding factor. -fn blind( +fn blind( rng: &mut R, key: &K, c: &BoxedUint, @@ -200,78 +197,92 @@ fn mul_mod_params(lhs: &BoxedUint, rhs: &BoxedUint, n_params: BoxedMontyParams) /// The following (deterministic) algorithm also recovers the prime factors `p` and `q` of a modulus `n`, given the /// public exponent `e` and private exponent `d` using the method described in /// [NIST 800-56B Appendix C.2](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf). -pub fn recover_primes(n: &BigUint, e: &BigUint, d: &BigUint) -> Result<(BigUint, BigUint)> { +pub fn recover_primes( + n: &NonZero, + e: u64, + d: &BoxedUint, +) -> Result<(BoxedUint, BoxedUint)> { // Check precondition - let two = BigUint::from_u8(2).unwrap(); - if e <= &two.pow(16u32) || e >= &two.pow(256u32) { + if e <= 2u64.pow(16) || e >= 2u64.pow(256) { return Err(Error::InvalidArguments); } // 1. Let a = (de – 1) × GCD(n – 1, de – 1). - let one = BigUint::one(); - let a = Zeroizing::new((d * e - &one) * (n - &one).gcd(&(d * e - &one))); + let one = BoxedUint::one(); + let e = BoxedUint::from(e); + + let a1 = d * &e - &one; + let a2 = (n.as_ref() - &one).gcd(&(d * e - &one)).unwrap(); + let a = a1 * a2; // 2. Let m = floor(a /n) and r = a – m n, so that a = m n + r and 0 ≤ r < n. - let m = Zeroizing::new(&*a / n); - let r = Zeroizing::new(&*a - &*m * n); + let m = &a / n; + let r = a - &m * n.as_ref(); // 3. Let b = ( (n – r)/(m + 1) ) + 1; if b is not an integer or b^2 ≤ 4n, then output an error indicator, // and exit without further processing. - let modulus_check = Zeroizing::new((n - &*r) % (&*m + &one)); - if !modulus_check.is_zero() { + let modulus_check = (n.as_ref() - &r) % NonZero::new(&m + &one).unwrap(); + if (!modulus_check.is_zero()).into() { return Err(Error::InvalidArguments); } - let b = Zeroizing::new((n - &*r) / (&*m + &one) + one); + let b = (n.as_ref() - &r) / NonZero::new((&m + &one) + one).unwrap(); - let four = BigUint::from_u8(4).unwrap(); - let four_n = Zeroizing::new(n * four); - let b_squared = Zeroizing::new(b.pow(2u32)); - if *b_squared <= *four_n { + let four = BoxedUint::from(4u32); + let four_n = n.as_ref() * four; + let b_squared = b.square(); + if b_squared <= four_n { return Err(Error::InvalidArguments); } - let b_squared_minus_four_n = Zeroizing::new(&*b_squared - &*four_n); + let b_squared_minus_four_n = b_squared - four_n; // 4. Let ϒ be the positive square root of b^2 – 4n; if ϒ is not an integer, // then output an error indicator, and exit without further processing. - let y = Zeroizing::new(sqrt((*b_squared_minus_four_n).clone())); + let y = b_squared_minus_four_n.sqrt(); - let y_squared = Zeroizing::new(y.pow(2u32)); + let y_squared = y.square(); let sqrt_is_whole_number = y_squared == b_squared_minus_four_n; if !sqrt_is_whole_number { return Err(Error::InvalidArguments); } - let p = (&*b + &*y) / &two; - let q = (&*b - &*y) / two; + + let two = NonZero::new(BoxedUint::from(2u64)).unwrap(); + let p = (&b + &y) / &two; + let q = (b - y) / two; Ok((p, q)) } /// Compute the modulus of a key from its primes. -pub(crate) fn compute_modulus(primes: &[BigUint]) -> BigUint { - primes.iter().product() +pub(crate) fn compute_modulus(primes: &[BoxedUint]) -> Odd { + let mut out = primes[0].clone(); + for p in &primes[1..] { + out = out * p; + } + Odd::new(out).unwrap() } /// Compute the private exponent from its primes (p and q) and public exponent /// This uses Euler's totient function #[inline] pub(crate) fn compute_private_exponent_euler_totient( - primes: &[BigUint], - exp: &BigUint, -) -> Result { + primes: &[BoxedUint], + exp: u64, +) -> Result { if primes.len() < 2 { return Err(Error::InvalidPrime); } - let mut totient = BigUint::one(); + let mut totient = BoxedUint::one(); for prime in primes { - totient *= prime - BigUint::one(); + totient = totient * (prime - &BoxedUint::one()); } + let totient = Odd::new(totient).unwrap(); // 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) = exp.mod_inverse(totient) { - Ok(d.to_biguint().unwrap()) + if let Some(d) = BoxedUint::from(exp).inv_odd_mod(&totient).into() { + Ok(d) } else { // `exp` evenly divides `totient` Err(Error::InvalidPrime) @@ -288,16 +299,17 @@ pub(crate) fn compute_private_exponent_euler_totient( /// make Euler's totiem unreliable. #[inline] pub(crate) fn compute_private_exponent_carmicheal( - p: &BigUint, - q: &BigUint, - exp: &BigUint, -) -> Result { - let p1 = p - BigUint::one(); - let q1 = q - BigUint::one(); - - let lcm = p1.lcm(&q1); - if let Some(d) = exp.mod_inverse(lcm) { - Ok(d.to_biguint().unwrap()) + p: &BoxedUint, + q: &BoxedUint, + exp: u64, +) -> Result { + let p1 = p - &BoxedUint::one(); + let q1 = q - &BoxedUint::one(); + + let lcm = p1; // TODO: p1.lcm(&q1); + let lcm = Odd::new(lcm).unwrap(); + if let Some(d) = BoxedUint::from(exp).inv_odd_mod(&lcm).into() { + Ok(d) } else { // `exp` evenly divides `lcm` Err(Error::InvalidPrime) @@ -306,19 +318,19 @@ pub(crate) fn compute_private_exponent_carmicheal( #[cfg(test)] mod tests { - use num_traits::FromPrimitive; - use super::*; #[test] fn recover_primes_works() { - let n = BigUint::parse_bytes(b"00d397b84d98a4c26138ed1b695a8106ead91d553bf06041b62d3fdc50a041e222b8f4529689c1b82c5e71554f5dd69fa2f4b6158cf0dbeb57811a0fc327e1f28e74fe74d3bc166c1eabdc1b8b57b934ca8be5b00b4f29975bcc99acaf415b59bb28a6782bb41a2c3c2976b3c18dbadef62f00c6bb226640095096c0cc60d22fe7ef987d75c6a81b10d96bf292028af110dc7cc1bbc43d22adab379a0cd5d8078cc780ff5cd6209dea34c922cf784f7717e428d75b5aec8ff30e5f0141510766e2e0ab8d473c84e8710b2b98227c3db095337ad3452f19e2b9bfbccdd8148abf6776fa552775e6e75956e45229ae5a9c46949bab1e622f0e48f56524a84ed3483b", 16).unwrap(); - let e = BigUint::from_u64(65537).unwrap(); - let d = BigUint::parse_bytes(b"00c4e70c689162c94c660828191b52b4d8392115df486a9adbe831e458d73958320dc1b755456e93701e9702d76fb0b92f90e01d1fe248153281fe79aa9763a92fae69d8d7ecd144de29fa135bd14f9573e349e45031e3b76982f583003826c552e89a397c1a06bd2163488630d92e8c2bb643d7abef700da95d685c941489a46f54b5316f62b5d2c3a7f1bbd134cb37353a44683fdc9d95d36458de22f6c44057fe74a0a436c4308f73f4da42f35c47ac16a7138d483afc91e41dc3a1127382e0c0f5119b0221b4fc639d6b9c38177a6de9b526ebd88c38d7982c07f98a0efd877d508aae275b946915c02e2e1106d175d74ec6777f5e80d12c053d9c7be1e341", 16).unwrap(); - let p = BigUint::parse_bytes(b"00f827bbf3a41877c7cc59aebf42ed4b29c32defcb8ed96863d5b090a05a8930dd624a21c9dcf9838568fdfa0df65b8462a5f2ac913d6c56f975532bd8e78fb07bd405ca99a484bcf59f019bbddcb3933f2bce706300b4f7b110120c5df9018159067c35da3061a56c8635a52b54273b31271b4311f0795df6021e6355e1a42e61",16).unwrap(); - let q = BigUint::parse_bytes(b"00da4817ce0089dd36f2ade6a3ff410c73ec34bf1b4f6bda38431bfede11cef1f7f6efa70e5f8063a3b1f6e17296ffb15feefa0912a0325b8d1fd65a559e717b5b961ec345072e0ec5203d03441d29af4d64054a04507410cf1da78e7b6119d909ec66e6ad625bf995b279a4b3c5be7d895cd7c5b9c4c497fde730916fcdb4e41b", 16).unwrap(); + let bits = 512; + + let n = BoxedUint::from_be_hex("00d397b84d98a4c26138ed1b695a8106ead91d553bf06041b62d3fdc50a041e222b8f4529689c1b82c5e71554f5dd69fa2f4b6158cf0dbeb57811a0fc327e1f28e74fe74d3bc166c1eabdc1b8b57b934ca8be5b00b4f29975bcc99acaf415b59bb28a6782bb41a2c3c2976b3c18dbadef62f00c6bb226640095096c0cc60d22fe7ef987d75c6a81b10d96bf292028af110dc7cc1bbc43d22adab379a0cd5d8078cc780ff5cd6209dea34c922cf784f7717e428d75b5aec8ff30e5f0141510766e2e0ab8d473c84e8710b2b98227c3db095337ad3452f19e2b9bfbccdd8148abf6776fa552775e6e75956e45229ae5a9c46949bab1e622f0e48f56524a84ed3483b", bits).unwrap(); + let e = 65537; + let d = BoxedUint::from_be_hex("00c4e70c689162c94c660828191b52b4d8392115df486a9adbe831e458d73958320dc1b755456e93701e9702d76fb0b92f90e01d1fe248153281fe79aa9763a92fae69d8d7ecd144de29fa135bd14f9573e349e45031e3b76982f583003826c552e89a397c1a06bd2163488630d92e8c2bb643d7abef700da95d685c941489a46f54b5316f62b5d2c3a7f1bbd134cb37353a44683fdc9d95d36458de22f6c44057fe74a0a436c4308f73f4da42f35c47ac16a7138d483afc91e41dc3a1127382e0c0f5119b0221b4fc639d6b9c38177a6de9b526ebd88c38d7982c07f98a0efd877d508aae275b946915c02e2e1106d175d74ec6777f5e80d12c053d9c7be1e341", bits).unwrap(); + let p = BoxedUint::from_be_hex("00f827bbf3a41877c7cc59aebf42ed4b29c32defcb8ed96863d5b090a05a8930dd624a21c9dcf9838568fdfa0df65b8462a5f2ac913d6c56f975532bd8e78fb07bd405ca99a484bcf59f019bbddcb3933f2bce706300b4f7b110120c5df9018159067c35da3061a56c8635a52b54273b31271b4311f0795df6021e6355e1a42e61", bits).unwrap(); + let q = BoxedUint::from_be_hex("00da4817ce0089dd36f2ade6a3ff410c73ec34bf1b4f6bda38431bfede11cef1f7f6efa70e5f8063a3b1f6e17296ffb15feefa0912a0325b8d1fd65a559e717b5b961ec345072e0ec5203d03441d29af4d64054a04507410cf1da78e7b6119d909ec66e6ad625bf995b279a4b3c5be7d895cd7c5b9c4c497fde730916fcdb4e41b", bits).unwrap(); - let (mut p1, mut q1) = recover_primes(&n, &e, &d).unwrap(); + let (mut p1, mut q1) = recover_primes(&NonZero::new(n).unwrap(), e, &d).unwrap(); if p1 < q1 { std::mem::swap(&mut p1, &mut q1); diff --git a/src/encoding.rs b/src/encoding.rs index 04faab82..6a86b543 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -4,11 +4,11 @@ //! `pkcs1` crate's traits for types which impl the `pkcs8` crate's traits. use crate::{ - key::to_biguint, traits::{PrivateKeyParts, PublicKeyParts}, - BigUint, RsaPrivateKey, RsaPublicKey, + RsaPrivateKey, RsaPublicKey, }; use core::convert::{TryFrom, TryInto}; +use crypto_bigint::{BoxedUint, NonZero, Odd}; use pkcs8::{der::Encode, Document, EncodePrivateKey, EncodePublicKey, SecretDocument}; use zeroize::Zeroizing; @@ -35,12 +35,13 @@ impl TryFrom> for RsaPrivateKey { if pkcs1_key.version() != pkcs1::Version::TwoPrime { return Err(pkcs1::Error::Version.into()); } - - let n = BigUint::from_bytes_be(pkcs1_key.modulus.as_bytes()); - let e = BigUint::from_bytes_be(pkcs1_key.public_exponent.as_bytes()); - let d = BigUint::from_bytes_be(pkcs1_key.private_exponent.as_bytes()); - let prime1 = BigUint::from_bytes_be(pkcs1_key.prime1.as_bytes()); - let prime2 = BigUint::from_bytes_be(pkcs1_key.prime2.as_bytes()); + let bits = 512; // TODO: read from data + let n = BoxedUint::from_be_slice(pkcs1_key.modulus.as_bytes(), bits).unwrap(); + let n = Odd::new(n).unwrap(); + let e = u64::from_be_bytes(pkcs1_key.public_exponent.as_bytes().try_into().unwrap()); + let d = BoxedUint::from_be_slice(pkcs1_key.private_exponent.as_bytes(), bits).unwrap(); + let prime1 = BoxedUint::from_be_slice(pkcs1_key.prime1.as_bytes(), bits).unwrap(); + let prime2 = BoxedUint::from_be_slice(pkcs1_key.prime2.as_bytes(), bits).unwrap(); let primes = vec![prime1, prime2]; RsaPrivateKey::from_components(n, e, d, primes).map_err(|_| pkcs8::Error::KeyMalformed) } @@ -57,8 +58,10 @@ impl TryFrom> for RsaPublicKey { .as_bytes() .ok_or(pkcs8::spki::Error::KeyMalformed)?, )?; - let n = BigUint::from_bytes_be(pkcs1_key.modulus.as_bytes()); - let e = BigUint::from_bytes_be(pkcs1_key.public_exponent.as_bytes()); + + let bits = 512; // TODO: determine at runtime + let n = BoxedUint::from_be_slice(pkcs1_key.modulus.as_bytes(), bits).unwrap(); + let e = u64::from_be_bytes(pkcs1_key.public_exponent.as_bytes().try_into().unwrap()); RsaPublicKey::new(n, e).map_err(|_| pkcs8::spki::Error::KeyMalformed) } } @@ -70,19 +73,21 @@ impl EncodePrivateKey for RsaPrivateKey { return Err(pkcs1::Error::Version.into()); } - let modulus = self.n().to_bytes_be(); - let public_exponent = self.e().to_bytes_be(); - let private_exponent = Zeroizing::new(self.d().to_bytes_be()); - let prime1 = Zeroizing::new(to_biguint(&self.primes[0]).to_bytes_be()); - let prime2 = Zeroizing::new(to_biguint(&self.primes[1]).to_bytes_be()); - let exponent1 = - Zeroizing::new((self.d() % (&to_biguint(&self.primes[0]) - 1u8)).to_bytes_be()); - let exponent2 = - Zeroizing::new((self.d() % (&to_biguint(&self.primes[1]) - 1u8)).to_bytes_be()); + let modulus = self.n().to_be_bytes(); + let public_exponent = self.e().to_be_bytes(); + 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 exponent1 = Zeroizing::new( + (self.d() % NonZero::new(&self.primes[0] - &BoxedUint::one()).unwrap()).to_be_bytes(), + ); + let exponent2 = Zeroizing::new( + (self.d() % NonZero::new(&self.primes[1] - &BoxedUint::one()).unwrap()).to_be_bytes(), + ); let coefficient = Zeroizing::new( self.crt_coefficient() .ok_or(pkcs1::Error::Crypto)? - .to_bytes_be(), + .to_be_bytes(), ); let private_key = pkcs1::RsaPrivateKey { @@ -104,8 +109,8 @@ impl EncodePrivateKey for RsaPrivateKey { impl EncodePublicKey for RsaPublicKey { fn to_public_key_der(&self) -> pkcs8::spki::Result { - let modulus = self.n().to_bytes_be(); - let public_exponent = self.e().to_bytes_be(); + let modulus = self.n().to_be_bytes(); + let public_exponent = self.e().to_be_bytes(); let subject_public_key = pkcs1::RsaPublicKey { modulus: pkcs1::UintRef::new(&modulus)?, diff --git a/src/key.rs b/src/key.rs index df199cd6..97b4e6bd 100644 --- a/src/key.rs +++ b/src/key.rs @@ -2,10 +2,7 @@ use alloc::vec::Vec; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams}; -use crypto_bigint::{BoxedUint, InvMod, Limb, NonZero, Odd}; -use num_bigint::BigUint; -use num_integer::Integer; -use num_traits::{FromPrimitive, ToPrimitive}; +use crypto_bigint::{BoxedUint, Integer, InvMod, NonZero, Odd}; use rand_core::CryptoRngCore; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -19,8 +16,8 @@ use crate::algorithms::rsa::{ use crate::dummy_rng::DummyRng; use crate::errors::{Error, Result}; -use crate::traits::keys::{CrtValueNew, PrivateKeyPartsNew, PublicKeyPartsNew}; -use crate::traits::{PaddingScheme, PublicKeyParts, SignatureScheme}; +use crate::traits::keys::{CrtValue, PrivateKeyParts, PublicKeyParts}; +use crate::traits::{PaddingScheme, SignatureScheme}; /// Represents the public part of an RSA key. #[derive(Debug, Clone)] @@ -138,9 +135,9 @@ impl From for RsaPublicKey { impl From<&RsaPrivateKey> for RsaPublicKey { fn from(private_key: &RsaPrivateKey) -> Self { - let n = PublicKeyPartsNew::n(private_key); - let e = PublicKeyPartsNew::e(private_key); - let n_params = PublicKeyPartsNew::n_params(private_key); + let n = PublicKeyParts::n(private_key); + let e = PublicKeyParts::e(private_key); + let n_params = PublicKeyParts::n_params(private_key); RsaPublicKey { n: n.clone(), e: e.clone(), @@ -149,7 +146,7 @@ impl From<&RsaPrivateKey> for RsaPublicKey { } } -impl PublicKeyPartsNew for RsaPublicKey { +impl PublicKeyParts for RsaPublicKey { fn n(&self) -> &NonZero { &self.n } @@ -199,19 +196,17 @@ impl RsaPublicKey { /// /// This function accepts public keys with a modulus size up to 4096-bits, /// i.e. [`RsaPublicKey::MAX_SIZE`]. - pub fn new(n: BigUint, e: BigUint) -> Result { + pub fn new(n: BoxedUint, e: u64) -> Result { Self::new_with_max_size(n, e, Self::MAX_SIZE) } /// Create a new public key from its components. - pub fn new_with_max_size(n: BigUint, e: BigUint, max_size: usize) -> Result { - check_public_with_max_size(&n, &e, max_size)?; - let e = e.to_u64().unwrap(); + pub fn new_with_max_size(n: BoxedUint, e: u64, max_size: usize) -> Result { + check_public_with_max_size(&n, e, max_size)?; - let raw_n = to_uint(n); - let n_odd = Odd::new(raw_n.clone()).unwrap(); + let n_odd = Odd::new(n.clone()).unwrap(); let n_params = BoxedMontyParams::new(n_odd); - let n = NonZero::new(raw_n).unwrap(); + let n = NonZero::new(n).unwrap(); let k = Self { n, e, n_params }; @@ -224,43 +219,15 @@ impl RsaPublicKey { /// This method is not recommended, and only intended for unusual use cases. /// Most applications should use [`RsaPublicKey::new`] or /// [`RsaPublicKey::new_with_max_size`] instead. - pub fn new_unchecked(n: BigUint, e: BigUint) -> Self { - let raw_n = to_uint(n); - let n_odd = Odd::new(raw_n.clone()).unwrap(); + pub fn new_unchecked(n: BoxedUint, e: u64) -> Self { + let n_odd = Odd::new(n.clone()).unwrap(); let n_params = BoxedMontyParams::new(n_odd); - let n = NonZero::new(raw_n).unwrap(); - let e = e.to_u64().unwrap(); + let n = NonZero::new(n).unwrap(); Self { n, e, n_params } } } -fn needed_bits(n: &BigUint) -> u32 { - // widen to the max size bits - let n_bits = n.bits(); - - // TODO: better algorithm/more sizes - if n_bits <= 64 { - 64 - } else if n_bits <= 128 { - 128 - } else if n_bits <= 256 { - 256 - } else if n_bits <= 512 { - 512 - } else if n_bits <= 1024 { - 1024 - } else if n_bits <= 2048 { - 2048 - } else if n_bits <= 4096 { - 4096 - } else if n_bits <= 8192 { - 8192 - } else { - 16384 - } -} - -impl PublicKeyPartsNew for RsaPrivateKey { +impl PublicKeyParts for RsaPrivateKey { fn n(&self) -> &NonZero { &self.pubkey_components.n } @@ -279,19 +246,18 @@ impl RsaPrivateKey { const EXP: u64 = 65537; /// Generate a new Rsa key pair of the given bit size using the passed in `rng`. - pub fn new(rng: &mut R, bit_size: usize) -> Result { - let exp = BigUint::from_u64(Self::EXP).expect("invalid static exponent"); - Self::new_with_exp(rng, bit_size, &exp) + pub fn new(rng: &mut R, bit_size: usize) -> Result { + Self::new_with_exp(rng, bit_size, Self::EXP) } /// Generate a new RSA key pair of the given bit size and the public exponent /// using the passed in `rng`. /// /// Unless you have specific needs, you should use `RsaPrivateKey::new` instead. - pub fn new_with_exp( + pub fn new_with_exp( rng: &mut R, bit_size: usize, - exp: &BigUint, + exp: u64, ) -> Result { let components = generate_multi_prime_key_with_exp(rng, 2, bit_size, exp)?; RsaPrivateKey::from_components(components.n, components.e, components.d, components.primes) @@ -311,25 +277,6 @@ impl RsaPrivateKey { /// /// [NIST SP 800-56B Revision 2]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf pub fn from_components( - n: BigUint, - e: BigUint, - d: BigUint, - primes: Vec, - ) -> Result { - let n = to_uint(n.clone()); - let e = e.to_u64().ok_or_else(|| Error::InvalidExponent)?; - let nbits = n.bits_precision(); - let d = to_uint_exact(d, nbits); - let primes = primes - .into_iter() - .map(|p| to_uint_exact(p, nbits)) - .collect(); - - let n_odd = Odd::new(n).unwrap(); - Self::from_components_new(n_odd, e, d, primes) - } - - pub(crate) fn from_components_new( n: Odd, e: u64, d: BoxedUint, @@ -337,7 +284,6 @@ impl RsaPrivateKey { ) -> Result { let n_params = BoxedMontyParams::new(n.clone()); let n_c = NonZero::new(n.as_ref().clone()).unwrap(); - let nbits = n_c.bits_precision(); let mut should_validate = false; @@ -347,13 +293,9 @@ impl RsaPrivateKey { } // Recover `p` and `q` from `d`. // See method in Appendix C.2: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf - let (p, q) = recover_primes( - &to_biguint(&n), - &BigUint::from_u64(e).unwrap(), - &to_biguint(&d), - )?; - primes.push(to_uint_exact(p, nbits)); - primes.push(to_uint_exact(q, nbits)); + let (p, q) = recover_primes(&n_c, e, &d)?; + primes.push(p); + primes.push(q); should_validate = true; } @@ -385,13 +327,13 @@ impl RsaPrivateKey { /// /// Private exponent will be rebuilt using the method defined in /// [NIST 800-56B Section 6.2.1](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf#page=47). - pub fn from_p_q(p: BigUint, q: BigUint, public_exponent: BigUint) -> Result { + pub fn from_p_q(p: BoxedUint, q: BoxedUint, public_exponent: u64) -> Result { if p == q { return Err(Error::InvalidPrime); } let n = compute_modulus(&[p.clone(), q.clone()]); - let d = compute_private_exponent_carmicheal(&p, &q, &public_exponent)?; + let d = compute_private_exponent_carmicheal(&p, &q, public_exponent)?; Self::from_components(n, public_exponent, d, vec![p, q]) } @@ -399,7 +341,7 @@ impl RsaPrivateKey { /// Constructs an RSA key pair from its primes. /// /// This will rebuild the private exponent and the modulus. - pub fn from_primes(primes: Vec, public_exponent: BigUint) -> Result { + pub fn from_primes(primes: Vec, public_exponent: u64) -> Result { if primes.len() < 2 { return Err(Error::NprimesTooSmall); } @@ -414,7 +356,7 @@ impl RsaPrivateKey { } let n = compute_modulus(&primes); - let d = compute_private_exponent_euler_totient(&primes, &public_exponent)?; + let d = compute_private_exponent_euler_totient(&primes, public_exponent)?; Self::from_components(n, public_exponent, d, primes) } @@ -472,11 +414,11 @@ impl RsaPrivateKey { } /// Compute CRT coefficient: `(1/q) mod p`. - pub fn crt_coefficient(&self) -> Option { + pub fn crt_coefficient(&self) -> Option { let p = &self.primes[0]; let q = &self.primes[1]; - Option::from(q.inv_mod(p)).map(|x| to_biguint(&x)) + Option::from(q.inv_mod(p)) } /// Performs basic sanity checks on the key. @@ -559,7 +501,7 @@ impl RsaPrivateKey { } } -impl PrivateKeyPartsNew for RsaPrivateKey { +impl PrivateKeyParts for RsaPrivateKey { fn d(&self) -> &BoxedUint { &self.d } @@ -580,7 +522,7 @@ impl PrivateKeyPartsNew for RsaPrivateKey { self.precomputed.as_ref().map(|p| &p.qinv) } - fn crt_values(&self) -> Option<&[CrtValueNew]> { + fn crt_values(&self) -> Option<&[CrtValue]> { None } @@ -596,71 +538,36 @@ impl PrivateKeyPartsNew for RsaPrivateKey { /// Check that the public key is well formed and has an exponent within acceptable bounds. #[inline] pub fn check_public(public_key: &impl PublicKeyParts) -> Result<()> { - check_public_with_max_size(&public_key.n(), &public_key.e(), RsaPublicKey::MAX_SIZE) + check_public_with_max_size(&public_key.n(), public_key.e(), RsaPublicKey::MAX_SIZE) } /// Check that the public key is well formed and has an exponent within acceptable bounds. #[inline] -fn check_public_with_max_size(n: &BigUint, e: &BigUint, max_size: usize) -> Result<()> { - if n.bits() > max_size { +fn check_public_with_max_size(n: &BoxedUint, e: u64, max_size: usize) -> Result<()> { + if n.bits_precision() as usize > max_size { return Err(Error::ModulusTooLarge); } - let eu64 = e.to_u64().ok_or(Error::PublicExponentTooLarge)?; - - if e >= n || n.is_even() { + let eb = BoxedUint::from(e); // TODO: avoid + if &eb >= n || n.is_even().into() { return Err(Error::InvalidModulus); } - if e.is_even() { + if eb.is_even().into() { return Err(Error::InvalidExponent); } - if eu64 < RsaPublicKey::MIN_PUB_EXPONENT { + if e < RsaPublicKey::MIN_PUB_EXPONENT { return Err(Error::PublicExponentTooSmall); } - if eu64 > RsaPublicKey::MAX_PUB_EXPONENT { + if e > RsaPublicKey::MAX_PUB_EXPONENT { return Err(Error::PublicExponentTooLarge); } Ok(()) } -pub(crate) fn to_biguint(uint: &BoxedUint) -> BigUint { - BigUint::from_bytes_be(&uint.to_be_bytes()) -} - -pub(crate) fn to_uint_exact(big_uint: BigUint, nbits: u32) -> BoxedUint { - let res = inner_to_uint(big_uint); - - match res.bits_precision().cmp(&nbits) { - Ordering::Equal => res, - Ordering::Greater => panic!("too large: {} > {}", res.bits_precision(), nbits), - Ordering::Less => res.widen(nbits), - } -} - -fn inner_to_uint(big_uint: BigUint) -> BoxedUint { - let bytes = big_uint.to_bytes_be(); - let rem = bytes.len() % Limb::BYTES; - let pad_count = if rem == 0 { 0 } else { Limb::BYTES - rem }; - - let mut padded_bytes = vec![0u8; pad_count]; - padded_bytes.extend_from_slice(&bytes); - - BoxedUint::from_be_slice(&padded_bytes, padded_bytes.len() as u32 * 8).unwrap() -} - -pub(crate) fn to_uint(big_uint: BigUint) -> BoxedUint { - let nbits = needed_bits(&big_uint); - let res = inner_to_uint(big_uint); - if (res.bits_precision() as u32) < nbits { - return res.widen(nbits); - } - res -} - pub(crate) fn reduce(n: &BoxedUint, p: BoxedMontyParams) -> BoxedMontyForm { let bits_precision = p.modulus().bits_precision(); let modulus = NonZero::new(p.modulus().as_ref().clone()).unwrap(); @@ -682,7 +589,6 @@ mod tests { use crate::traits::{PrivateKeyParts, PublicKeyParts}; use hex_literal::hex; - use num_traits::{FromPrimitive, ToPrimitive}; use pkcs8::DecodePrivateKey; use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; @@ -702,15 +608,16 @@ mod tests { }; let public_key: RsaPublicKey = private_key.into(); - assert_eq!(PublicKeyParts::n(&public_key).to_u64(), Some(101)); - assert_eq!(PublicKeyParts::e(&public_key).to_u64(), Some(200)); + let n_limbs: &[u64] = PublicKeyParts::n(&public_key).as_ref().as_ref(); + assert_eq!(n_limbs, &[101u64]); + assert_eq!(PublicKeyParts::e(&public_key), 200); } fn test_key_basics(private_key: &RsaPrivateKey) { private_key.validate().expect("invalid private key"); assert!( - PrivateKeyParts::d(private_key) < PublicKeyParts::n(private_key), + PrivateKeyParts::d(private_key) < PublicKeyParts::n(private_key).as_ref(), "private exponent too large" ); @@ -732,11 +639,11 @@ mod tests { #[test] fn $name() { let mut rng = ChaCha8Rng::from_seed([42; 32]); - let exp = BigUint::from_u64(RsaPrivateKey::EXP).expect("invalid static exponent"); + let exp = RsaPrivateKey::EXP; for _ in 0..10 { let components = - generate_multi_prime_key_with_exp(&mut rng, $multi, $size, &exp).unwrap(); + generate_multi_prime_key_with_exp(&mut rng, $multi, $size, exp).unwrap(); let private_key = RsaPrivateKey::from_components( components.n, components.e, @@ -765,17 +672,29 @@ mod tests { #[test] fn test_negative_decryption_value() { + let bits = 128; let private_key = RsaPrivateKey::from_components( - BigUint::from_bytes_le(&[ - 99, 192, 208, 179, 0, 220, 7, 29, 49, 151, 75, 107, 75, 73, 200, 180, - ]), - BigUint::from_bytes_le(&[1, 0, 1]), - BigUint::from_bytes_le(&[ - 81, 163, 254, 144, 171, 159, 144, 42, 244, 133, 51, 249, 28, 12, 63, 65, - ]), + Odd::new( + BoxedUint::from_le_slice( + &[ + 99, 192, 208, 179, 0, 220, 7, 29, 49, 151, 75, 107, 75, 73, 200, 180, + ], + bits, + ) + .unwrap(), + ) + .unwrap(), + u64::from_le_bytes([1, 0, 1, 0, 0, 0, 0, 0]), + BoxedUint::from_le_slice( + &[ + 81, 163, 254, 144, 171, 159, 144, 42, 244, 133, 51, 249, 28, 12, 63, 65, + ], + bits, + ) + .unwrap(), vec![ - BigUint::from_bytes_le(&[105, 101, 60, 173, 19, 153, 3, 192]), - BigUint::from_bytes_le(&[235, 65, 160, 134, 32, 136, 6, 241]), + BoxedUint::from_le_slice(&[105, 101, 60, 173, 19, 153, 3, 192], bits).unwrap(), + BoxedUint::from_le_slice(&[235, 65, 160, 134, 32, 136, 6, 241], bits).unwrap(), ], ) .unwrap(); @@ -866,11 +785,19 @@ mod tests { Base64::decode_vec("CUWC+hRWOT421kwRllgVjy6FYv6jQUcgDNHeAiYZnf5HjS9iK2ki7v8G5dL/0f+Yf+NhE/4q8w4m8go51hACrVpP1p8GJDjiT09+RsOzITsHwl+ceEKoe56ZW6iDHBLlrNw5/MtcYhKpjNU9KJ2udm5J/c9iislcjgckrZG2IB8ADgXHMEByZ5DgaMl4AKZ1Gx8/q6KftTvmOT5rNTMLi76VN5KWQcDWK/DqXiOiZHM7Nr4dX4me3XeRgABJyNR8Fqxj3N1+HrYLe/zs7LOaK0++F9Ul3tLelhrhsvLxei3oCZkF9A/foD3on3luYA+1cRcxWpSY3h2J4/22+yo4+Q==").unwrap(), ]; + let mut e_raw = [0u8; 8]; + e_raw[..e.len()].copy_from_slice(&e); + let e = u64::from_be_bytes(e_raw); + + let bits = 512; RsaPrivateKey::from_components( - BigUint::from_bytes_be(&n), - BigUint::from_bytes_be(&e), - BigUint::from_bytes_be(&d), - primes.iter().map(|p| BigUint::from_bytes_be(p)).collect(), + Odd::new(BoxedUint::from_be_slice(&n, bits).unwrap()).unwrap(), + e, + BoxedUint::from_be_slice(&d, bits).unwrap(), + primes + .iter() + .map(|p| BoxedUint::from_be_slice(p, bits).unwrap()) + .collect(), ) .unwrap(); } @@ -903,8 +830,9 @@ mod tests { // mQIDAQAB // -----END PUBLIC KEY----- - let n = BigUint::from_bytes_be(&hex!( - " + let n = BoxedUint::from_be_slice( + &hex!( + " 90c06207caac3555c0b0947a5e8b681f5af6aed665ff1cd42b6b487f2f7d68f1 38f3dbbee6d2f10908507fe6bcf75e7cbd20e9af6ff1c202bcc3dbb45e9bb69b b5d12a354c4b463a50820d16879373ceeb5574fdd9272be3b90d55c1a64855de @@ -937,9 +865,12 @@ mod tests { 68b98f141f5537be7a590cb3ba15b0bb15824652e8da8f70eb847240058a336a 1b6db7f88268aaf89f0b33b905d72c25338b13e61a51873c2d427021a3f29207 179ad32f423793f0c090dda025ce41df0e94afbc80ab5eda9b1a268aa2553a99" - )); + ), + 4096, + ) + .unwrap(); - let e = BigUint::from_u64(65537).unwrap(); + let e = 65537; assert_eq!( RsaPublicKey::new(n, e).err().unwrap(), diff --git a/src/lib.rs b/src/lib.rs index 2232f37a..f15480d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -222,7 +222,6 @@ extern crate alloc; #[cfg(feature = "std")] extern crate std; -pub use num_bigint::BigUint; pub use rand_core; pub use signature; diff --git a/src/oaep.rs b/src/oaep.rs index 20749a95..fba7a66e 100644 --- a/src/oaep.rs +++ b/src/oaep.rs @@ -195,7 +195,7 @@ fn encrypt( let int = BoxedUint::from_be_slice( &em, - crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), + crate::traits::keys::PublicKeyParts::n_bits_precision(pub_key), )?; uint_to_be_pad(rsa_encrypt(pub_key, &int)?, pub_key.size()) } @@ -219,7 +219,7 @@ fn encrypt_digest( let ciphertext = BoxedUint::from_be_slice( ciphertext, - crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), + crate::traits::keys::PublicKeyParts::n_bits_precision(priv_key), )?; let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?; @@ -289,7 +289,7 @@ fn decrypt_digest( let em = pkcs1v15_encrypt_pad(rng, msg, pub_key.size())?; let int = BoxedUint::from_be_slice( &em, - crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key), + crate::traits::keys::PublicKeyParts::n_bits_precision(pub_key), )?; uint_to_be_pad(rsa_encrypt(pub_key, &int)?, pub_key.size()) } @@ -170,7 +170,7 @@ fn decrypt( let ciphertext = BoxedUint::from_be_slice( ciphertext, - crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), + crate::traits::keys::PublicKeyParts::n_bits_precision(priv_key), )?; let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?; let em = uint_to_zeroizing_be_pad(em, priv_key.size())?; @@ -202,7 +202,7 @@ fn sign( let em = BoxedUint::from_be_slice( &em, - crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), + crate::traits::keys::PublicKeyParts::n_bits_precision(priv_key), )?; uint_to_zeroizing_be_pad(rsa_decrypt_and_check(priv_key, rng, &em)?, priv_key.size()) } @@ -216,7 +216,7 @@ fn verify( sig: &BoxedUint, sig_len: usize, ) -> Result<()> { - let n = crate::traits::keys::PublicKeyPartsNew::n(pub_key); + let n = crate::traits::keys::PublicKeyParts::n(pub_key); if sig >= n.as_ref() || sig_len != pub_key.size() { return Err(Error::Verification); } @@ -277,10 +277,8 @@ mod tests { SignatureEncoding, Signer, Verifier, }; use base64ct::{Base64, Encoding}; + use crypto_bigint::Odd; use hex_literal::hex; - use num_bigint::BigUint; - use num_traits::FromPrimitive; - use num_traits::Num; use rand_chacha::{ rand_core::{RngCore, SeedableRng}, ChaCha8Rng, @@ -306,13 +304,14 @@ mod tests { // tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V // -----END RSA PRIVATE KEY----- + let bits = 512; RsaPrivateKey::from_components( - BigUint::from_str_radix("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077", 10).unwrap(), - BigUint::from_u64(65537).unwrap(), - BigUint::from_str_radix("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861", 10).unwrap(), + Odd::new(BoxedUint::from_be_hex("B2990F49C47DFA8CD400AE6A4D1B8A3B6A13642B23F28B003BFB97790ADE9A4CC82B8B2A81747DDEC08B6296E53A08C331687EF25C4BF4936BA1C0E6041E9D15", bits).unwrap()).unwrap(), + 65537, + BoxedUint::from_be_hex("8ABD6A69F4D1A4B487F0AB8D7AAEFD38609405C999984E30F567E1E8AEEFF44E8B18BDB1EC78DFA31A55E32A48D7FB131F5AF1F44D7D6B2CED2A9DF5E5AE4535", bits).unwrap(), vec![ - BigUint::from_str_radix("98920366548084643601728869055592650835572950932266967461790948584315647051443",10).unwrap(), - BigUint::from_str_radix("94560208308847015747498523884063394671606671904944666360068158221458669711639", 10).unwrap() + BoxedUint::from_be_hex("DAB2F18048BAA68DE7DF04D2D35D5D80E60E2DFA42D50A9B04219032715E46B3", bits).unwrap(), + BoxedUint::from_be_hex("D10F2E66B1D0C13F10EF9927BF5324A379CA218146CBF9CAFC795221F16A3117", bits).unwrap() ], ).unwrap() } diff --git a/src/pkcs1v15/signing_key.rs b/src/pkcs1v15/signing_key.rs index 24754589..da3bd6b8 100644 --- a/src/pkcs1v15/signing_key.rs +++ b/src/pkcs1v15/signing_key.rs @@ -43,7 +43,7 @@ where } /// Generate a new signing key with a prefix for the digest `D`. - pub fn random(rng: &mut R, bit_size: usize) -> Result { + pub fn random(rng: &mut R, bit_size: usize) -> Result { Ok(Self { inner: RsaPrivateKey::new(rng, bit_size)?, prefix: pkcs1v15_generate_prefix::(), @@ -59,10 +59,7 @@ where /// Generate a new signing key with a prefix for the digest `D`. #[deprecated(since = "0.9.0", note = "use SigningKey::random instead")] - pub fn random_with_prefix( - rng: &mut R, - bit_size: usize, - ) -> Result { + pub fn random_with_prefix(rng: &mut R, bit_size: usize) -> Result { Self::random(rng, bit_size) } } @@ -85,10 +82,7 @@ where } /// Generate a new signing key with an empty prefix. - pub fn random_unprefixed( - rng: &mut R, - bit_size: usize, - ) -> Result { + pub fn random_unprefixed(rng: &mut R, bit_size: usize) -> Result { Ok(Self { inner: RsaPrivateKey::new(rng, bit_size)?, prefix: Vec::new(), diff --git a/src/pss.rs b/src/pss.rs index 1848fcfb..021bf8d9 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -137,7 +137,7 @@ pub(crate) fn verify( let mut em = uint_to_be_pad(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; - emsa_pss_verify(hashed, &mut em, salt_len, digest, pub_key.n().bits()) + emsa_pss_verify(hashed, &mut em, salt_len, digest, pub_key.n().bits() as _) } pub(crate) fn verify_digest( @@ -150,14 +150,14 @@ pub(crate) fn verify_digest( where D: Digest + FixedOutputReset, { - let n = crate::traits::keys::PublicKeyPartsNew::n(pub_key); + let n = crate::traits::keys::PublicKeyParts::n(pub_key); if sig >= n.as_ref() || sig_len != pub_key.size() { return Err(Error::Verification); } let mut em = uint_to_be_pad(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; - emsa_pss_verify_digest::(hashed, &mut em, salt_len, pub_key.n().bits()) + emsa_pss_verify_digest::(hashed, &mut em, salt_len, pub_key.n().bits() as _) } /// SignPSS calculates the signature of hashed using RSASSA-PSS. @@ -205,11 +205,11 @@ fn sign_pss_with_salt( digest: &mut dyn DynDigest, ) -> Result> { let em_bits = priv_key.n().bits() - 1; - let em = emsa_pss_encode(hashed, em_bits, salt, digest)?; + let em = emsa_pss_encode(hashed, em_bits as _, salt, digest)?; let em = BoxedUint::from_be_slice( &em, - crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), + crate::traits::keys::PublicKeyParts::n_bits_precision(priv_key), )?; uint_to_zeroizing_be_pad( rsa_decrypt_and_check(priv_key, blind_rng, &em)?, @@ -224,11 +224,11 @@ fn sign_pss_with_salt_digest Result> { let em_bits = priv_key.n().bits() - 1; - let em = emsa_pss_encode_digest::(hashed, em_bits, salt)?; + let em = emsa_pss_encode_digest::(hashed, em_bits as _, salt)?; let em = BoxedUint::from_be_slice( &em, - crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key), + crate::traits::keys::PublicKeyParts::n_bits_precision(priv_key), )?; uint_to_zeroizing_be_pad( rsa_decrypt_and_check(priv_key, blind_rng, &em)?, @@ -264,9 +264,8 @@ mod test { use crate::pss::{BlindedSigningKey, Pss, Signature, SigningKey, VerifyingKey}; use crate::{RsaPrivateKey, RsaPublicKey}; + use crypto_bigint::{BoxedUint, Odd}; use hex_literal::hex; - use num_bigint::BigUint; - use num_traits::{FromPrimitive, Num}; use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; use sha1::{Digest, Sha1}; use signature::hazmat::{PrehashVerifier, RandomizedPrehashSigner}; @@ -284,13 +283,14 @@ mod test { // tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V // -----END RSA PRIVATE KEY----- + let bits = 512; RsaPrivateKey::from_components( - BigUint::from_str_radix("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077", 10).unwrap(), - BigUint::from_u64(65537).unwrap(), - BigUint::from_str_radix("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861", 10).unwrap(), + Odd::new(BoxedUint::from_be_hex("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077", bits).unwrap()).unwrap(), + 65537, + BoxedUint::from_be_hex("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861", bits).unwrap(), vec![ - BigUint::from_str_radix("98920366548084643601728869055592650835572950932266967461790948584315647051443",10).unwrap(), - BigUint::from_str_radix("94560208308847015747498523884063394671606671904944666360068158221458669711639", 10).unwrap() + BoxedUint::from_be_hex("98920366548084643601728869055592650835572950932266967461790948584315647051443",bits).unwrap(), + BoxedUint::from_be_hex("94560208308847015747498523884063394671606671904944666360068158221458669711639", bits).unwrap() ], ).unwrap() } diff --git a/src/pss/blinded_signing_key.rs b/src/pss/blinded_signing_key.rs index adc0ff5f..c40e4bdc 100644 --- a/src/pss/blinded_signing_key.rs +++ b/src/pss/blinded_signing_key.rs @@ -52,13 +52,13 @@ where /// Create a new random RSASSA-PSS signing key which produces "blinded" /// signatures. /// Digest output size is used as a salt length. - pub fn random(rng: &mut R, bit_size: usize) -> Result { + pub fn random(rng: &mut R, bit_size: usize) -> Result { Self::random_with_salt_len(rng, bit_size, ::output_size()) } /// Create a new random RSASSA-PSS signing key which produces "blinded" /// signatures with a salt of the given length. - pub fn random_with_salt_len( + pub fn random_with_salt_len( rng: &mut R, bit_size: usize, salt_len: usize, diff --git a/src/pss/signing_key.rs b/src/pss/signing_key.rs index 39b41472..b6811f0b 100644 --- a/src/pss/signing_key.rs +++ b/src/pss/signing_key.rs @@ -57,12 +57,12 @@ where /// Generate a new random RSASSA-PSS signing key. /// Digest output size is used as a salt length. - pub fn random(rng: &mut R, bit_size: usize) -> Result { + pub fn random(rng: &mut R, bit_size: usize) -> Result { Self::random_with_salt_len(rng, bit_size, ::output_size()) } /// Generate a new random RSASSA-PSS signing key with a salt of the given length. - pub fn random_with_salt_len( + pub fn random_with_salt_len( rng: &mut R, bit_size: usize, salt_len: usize, diff --git a/src/traits/keys.rs b/src/traits/keys.rs index 94d2bb3a..2525117a 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -1,116 +1,34 @@ //! Traits related to the key components -use alloc::vec::Vec; - use crypto_bigint::{ modular::{BoxedMontyForm, BoxedMontyParams}, BoxedUint, NonZero, }; -use num_bigint::{BigInt, BigUint, IntoBigInt}; -use num_traits::FromPrimitive; use zeroize::Zeroize; -use crate::key::to_biguint; - /// Components of an RSA public key. pub trait PublicKeyParts { - /// Returns the modulus of the key. - fn n(&self) -> BigUint; - - /// Returns the public exponent of the key. - fn e(&self) -> BigUint; - - /// Returns the modulus size in bytes. Raw signatures and ciphertexts for - /// or by this public key will have the same size. - fn size(&self) -> usize { - (self.n().bits() + 7) / 8 - } -} - -pub trait PublicKeyPartsNew { /// Returns the modulus of the key. fn n(&self) -> &NonZero; /// Returns the public exponent of the key. fn e(&self) -> u64; - fn n_params(&self) -> BoxedMontyParams; - - fn n_bits_precision(&self) -> u32 { - self.n().bits_precision() - } - /// Returns the modulus size in bytes. Raw signatures and ciphertexts for /// or by this public key will have the same size. fn size(&self) -> usize { (self.n().bits() as usize + 7) / 8 } -} -impl PublicKeyParts for T { - fn n(&self) -> BigUint { - to_biguint(&PublicKeyPartsNew::n(self).clone().get()) - } - - fn e(&self) -> BigUint { - BigUint::from_u64(PublicKeyPartsNew::e(self)).unwrap() - } + fn n_params(&self) -> BoxedMontyParams; - fn size(&self) -> usize { - PublicKeyPartsNew::size(self) + fn n_bits_precision(&self) -> u32 { + self.n().bits_precision() } } /// Components of an RSA private key. pub trait PrivateKeyParts: PublicKeyParts { - /// Returns the private exponent of the key. - fn d(&self) -> BigUint; - - /// Returns the prime factors. - fn primes(&self) -> Vec; - - /// Returns the precomputed dp value, D mod (P-1) - fn dp(&self) -> Option; - - /// Returns the precomputed dq value, D mod (Q-1) - fn dq(&self) -> Option; - - /// Returns the precomputed qinv value, Q^-1 mod P - fn qinv(&self) -> Option; - - /// Returns an iterator over the CRT Values - fn crt_values(&self) -> Option>; -} - -/// Components of an RSA private key. -impl PrivateKeyParts for T { - fn d(&self) -> BigUint { - to_biguint(PrivateKeyPartsNew::d(self)) - } - fn primes(&self) -> Vec { - PrivateKeyPartsNew::primes(self) - .iter() - .map(to_biguint) - .collect() - } - fn dp(&self) -> Option { - PrivateKeyPartsNew::dp(self).map(to_biguint) - } - - fn dq(&self) -> Option { - PrivateKeyPartsNew::dq(self).map(to_biguint) - } - fn qinv(&self) -> Option { - PrivateKeyPartsNew::qinv(self).and_then(|v| to_biguint(&v.retrieve()).into_bigint()) - } - - fn crt_values(&self) -> Option> { - None - } -} - -/// Components of an RSA private key. -pub trait PrivateKeyPartsNew: PublicKeyPartsNew { /// Returns the private exponent of the key. fn d(&self) -> &BoxedUint; @@ -127,16 +45,15 @@ pub trait PrivateKeyPartsNew: PublicKeyPartsNew { fn qinv(&self) -> Option<&BoxedMontyForm>; /// Returns an iterator over the CRT Values - fn crt_values(&self) -> Option<&[CrtValueNew]>; + fn crt_values(&self) -> Option<&[CrtValue]>; fn p_params(&self) -> Option<&BoxedMontyParams>; - fn q_params(&self) -> Option<&BoxedMontyParams>; } /// Contains the precomputed Chinese remainder theorem values. #[derive(Debug, Clone)] -pub struct CrtValueNew { +pub struct CrtValue { /// D mod (prime - 1) pub(crate) exp: BoxedUint, /// R·Coeff ≡ 1 mod Prime. @@ -145,17 +62,6 @@ pub struct CrtValueNew { pub(crate) r: BoxedUint, } -/// Contains the precomputed Chinese remainder theorem values. -#[derive(Debug, Clone)] -pub struct CrtValue { - /// D mod (prime - 1) - pub(crate) exp: BigInt, - /// R·Coeff ≡ 1 mod Prime. - pub(crate) coeff: BigInt, - /// product of primes prior to this (inc p and q) - pub(crate) r: BigInt, -} - impl Zeroize for CrtValue { fn zeroize(&mut self) { self.exp.zeroize(); @@ -169,17 +75,3 @@ impl Drop for CrtValue { self.zeroize(); } } - -impl Zeroize for CrtValueNew { - fn zeroize(&mut self) { - self.exp.zeroize(); - self.coeff.zeroize(); - self.r.zeroize(); - } -} - -impl Drop for CrtValueNew { - fn drop(&mut self) { - self.zeroize(); - } -} diff --git a/tests/pkcs1.rs b/tests/pkcs1.rs index eff97f6d..c7db566a 100644 --- a/tests/pkcs1.rs +++ b/tests/pkcs1.rs @@ -50,11 +50,11 @@ fn decode_rsa2048_priv_der() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa2048-priv.pem - assert_eq!(&key.n().to_bytes_be(), &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); - assert_eq!(&key.d().to_bytes_be(), &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); - assert_eq!(&key.primes()[0].to_bytes_be(), &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); - assert_eq!(&key.primes()[1].to_bytes_be(), &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); + assert_eq!(&key.d().to_be_bytes()[..], &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); + assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); + assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); } #[test] @@ -63,11 +63,11 @@ fn decode_rsa4096_priv_der() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa4096-priv.pem - assert_eq!(&key.n().to_bytes_be(), &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); - assert_eq!(&key.d().to_bytes_be(), &hex!("9FE3097B2322B90FAB6606C017A095EBE640C39C100BCEE02F238FA14DAFF38E9E57568F1127ED4436126B904631B127EC395BB3EE127EB82C88D2562A7FB55FED8D1450B7E4E2D2F37F5742636FCC6F289963522D5B5706082CADFA01C0EE99B4D0E9274D3A992E06974CBE01694686356962AC1959FD9BD447E5B9968C0543DF1BF134742AF345CDB2FA1F9371B0D4CF61C68D16D653D8E999D4FD3A16CF978A35AA40E860CDCE09655DD8B4CF19D4141B1E92AD5E51A8E4A5C27FA745611D90E49D0E9282222AB6F126643E1C77578816FCE3B98F321D2549F294A470DF8453446BF36F985DF25ED8FDE9FDF3073FB27727DF48E9E1FC7056BC78965090B7850126406462C8253051EF84E34EE3C3CEB8F96C658C38BE45558D2F64E29D223350555FC1EFA28EC1F4AFB5BA4080F09A86CDC3538C1AD7C972E6D7A3612E6845BA9AFBDF19F09060D1A779DE9635E2D2F8E0C510BA24C6C44B30C9BDFAF85BE917AEC5D43AFAB1AA3ADD33CC83DA93CAC69218F6A36EB47F199D5424C95FD9ED7B1E8BE2AEAA6433B227241316C20EE792650CEB48BFD634446B19D286B4EA1722498DA1A36973210EC3824751A5808D9AAEF59C449E19A5077CFECA126BD9A8DD4996561D4E27B3609FF82C5B1B21E627845D44961B33B875D5C4FA9FF357EF6BE3364969E1337C91B29A07B9A913CDE40CE2D5530C900E73751685E65431")); - assert_eq!(&key.primes()[0].to_bytes_be(), &hex!("D0213A79425B665B719118448893EC3275600F63DBF85B77F4E8E99EF302F6E82596048F6DCA772DE6BBF1124DB84B0AFE61B03A8604AB0079ED53F3304797AD01B38C44FE27A5A45E378483A804B56A4A967F48F01A866E721E67E4C9A1048AF68927FAA43D6A85D93E7BF7074DBA797563FCABE12309B76653C6DB614DC231CC556D9F25AC4841A02D31CDF3015B212307F9D0C79FEB5D3956CE53CC8FA1651BE60761F19F74672489EAF9F215409F39956E77A82183F1F72BB2FEDDF1B9FBFC4AD89EA445809DDBD5BD595277990C0BE9366FBB2ECF7B057CC1C3DC8FB77BF8456D07BBC95B3C1815F48E62B81468C3D4D9D96C0F48DAB04993BE8D91EDE5")); - assert_eq!(&key.primes()[1].to_bytes_be(), &hex!("CE36C6810522ABE5D6465F36EB137DA3B9EA4A5F1D27C6614729EB8E5E2E5CB88E3EF1A473A21944B66557B3DC2CE462E4BF3446CB4990037E5672B1705CBAE81B65BAF967A266DC18EFE80F4DBBFE1A59063205CE2943CADF421CCE74AF7063FD1A83AF3C39AF84525F59BDC1FF54815F52AFD1E8D4862B2C3654F6CFA83DC08E2A9D52B9F833C646AF7694467DFC5F7D7AD7B441895FCB7FFBED526324B0154A15823F5107C89548EDDCB61DA5308C6CC834D4A0C16DFA6CA1D67B61A65677EB1719CD125D0EF0DB8802FB76CFC17577BCB2510AE294E1BF8A9173A2B85C16A6B508C98F2D770B7F3DE48D9E720C53E263680B57E7109410015745570652FD")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); + assert_eq!(&key.d().to_be_bytes()[..], &hex!("9FE3097B2322B90FAB6606C017A095EBE640C39C100BCEE02F238FA14DAFF38E9E57568F1127ED4436126B904631B127EC395BB3EE127EB82C88D2562A7FB55FED8D1450B7E4E2D2F37F5742636FCC6F289963522D5B5706082CADFA01C0EE99B4D0E9274D3A992E06974CBE01694686356962AC1959FD9BD447E5B9968C0543DF1BF134742AF345CDB2FA1F9371B0D4CF61C68D16D653D8E999D4FD3A16CF978A35AA40E860CDCE09655DD8B4CF19D4141B1E92AD5E51A8E4A5C27FA745611D90E49D0E9282222AB6F126643E1C77578816FCE3B98F321D2549F294A470DF8453446BF36F985DF25ED8FDE9FDF3073FB27727DF48E9E1FC7056BC78965090B7850126406462C8253051EF84E34EE3C3CEB8F96C658C38BE45558D2F64E29D223350555FC1EFA28EC1F4AFB5BA4080F09A86CDC3538C1AD7C972E6D7A3612E6845BA9AFBDF19F09060D1A779DE9635E2D2F8E0C510BA24C6C44B30C9BDFAF85BE917AEC5D43AFAB1AA3ADD33CC83DA93CAC69218F6A36EB47F199D5424C95FD9ED7B1E8BE2AEAA6433B227241316C20EE792650CEB48BFD634446B19D286B4EA1722498DA1A36973210EC3824751A5808D9AAEF59C449E19A5077CFECA126BD9A8DD4996561D4E27B3609FF82C5B1B21E627845D44961B33B875D5C4FA9FF357EF6BE3364969E1337C91B29A07B9A913CDE40CE2D5530C900E73751685E65431")); + assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("D0213A79425B665B719118448893EC3275600F63DBF85B77F4E8E99EF302F6E82596048F6DCA772DE6BBF1124DB84B0AFE61B03A8604AB0079ED53F3304797AD01B38C44FE27A5A45E378483A804B56A4A967F48F01A866E721E67E4C9A1048AF68927FAA43D6A85D93E7BF7074DBA797563FCABE12309B76653C6DB614DC231CC556D9F25AC4841A02D31CDF3015B212307F9D0C79FEB5D3956CE53CC8FA1651BE60761F19F74672489EAF9F215409F39956E77A82183F1F72BB2FEDDF1B9FBFC4AD89EA445809DDBD5BD595277990C0BE9366FBB2ECF7B057CC1C3DC8FB77BF8456D07BBC95B3C1815F48E62B81468C3D4D9D96C0F48DAB04993BE8D91EDE5")); + assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("CE36C6810522ABE5D6465F36EB137DA3B9EA4A5F1D27C6614729EB8E5E2E5CB88E3EF1A473A21944B66557B3DC2CE462E4BF3446CB4990037E5672B1705CBAE81B65BAF967A266DC18EFE80F4DBBFE1A59063205CE2943CADF421CCE74AF7063FD1A83AF3C39AF84525F59BDC1FF54815F52AFD1E8D4862B2C3654F6CFA83DC08E2A9D52B9F833C646AF7694467DFC5F7D7AD7B441895FCB7FFBED526324B0154A15823F5107C89548EDDCB61DA5308C6CC834D4A0C16DFA6CA1D67B61A65677EB1719CD125D0EF0DB8802FB76CFC17577BCB2510AE294E1BF8A9173A2B85C16A6B508C98F2D770B7F3DE48D9E720C53E263680B57E7109410015745570652FD")); } #[test] @@ -76,8 +76,8 @@ fn decode_rsa2048_pub_der() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa2048-pub.pem - assert_eq!(&key.n().to_bytes_be(), &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); } #[test] @@ -86,8 +86,8 @@ fn decode_rsa4096_pub_der() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa4096-pub.pem - assert_eq!(&key.n().to_bytes_be(), &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); } #[test] @@ -125,11 +125,11 @@ fn decode_rsa2048_priv_pem() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa2048-priv.pem - assert_eq!(&key.n().to_bytes_be(), &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); - assert_eq!(&key.d().to_bytes_be(), &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); - assert_eq!(&key.primes()[0].to_bytes_be(), &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); - assert_eq!(&key.primes()[1].to_bytes_be(), &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); + assert_eq!(&key.d().to_be_bytes()[..], &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); + assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); + assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); } #[test] @@ -139,11 +139,11 @@ fn decode_rsa4096_priv_pem() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa4096-priv.pem - assert_eq!(&key.n().to_bytes_be(), &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); - assert_eq!(&key.d().to_bytes_be(), &hex!("9FE3097B2322B90FAB6606C017A095EBE640C39C100BCEE02F238FA14DAFF38E9E57568F1127ED4436126B904631B127EC395BB3EE127EB82C88D2562A7FB55FED8D1450B7E4E2D2F37F5742636FCC6F289963522D5B5706082CADFA01C0EE99B4D0E9274D3A992E06974CBE01694686356962AC1959FD9BD447E5B9968C0543DF1BF134742AF345CDB2FA1F9371B0D4CF61C68D16D653D8E999D4FD3A16CF978A35AA40E860CDCE09655DD8B4CF19D4141B1E92AD5E51A8E4A5C27FA745611D90E49D0E9282222AB6F126643E1C77578816FCE3B98F321D2549F294A470DF8453446BF36F985DF25ED8FDE9FDF3073FB27727DF48E9E1FC7056BC78965090B7850126406462C8253051EF84E34EE3C3CEB8F96C658C38BE45558D2F64E29D223350555FC1EFA28EC1F4AFB5BA4080F09A86CDC3538C1AD7C972E6D7A3612E6845BA9AFBDF19F09060D1A779DE9635E2D2F8E0C510BA24C6C44B30C9BDFAF85BE917AEC5D43AFAB1AA3ADD33CC83DA93CAC69218F6A36EB47F199D5424C95FD9ED7B1E8BE2AEAA6433B227241316C20EE792650CEB48BFD634446B19D286B4EA1722498DA1A36973210EC3824751A5808D9AAEF59C449E19A5077CFECA126BD9A8DD4996561D4E27B3609FF82C5B1B21E627845D44961B33B875D5C4FA9FF357EF6BE3364969E1337C91B29A07B9A913CDE40CE2D5530C900E73751685E65431")); - assert_eq!(&key.primes()[0].to_bytes_be(), &hex!("D0213A79425B665B719118448893EC3275600F63DBF85B77F4E8E99EF302F6E82596048F6DCA772DE6BBF1124DB84B0AFE61B03A8604AB0079ED53F3304797AD01B38C44FE27A5A45E378483A804B56A4A967F48F01A866E721E67E4C9A1048AF68927FAA43D6A85D93E7BF7074DBA797563FCABE12309B76653C6DB614DC231CC556D9F25AC4841A02D31CDF3015B212307F9D0C79FEB5D3956CE53CC8FA1651BE60761F19F74672489EAF9F215409F39956E77A82183F1F72BB2FEDDF1B9FBFC4AD89EA445809DDBD5BD595277990C0BE9366FBB2ECF7B057CC1C3DC8FB77BF8456D07BBC95B3C1815F48E62B81468C3D4D9D96C0F48DAB04993BE8D91EDE5")); - assert_eq!(&key.primes()[1].to_bytes_be(), &hex!("CE36C6810522ABE5D6465F36EB137DA3B9EA4A5F1D27C6614729EB8E5E2E5CB88E3EF1A473A21944B66557B3DC2CE462E4BF3446CB4990037E5672B1705CBAE81B65BAF967A266DC18EFE80F4DBBFE1A59063205CE2943CADF421CCE74AF7063FD1A83AF3C39AF84525F59BDC1FF54815F52AFD1E8D4862B2C3654F6CFA83DC08E2A9D52B9F833C646AF7694467DFC5F7D7AD7B441895FCB7FFBED526324B0154A15823F5107C89548EDDCB61DA5308C6CC834D4A0C16DFA6CA1D67B61A65677EB1719CD125D0EF0DB8802FB76CFC17577BCB2510AE294E1BF8A9173A2B85C16A6B508C98F2D770B7F3DE48D9E720C53E263680B57E7109410015745570652FD")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); + assert_eq!(&key.d().to_be_bytes()[..], &hex!("9FE3097B2322B90FAB6606C017A095EBE640C39C100BCEE02F238FA14DAFF38E9E57568F1127ED4436126B904631B127EC395BB3EE127EB82C88D2562A7FB55FED8D1450B7E4E2D2F37F5742636FCC6F289963522D5B5706082CADFA01C0EE99B4D0E9274D3A992E06974CBE01694686356962AC1959FD9BD447E5B9968C0543DF1BF134742AF345CDB2FA1F9371B0D4CF61C68D16D653D8E999D4FD3A16CF978A35AA40E860CDCE09655DD8B4CF19D4141B1E92AD5E51A8E4A5C27FA745611D90E49D0E9282222AB6F126643E1C77578816FCE3B98F321D2549F294A470DF8453446BF36F985DF25ED8FDE9FDF3073FB27727DF48E9E1FC7056BC78965090B7850126406462C8253051EF84E34EE3C3CEB8F96C658C38BE45558D2F64E29D223350555FC1EFA28EC1F4AFB5BA4080F09A86CDC3538C1AD7C972E6D7A3612E6845BA9AFBDF19F09060D1A779DE9635E2D2F8E0C510BA24C6C44B30C9BDFAF85BE917AEC5D43AFAB1AA3ADD33CC83DA93CAC69218F6A36EB47F199D5424C95FD9ED7B1E8BE2AEAA6433B227241316C20EE792650CEB48BFD634446B19D286B4EA1722498DA1A36973210EC3824751A5808D9AAEF59C449E19A5077CFECA126BD9A8DD4996561D4E27B3609FF82C5B1B21E627845D44961B33B875D5C4FA9FF357EF6BE3364969E1337C91B29A07B9A913CDE40CE2D5530C900E73751685E65431")); + assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("D0213A79425B665B719118448893EC3275600F63DBF85B77F4E8E99EF302F6E82596048F6DCA772DE6BBF1124DB84B0AFE61B03A8604AB0079ED53F3304797AD01B38C44FE27A5A45E378483A804B56A4A967F48F01A866E721E67E4C9A1048AF68927FAA43D6A85D93E7BF7074DBA797563FCABE12309B76653C6DB614DC231CC556D9F25AC4841A02D31CDF3015B212307F9D0C79FEB5D3956CE53CC8FA1651BE60761F19F74672489EAF9F215409F39956E77A82183F1F72BB2FEDDF1B9FBFC4AD89EA445809DDBD5BD595277990C0BE9366FBB2ECF7B057CC1C3DC8FB77BF8456D07BBC95B3C1815F48E62B81468C3D4D9D96C0F48DAB04993BE8D91EDE5")); + assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("CE36C6810522ABE5D6465F36EB137DA3B9EA4A5F1D27C6614729EB8E5E2E5CB88E3EF1A473A21944B66557B3DC2CE462E4BF3446CB4990037E5672B1705CBAE81B65BAF967A266DC18EFE80F4DBBFE1A59063205CE2943CADF421CCE74AF7063FD1A83AF3C39AF84525F59BDC1FF54815F52AFD1E8D4862B2C3654F6CFA83DC08E2A9D52B9F833C646AF7694467DFC5F7D7AD7B441895FCB7FFBED526324B0154A15823F5107C89548EDDCB61DA5308C6CC834D4A0C16DFA6CA1D67B61A65677EB1719CD125D0EF0DB8802FB76CFC17577BCB2510AE294E1BF8A9173A2B85C16A6B508C98F2D770B7F3DE48D9E720C53E263680B57E7109410015745570652FD")); } #[test] @@ -153,8 +153,8 @@ fn decode_rsa2048_pub_pem() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa2048-pub.pem - assert_eq!(&key.n().to_bytes_be(), &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); } #[test] @@ -164,8 +164,8 @@ fn decode_rsa4096_pub_pem() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa4096-pub.pem - assert_eq!(&key.n().to_bytes_be(), &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); } #[test] diff --git a/tests/pkcs8.rs b/tests/pkcs8.rs index ee597e18..d8c97b32 100644 --- a/tests/pkcs8.rs +++ b/tests/pkcs8.rs @@ -31,11 +31,11 @@ fn decode_rsa2048_priv_der() { let key = RsaPrivateKey::from_pkcs8_der(RSA_2048_PRIV_DER).unwrap(); // Note: matches PKCS#1 test vectors - assert_eq!(&key.n().to_bytes_be(), &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); - assert_eq!(&key.d().to_bytes_be(), &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); - assert_eq!(&key.primes()[0].to_bytes_be(), &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); - assert_eq!(&key.primes()[1].to_bytes_be(), &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); + assert_eq!(&key.d().to_be_bytes()[..], &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); + assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); + assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); let _ = pkcs1v15::SigningKey::::from_pkcs8_der(RSA_2048_PRIV_DER).unwrap(); } @@ -45,8 +45,8 @@ fn decode_rsa2048_pub_der() { let key = RsaPublicKey::from_public_key_der(RSA_2048_PUB_DER).unwrap(); // Note: matches PKCS#1 test vectors - assert_eq!(&key.n().to_bytes_be(), &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); let _ = pkcs1v15::VerifyingKey::::from_public_key_der(RSA_2048_PUB_DER).unwrap(); } @@ -80,11 +80,11 @@ fn decode_rsa2048_priv_pem() { let key = RsaPrivateKey::from_pkcs8_pem(RSA_2048_PRIV_PEM).unwrap(); // Note: matches PKCS#1 test vectors - assert_eq!(&key.n().to_bytes_be(), &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); - assert_eq!(&key.d().to_bytes_be(), &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); - assert_eq!(&key.primes()[0].to_bytes_be(), &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); - assert_eq!(&key.primes()[1].to_bytes_be(), &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); + assert_eq!(&key.d().to_be_bytes()[..], &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); + assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); + assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); let _ = pkcs1v15::SigningKey::::from_pkcs8_pem(RSA_2048_PRIV_PEM).unwrap(); } @@ -95,8 +95,8 @@ fn decode_rsa2048_pub_pem() { let key = RsaPublicKey::from_public_key_pem(RSA_2048_PUB_PEM).unwrap(); // Note: matches PKCS#1 test vectors - assert_eq!(&key.n().to_bytes_be(), &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); - assert_eq!(&key.e().to_bytes_be(), &hex!("010001")); + assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); let _ = pkcs1v15::VerifyingKey::::from_public_key_pem(RSA_2048_PUB_PEM).unwrap(); } From b2bb016db53a540f9646b0f0dd634c1ab8cb3982 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 25 Mar 2024 17:46:49 +0100 Subject: [PATCH 33/51] handle encoding sizes --- src/encoding.rs | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/encoding.rs b/src/encoding.rs index 6a86b543..5ecf6517 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -35,13 +35,27 @@ impl TryFrom> for RsaPrivateKey { if pkcs1_key.version() != pkcs1::Version::TwoPrime { return Err(pkcs1::Error::Version.into()); } - let bits = 512; // TODO: read from data - let n = BoxedUint::from_be_slice(pkcs1_key.modulus.as_bytes(), bits).unwrap(); - let n = Odd::new(n).unwrap(); - let e = u64::from_be_bytes(pkcs1_key.public_exponent.as_bytes().try_into().unwrap()); - let d = BoxedUint::from_be_slice(pkcs1_key.private_exponent.as_bytes(), bits).unwrap(); - let prime1 = BoxedUint::from_be_slice(pkcs1_key.prime1.as_bytes(), bits).unwrap(); - let prime2 = BoxedUint::from_be_slice(pkcs1_key.prime2.as_bytes(), bits).unwrap(); + + let key_malformed = pkcs8::Error::KeyMalformed; + + let bits = + u32::try_from(pkcs1_key.modulus.as_bytes().len()).map_err(|_| key_malformed)? / 8; + let n = BoxedUint::from_be_slice(pkcs1_key.modulus.as_bytes(), bits) + .map_err(|_| key_malformed)?; + let n = Option::from(Odd::new(n)).ok_or_else(|| key_malformed)?; + let e = u64::from_be_bytes( + pkcs1_key + .public_exponent + .as_bytes() + .try_into() + .map_err(|_| key_malformed)?, + ); + let d = BoxedUint::from_be_slice(pkcs1_key.private_exponent.as_bytes(), bits) + .map_err(|_| key_malformed)?; + let prime1 = BoxedUint::from_be_slice(pkcs1_key.prime1.as_bytes(), bits) + .map_err(|_| key_malformed)?; + let prime2 = BoxedUint::from_be_slice(pkcs1_key.prime2.as_bytes(), bits) + .map_err(|_| key_malformed)?; let primes = vec![prime1, prime2]; RsaPrivateKey::from_components(n, e, d, primes).map_err(|_| pkcs8::Error::KeyMalformed) } @@ -59,9 +73,18 @@ impl TryFrom> for RsaPublicKey { .ok_or(pkcs8::spki::Error::KeyMalformed)?, )?; - let bits = 512; // TODO: determine at runtime - let n = BoxedUint::from_be_slice(pkcs1_key.modulus.as_bytes(), bits).unwrap(); - let e = u64::from_be_bytes(pkcs1_key.public_exponent.as_bytes().try_into().unwrap()); + let key_malformed = pkcs8::spki::Error::KeyMalformed; + let bits = + u32::try_from(pkcs1_key.modulus.as_bytes().len()).map_err(|_| key_malformed)? / 8; + let n = BoxedUint::from_be_slice(pkcs1_key.modulus.as_bytes(), bits) + .map_err(|_| key_malformed)?; + let e = u64::from_be_bytes( + pkcs1_key + .public_exponent + .as_bytes() + .try_into() + .map_err(|_| key_malformed)?, + ); RsaPublicKey::new(n, e).map_err(|_| pkcs8::spki::Error::KeyMalformed) } } From 040f8b0c1ee114b860a0ee496f862d2403437d31 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 17:20:55 +0200 Subject: [PATCH 34/51] small fixes --- src/algorithms/generate.rs | 3 ++- src/key.rs | 1 - src/pkcs1v15/signature.rs | 2 +- src/pss/signature.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/algorithms/generate.rs b/src/algorithms/generate.rs index ad89bcaf..034cc985 100644 --- a/src/algorithms/generate.rs +++ b/src/algorithms/generate.rs @@ -77,7 +77,8 @@ pub(crate) fn generate_multi_prime_key_with_exp( for (i, prime) in primes.iter_mut().enumerate() { let bits = (todo / (nprimes - i)) as u32; - *prime = generate_prime_with_rng(rng, bits, bits); + let bits_precision = BoxedUint::zero_with_precision(bits).bits_precision(); + *prime = generate_prime_with_rng(rng, bits, bits_precision); todo -= prime.bits() as usize; } diff --git a/src/key.rs b/src/key.rs index 28aac6f4..5ea588b0 100644 --- a/src/key.rs +++ b/src/key.rs @@ -34,7 +34,6 @@ pub struct RsaPublicKey { /// Typically 0x10001 (65537) e: u64, - #[cfg_attr(feature = "serde", serde(skip))] n_params: BoxedMontyParams, } diff --git a/src/pkcs1v15/signature.rs b/src/pkcs1v15/signature.rs index 3209ba30..27bb35f1 100644 --- a/src/pkcs1v15/signature.rs +++ b/src/pkcs1v15/signature.rs @@ -116,7 +116,7 @@ mod tests { use super::*; use serde_test::{assert_tokens, Configure, Token}; let signature = Signature { - inner: BigUint::new(Vec::from([42])), + inner: BoxedUint::from(42u32), len: 1, }; diff --git a/src/pss/signature.rs b/src/pss/signature.rs index e7aee64f..f936b1aa 100644 --- a/src/pss/signature.rs +++ b/src/pss/signature.rs @@ -110,7 +110,7 @@ mod tests { use super::*; use serde_test::{assert_tokens, Configure, Token}; let signature = Signature { - inner: BigUint::new(Vec::from([42])), + inner: BoxedUint::from(42u32), len: 1, }; From 7b2aa3d70970c985df8fd7ff3445414d07e24e01 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 17:22:31 +0200 Subject: [PATCH 35/51] update deps --- Cargo.lock | 68 +++++++++++++++++++++++++++--------------------------- Cargo.toml | 2 +- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ecd643e..60b994d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,9 +48,9 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -256,9 +256,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.2.0-rc.8" +version = "0.2.0-rc.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53668f5da5a41d9eaf4bf7064be46d1ebe6a4e1ceed817f387587b18f2b51047" +checksum = "4d306b679262030ad8813a82d4915fc04efff97776e4db7f8eb5137039d56400" dependencies = [ "typenum", ] @@ -284,9 +284,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" @@ -381,18 +381,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ "bit-set", "bit-vec", @@ -464,9 +464,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rsa" @@ -646,15 +646,15 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.66" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -723,9 +723,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -739,51 +739,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "zeroize" diff --git a/Cargo.toml b/Cargo.toml index 9e950619..32f7e700 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ pkcs8 = { version = "=0.11.0-pre.0", default-features = false, features = ["allo signature = { version = "=2.3.0-pre.3", default-features = false , features = ["alloc", "digest", "rand_core"] } spki = { version = "=0.8.0-pre.0", default-features = false, features = ["alloc"] } zeroize = { version = "1.5", features = ["alloc"] } -crypto-bigint = { version = "0.6.0-pre.12", features = ["zeroize", "alloc"] } +crypto-bigint = { version = "0.6.0-rc.0", features = ["zeroize", "alloc"] } crypto-primes = { version = "0.6.0-pre.0" } # optional dependencies From a2d49989aa447c78b9ca1b7bd29f5644e378ffd0 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 18:03:42 +0200 Subject: [PATCH 36/51] widen and shorten --- src/algorithms/rsa.rs | 47 +++++++++++++++++++++++++++++-------------- src/encoding.rs | 9 +++++++-- src/key.rs | 13 ++++++++++-- 3 files changed, 50 insertions(+), 19 deletions(-) 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, From cf3548b6a1678108ad583d9ab4e69faa8048d045 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 18:38:31 +0200 Subject: [PATCH 37/51] some encoding fixes --- src/algorithms/rsa.rs | 10 +++++----- src/encoding.rs | 20 +++++++++++--------- src/key.rs | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 9d21f782..f659fa5c 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -1,8 +1,7 @@ //! Generic RSA implementation -use alloc::borrow::Cow; use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams}; -use crypto_bigint::{BoxedUint, Gcd, InvMod, NonZero, Odd, RandomMod, Wrapping}; +use crypto_bigint::{BoxedUint, Gcd, NonZero, Odd, RandomMod, Wrapping}; use rand_core::CryptoRngCore; use zeroize::Zeroize; @@ -323,9 +322,10 @@ pub(crate) fn compute_private_exponent_carmicheal( let p1 = p - &BoxedUint::one(); let q1 = q - &BoxedUint::one(); - let lcm = p1; // TODO: p1.lcm(&q1); - let lcm = Odd::new(lcm).unwrap(); - if let Some(d) = BoxedUint::from(exp).inv_odd_mod(&lcm).into() { + // LCM inlined + let gcd = p1.gcd(&q1).unwrap(); + let lcm = p1 / NonZero::new(gcd).unwrap() * &q1; + if let Some(d) = BoxedUint::from(exp).inv_mod(&lcm).into() { Ok(d) } else { // `exp` evenly divides `lcm` diff --git a/src/encoding.rs b/src/encoding.rs index 4bbe6624..2ab33c7e 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -54,25 +54,27 @@ impl TryFrom> for RsaPrivateKey { let key_malformed = pkcs8::Error::KeyMalformed; let bits = - u32::try_from(pkcs1_key.modulus.as_bytes().len()).map_err(|_| key_malformed)? / 8; + u32::try_from(pkcs1_key.modulus.as_bytes().len()).map_err(|_| key_malformed)? * 8; + let n = BoxedUint::from_be_slice(pkcs1_key.modulus.as_bytes(), bits) .map_err(|_| key_malformed)?; let n = Option::from(Odd::new(n)).ok_or_else(|| key_malformed)?; - let e = u64::from_be_bytes( - pkcs1_key - .public_exponent - .as_bytes() - .try_into() - .map_err(|_| key_malformed)?, - ); + + // exponent potentially needs padding + let mut e_slice = [0u8; 8]; + let raw_e_slice = pkcs1_key.public_exponent.as_bytes(); + e_slice[8 - raw_e_slice.len()..].copy_from_slice(raw_e_slice); + let e = u64::from_be_bytes(e_slice); let d = BoxedUint::from_be_slice(pkcs1_key.private_exponent.as_bytes(), bits) .map_err(|_| key_malformed)?; + let prime1 = BoxedUint::from_be_slice(pkcs1_key.prime1.as_bytes(), bits) .map_err(|_| key_malformed)?; let prime2 = BoxedUint::from_be_slice(pkcs1_key.prime2.as_bytes(), bits) .map_err(|_| key_malformed)?; let primes = vec![prime1, prime2]; - RsaPrivateKey::from_components(n, e, d, primes).map_err(|_| pkcs8::Error::KeyMalformed) + + RsaPrivateKey::from_components(n, e, d, primes).map_err(|_| key_malformed) } } diff --git a/src/key.rs b/src/key.rs index 050b9cc3..e7d660b9 100644 --- a/src/key.rs +++ b/src/key.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams}; -use crypto_bigint::{BoxedUint, Integer, InvMod, NonZero, Odd}; +use crypto_bigint::{BoxedUint, Integer, NonZero, Odd}; use rand_core::CryptoRngCore; use zeroize::{Zeroize, ZeroizeOnDrop}; #[cfg(feature = "serde")] From 3ef5f3f04995eed4078d2563667d48edfa4c94bb Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 19:11:54 +0200 Subject: [PATCH 38/51] fix serde tests --- src/encoding.rs | 17 +++++++++-------- src/key.rs | 6 ++---- src/oaep/decrypting_key.rs | 2 +- src/oaep/encrypting_key.rs | 2 +- src/pkcs1v15.rs | 11 ++--------- src/pkcs1v15/decrypting_key.rs | 2 +- src/pkcs1v15/encrypting_key.rs | 2 +- src/pkcs1v15/signature.rs | 22 ++++------------------ src/pkcs1v15/signing_key.rs | 2 +- src/pkcs1v15/verifying_key.rs | 13 ++----------- src/pss.rs | 3 +-- src/pss/blinded_signing_key.rs | 2 +- src/pss/signature.rs | 22 ++++------------------ src/pss/signing_key.rs | 2 +- src/pss/verifying_key.rs | 14 +++----------- 15 files changed, 34 insertions(+), 88 deletions(-) diff --git a/src/encoding.rs b/src/encoding.rs index 2ab33c7e..34860749 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -65,6 +65,7 @@ impl TryFrom> for RsaPrivateKey { let raw_e_slice = pkcs1_key.public_exponent.as_bytes(); e_slice[8 - raw_e_slice.len()..].copy_from_slice(raw_e_slice); let e = u64::from_be_bytes(e_slice); + let d = BoxedUint::from_be_slice(pkcs1_key.private_exponent.as_bytes(), bits) .map_err(|_| key_malformed)?; @@ -92,16 +93,16 @@ impl TryFrom> for RsaPublicKey { let key_malformed = pkcs8::spki::Error::KeyMalformed; let bits = - u32::try_from(pkcs1_key.modulus.as_bytes().len()).map_err(|_| key_malformed)? / 8; + u32::try_from(pkcs1_key.modulus.as_bytes().len()).map_err(|_| key_malformed)? * 8; let n = BoxedUint::from_be_slice(pkcs1_key.modulus.as_bytes(), bits) .map_err(|_| key_malformed)?; - let e = u64::from_be_bytes( - pkcs1_key - .public_exponent - .as_bytes() - .try_into() - .map_err(|_| key_malformed)?, - ); + + // exponent potentially needs padding + let mut e_slice = [0u8; 8]; + let raw_e_slice = pkcs1_key.public_exponent.as_bytes(); + e_slice[8 - raw_e_slice.len()..].copy_from_slice(raw_e_slice); + let e = u64::from_be_bytes(e_slice); + RsaPublicKey::new(n, e).map_err(|_| pkcs8::spki::Error::KeyMalformed) } } diff --git a/src/key.rs b/src/key.rs index e7d660b9..4cb52a94 100644 --- a/src/key.rs +++ b/src/key.rs @@ -767,14 +767,12 @@ mod tests { let priv_key = RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"); let priv_tokens = [Token::Str( - "3054020100300d06092a864886f70d01010105000440303e020100020900cc6c\ - 6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d4\ - 6b68cb02046d9a09f102047b4e3a4f020500f45065cc", + "3054020100300d06092a864886f70d01010105000440303e020100020900aaadacc31e2e5119020301000102087e1710295cb2ba81020500b21fdf97020500f54c6acf02040b862461020463ed8f8d0205008bb00f5f", )]; assert_tokens(&priv_key.clone().readable(), &priv_tokens); let priv_tokens = [Token::Str( - "3024300d06092a864886f70d01010105000313003010020900cc6c6130e35b46bf0203010001", + "3024300d06092a864886f70d01010105000313003010020900aaadacc31e2e51190203010001", )]; assert_tokens( &RsaPublicKey::from(priv_key.clone()).readable(), diff --git a/src/oaep/decrypting_key.rs b/src/oaep/decrypting_key.rs index 83ab2824..02d4e08c 100644 --- a/src/oaep/decrypting_key.rs +++ b/src/oaep/decrypting_key.rs @@ -126,7 +126,7 @@ mod tests { let tokens = [ Token::Struct { name: "DecryptingKey", len: 4 }, Token::Str("inner"), - Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900cc6c6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d46b68cb02046d9a09f102047b4e3a4f020500f45065cc"), + Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900aaadacc31e2e5119020301000102087e1710295cb2ba81020500b21fdf97020500f54c6acf02040b862461020463ed8f8d0205008bb00f5f"), Token::Str("label"), Token::None, Token::Str("phantom"), diff --git a/src/oaep/encrypting_key.rs b/src/oaep/encrypting_key.rs index 9a9ae290..ec35d952 100644 --- a/src/oaep/encrypting_key.rs +++ b/src/oaep/encrypting_key.rs @@ -97,7 +97,7 @@ mod tests { }, Token::Str("inner"), Token::Str( - "3024300d06092a864886f70d01010105000313003010020900cc6c6130e35b46bf0203010001", + "3024300d06092a864886f70d01010105000313003010020900aaadacc31e2e51190203010001", ), Token::Str("label"), Token::None, diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index 12ec7b97..e26f2a39 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -127,7 +127,6 @@ impl SignatureScheme for Pkcs1v15Sign { self.prefix.as_ref(), hashed, &BoxedUint::from_be_slice(sig, sig.len() as u32 * 8)?, - sig.len(), ) } } @@ -209,15 +208,9 @@ fn sign( /// Verifies an RSA PKCS#1 v1.5 signature. #[inline] -fn verify( - pub_key: &RsaPublicKey, - prefix: &[u8], - hashed: &[u8], - sig: &BoxedUint, - sig_len: usize, -) -> Result<()> { +fn verify(pub_key: &RsaPublicKey, prefix: &[u8], hashed: &[u8], sig: &BoxedUint) -> Result<()> { let n = crate::traits::keys::PublicKeyParts::n(pub_key); - if sig >= n.as_ref() || sig_len != pub_key.size() { + if sig >= n.as_ref() || sig.bits_precision() != pub_key.n_bits_precision() { return Err(Error::Verification); } diff --git a/src/pkcs1v15/decrypting_key.rs b/src/pkcs1v15/decrypting_key.rs index 78aee178..6ff0e850 100644 --- a/src/pkcs1v15/decrypting_key.rs +++ b/src/pkcs1v15/decrypting_key.rs @@ -69,7 +69,7 @@ mod tests { let tokens = [ Token::Struct { name: "DecryptingKey", len: 1 }, Token::Str("inner"), - Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900cc6c6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d46b68cb02046d9a09f102047b4e3a4f020500f45065cc"), + Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900aaadacc31e2e5119020301000102087e1710295cb2ba81020500b21fdf97020500f54c6acf02040b862461020463ed8f8d0205008bb00f5f"), Token::StructEnd, ]; assert_tokens(&decrypting_key.readable(), &tokens); diff --git a/src/pkcs1v15/encrypting_key.rs b/src/pkcs1v15/encrypting_key.rs index 2850f79d..d12f2b66 100644 --- a/src/pkcs1v15/encrypting_key.rs +++ b/src/pkcs1v15/encrypting_key.rs @@ -51,7 +51,7 @@ mod tests { }, Token::Str("inner"), Token::Str( - "3024300d06092a864886f70d01010105000313003010020900cc6c6130e35b46bf0203010001", + "3024300d06092a864886f70d01010105000313003010020900aaadacc31e2e51190203010001", ), Token::StructEnd, ]; diff --git a/src/pkcs1v15/signature.rs b/src/pkcs1v15/signature.rs index 27bb35f1..2604f730 100644 --- a/src/pkcs1v15/signature.rs +++ b/src/pkcs1v15/signature.rs @@ -1,8 +1,7 @@ //! `RSASSA-PKCS1-v1_5` signatures. -use crate::algorithms::pad::uint_to_be_pad; use ::signature::SignatureEncoding; -use alloc::{boxed::Box, string::ToString}; +use alloc::boxed::Box; use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex}; use crypto_bigint::BoxedUint; @@ -16,10 +15,9 @@ use spki::{ /// `RSASSA-PKCS1-v1_5` signatures as described in [RFC8017 § 8.2]. /// /// [RFC8017 § 8.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2 -#[derive(Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Signature { pub(super) inner: BoxedUint, - pub(super) len: usize, } impl SignatureEncoding for Signature { @@ -40,24 +38,13 @@ impl TryFrom<&[u8]> for Signature { Ok(Self { // TODO: how to convert error? inner: BoxedUint::from_be_slice(bytes, len as u32 * 8).unwrap(), - len, }) } } impl From for Box<[u8]> { fn from(signature: Signature) -> Box<[u8]> { - uint_to_be_pad(signature.inner, signature.len) - .expect("RSASSA-PKCS1-v1_5 length invariants should've been enforced") - .into_boxed_slice() - } -} - -impl Debug for Signature { - fn fmt(&self, fmt: &mut Formatter<'_>) -> core::result::Result<(), core::fmt::Error> { - fmt.debug_tuple("Signature") - .field(&self.to_string()) - .finish() + signature.inner.to_be_bytes() } } @@ -117,10 +104,9 @@ mod tests { use serde_test::{assert_tokens, Configure, Token}; let signature = Signature { inner: BoxedUint::from(42u32), - len: 1, }; - let tokens = [Token::Str("2a")]; + let tokens = [Token::Str("000000000000002a")]; assert_tokens(&signature.readable(), &tokens); } } diff --git a/src/pkcs1v15/signing_key.rs b/src/pkcs1v15/signing_key.rs index 912cc657..ced45995 100644 --- a/src/pkcs1v15/signing_key.rs +++ b/src/pkcs1v15/signing_key.rs @@ -309,7 +309,7 @@ mod tests { let signing_key = SigningKey::::new(priv_key); let tokens = [ - Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900cc6c6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d46b68cb02046d9a09f102047b4e3a4f020500f45065cc") + Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900aaadacc31e2e5119020301000102087e1710295cb2ba81020500b21fdf97020500f54c6acf02040b862461020463ed8f8d0205008bb00f5f") ]; assert_tokens(&signing_key.readable(), &tokens); diff --git a/src/pkcs1v15/verifying_key.rs b/src/pkcs1v15/verifying_key.rs index fa23e8f7..c74ca372 100644 --- a/src/pkcs1v15/verifying_key.rs +++ b/src/pkcs1v15/verifying_key.rs @@ -85,7 +85,6 @@ where &self.prefix, &digest.finalize(), &signature.inner, - signature.len, ) .map_err(|e| e.into()) } @@ -96,14 +95,7 @@ where D: Digest, { fn verify_prehash(&self, prehash: &[u8], signature: &Signature) -> signature::Result<()> { - verify( - &self.inner, - &self.prefix, - prehash, - &signature.inner, - signature.len, - ) - .map_err(|e| e.into()) + verify(&self.inner, &self.prefix, prehash, &signature.inner).map_err(|e| e.into()) } } @@ -117,7 +109,6 @@ where &self.prefix.clone(), &D::digest(msg), &signature.inner, - signature.len, ) .map_err(|e| e.into()) } @@ -265,7 +256,7 @@ mod tests { let verifying_key = VerifyingKey::::new(pub_key); let tokens = [Token::Str( - "3024300d06092a864886f70d01010105000313003010020900cc6c6130e35b46bf0203010001", + "3024300d06092a864886f70d01010105000313003010020900aaadacc31e2e51190203010001", )]; assert_tokens(&verifying_key.readable(), &tokens); diff --git a/src/pss.rs b/src/pss.rs index 1d79e02d..855069d7 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -145,14 +145,13 @@ pub(crate) fn verify_digest( pub_key: &RsaPublicKey, hashed: &[u8], sig: &BoxedUint, - sig_len: usize, salt_len: usize, ) -> Result<()> where D: Digest + FixedOutputReset, { let n = crate::traits::keys::PublicKeyParts::n(pub_key); - if sig >= n.as_ref() || sig_len != pub_key.size() { + if sig >= n.as_ref() || sig.bits_precision() != pub_key.n_bits_precision() { return Err(Error::Verification); } diff --git a/src/pss/blinded_signing_key.rs b/src/pss/blinded_signing_key.rs index 4d9eba22..85ca5e31 100644 --- a/src/pss/blinded_signing_key.rs +++ b/src/pss/blinded_signing_key.rs @@ -267,7 +267,7 @@ mod tests { ); let tokens = [ - Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900cc6c6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d46b68cb02046d9a09f102047b4e3a4f020500f45065cc") + Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900aaadacc31e2e5119020301000102087e1710295cb2ba81020500b21fdf97020500f54c6acf02040b862461020463ed8f8d0205008bb00f5f") ]; assert_tokens(&signing_key.readable(), &tokens); } diff --git a/src/pss/signature.rs b/src/pss/signature.rs index f936b1aa..065424b9 100644 --- a/src/pss/signature.rs +++ b/src/pss/signature.rs @@ -1,8 +1,7 @@ //! `RSASSA-PSS` signatures. -use crate::algorithms::pad::uint_to_be_pad; use ::signature::SignatureEncoding; -use alloc::{boxed::Box, string::ToString}; +use alloc::boxed::Box; use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex}; use crypto_bigint::BoxedUint; @@ -16,10 +15,9 @@ use spki::{ /// `RSASSA-PSS` signatures as described in [RFC8017 § 8.1]. /// /// [RFC8017 § 8.1]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.1 -#[derive(Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Signature { pub(super) inner: BoxedUint, - pub(super) len: usize, } impl SignatureEncoding for Signature { @@ -38,7 +36,6 @@ impl TryFrom<&[u8]> for Signature { fn try_from(bytes: &[u8]) -> signature::Result { let len = bytes.len(); Ok(Self { - len, // TODO: how to convert the error? inner: BoxedUint::from_be_slice(bytes, len as u32 * 8).unwrap(), }) @@ -47,17 +44,7 @@ impl TryFrom<&[u8]> for Signature { impl From for Box<[u8]> { fn from(signature: Signature) -> Box<[u8]> { - uint_to_be_pad(signature.inner, signature.len) - .expect("RSASSA-PKCS1-v1_5 length invariants should've been enforced") - .into_boxed_slice() - } -} - -impl Debug for Signature { - fn fmt(&self, fmt: &mut Formatter<'_>) -> core::result::Result<(), core::fmt::Error> { - fmt.debug_tuple("Signature") - .field(&self.to_string()) - .finish() + signature.inner.to_be_bytes() } } @@ -111,10 +98,9 @@ mod tests { use serde_test::{assert_tokens, Configure, Token}; let signature = Signature { inner: BoxedUint::from(42u32), - len: 1, }; - let tokens = [Token::Str("2a")]; + let tokens = [Token::Str("000000000000002a")]; assert_tokens(&signature.readable(), &tokens); } } diff --git a/src/pss/signing_key.rs b/src/pss/signing_key.rs index 574d30ed..b4b25f0b 100644 --- a/src/pss/signing_key.rs +++ b/src/pss/signing_key.rs @@ -291,7 +291,7 @@ mod tests { let signing_key = SigningKey::::new(priv_key); let tokens = [ - Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900cc6c6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d46b68cb02046d9a09f102047b4e3a4f020500f45065cc") + Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900aaadacc31e2e5119020301000102087e1710295cb2ba81020500b21fdf97020500f54c6acf02040b862461020463ed8f8d0205008bb00f5f") ]; assert_tokens(&signing_key.readable(), &tokens); diff --git a/src/pss/verifying_key.rs b/src/pss/verifying_key.rs index 2fd62d37..f6e4d75b 100644 --- a/src/pss/verifying_key.rs +++ b/src/pss/verifying_key.rs @@ -61,7 +61,6 @@ where &self.inner, &digest.finalize(), &signature.inner, - signature.len, self.salt_len, ) .map_err(|e| e.into()) @@ -73,14 +72,8 @@ where D: Digest + FixedOutputReset, { fn verify_prehash(&self, prehash: &[u8], signature: &Signature) -> signature::Result<()> { - verify_digest::( - &self.inner, - prehash, - &signature.inner, - signature.len, - self.salt_len, - ) - .map_err(|e| e.into()) + verify_digest::(&self.inner, prehash, &signature.inner, self.salt_len) + .map_err(|e| e.into()) } } @@ -93,7 +86,6 @@ where &self.inner, &D::digest(msg), &signature.inner, - signature.len, self.salt_len, ) .map_err(|e| e.into()) @@ -236,7 +228,7 @@ mod tests { let verifying_key = VerifyingKey::::new(pub_key); let tokens = [Token::Str( - "3024300d06092a864886f70d01010105000313003010020900cc6c6130e35b46bf0203010001", + "3024300d06092a864886f70d01010105000313003010020900aaadacc31e2e51190203010001", )]; assert_tokens(&verifying_key.readable(), &tokens); From bd308a4291a369bb31134090edeeedfa93085bd7 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 19:34:12 +0200 Subject: [PATCH 39/51] fix pkcs test parsing --- src/pkcs1v15.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index e26f2a39..3ac3bdc0 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -297,14 +297,13 @@ mod tests { // tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V // -----END RSA PRIVATE KEY----- - let bits = 512; RsaPrivateKey::from_components( - Odd::new(BoxedUint::from_be_hex("B2990F49C47DFA8CD400AE6A4D1B8A3B6A13642B23F28B003BFB97790ADE9A4CC82B8B2A81747DDEC08B6296E53A08C331687EF25C4BF4936BA1C0E6041E9D15", bits).unwrap()).unwrap(), + Odd::new(BoxedUint::from_be_hex("B2990F49C47DFA8CD400AE6A4D1B8A3B6A13642B23F28B003BFB97790ADE9A4CC82B8B2A81747DDEC08B6296E53A08C331687EF25C4BF4936BA1C0E6041E9D15", 512).unwrap()).unwrap(), 65537, - BoxedUint::from_be_hex("8ABD6A69F4D1A4B487F0AB8D7AAEFD38609405C999984E30F567E1E8AEEFF44E8B18BDB1EC78DFA31A55E32A48D7FB131F5AF1F44D7D6B2CED2A9DF5E5AE4535", bits).unwrap(), + BoxedUint::from_be_hex("8ABD6A69F4D1A4B487F0AB8D7AAEFD38609405C999984E30F567E1E8AEEFF44E8B18BDB1EC78DFA31A55E32A48D7FB131F5AF1F44D7D6B2CED2A9DF5E5AE4535", 512).unwrap(), vec![ - BoxedUint::from_be_hex("DAB2F18048BAA68DE7DF04D2D35D5D80E60E2DFA42D50A9B04219032715E46B3", bits).unwrap(), - BoxedUint::from_be_hex("D10F2E66B1D0C13F10EF9927BF5324A379CA218146CBF9CAFC795221F16A3117", bits).unwrap() + BoxedUint::from_be_hex("DAB2F18048BAA68DE7DF04D2D35D5D80E60E2DFA42D50A9B04219032715E46B3", 256).unwrap(), + BoxedUint::from_be_hex("D10F2E66B1D0C13F10EF9927BF5324A379CA218146CBF9CAFC795221F16A3117", 256).unwrap() ], ).unwrap() } From 1b070ca44a44020347427b72943c937e58e25524 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 19:37:10 +0200 Subject: [PATCH 40/51] fix oaep test decoding --- src/oaep.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/oaep.rs b/src/oaep.rs index fba7a66e..faac7d67 100644 --- a/src/oaep.rs +++ b/src/oaep.rs @@ -344,14 +344,13 @@ mod tests { // BoB0er/UmDm4Ly/97EO9A0PKMOE5YbMq9s3t3RlWcsdrU7dvw+p2+A== // -----END RSA PRIVATE KEY----- - let bits = 1024; RsaPrivateKey::from_components( - Odd::new(BoxedUint::from_be_hex("00d397b84d98a4c26138ed1b695a8106ead91d553bf06041b62d3fdc50a041e222b8f4529689c1b82c5e71554f5dd69fa2f4b6158cf0dbeb57811a0fc327e1f28e74fe74d3bc166c1eabdc1b8b57b934ca8be5b00b4f29975bcc99acaf415b59bb28a6782bb41a2c3c2976b3c18dbadef62f00c6bb226640095096c0cc60d22fe7ef987d75c6a81b10d96bf292028af110dc7cc1bbc43d22adab379a0cd5d8078cc780ff5cd6209dea34c922cf784f7717e428d75b5aec8ff30e5f0141510766e2e0ab8d473c84e8710b2b98227c3db095337ad3452f19e2b9bfbccdd8148abf6776fa552775e6e75956e45229ae5a9c46949bab1e622f0e48f56524a84ed3483b", bits).unwrap()).unwrap(), + Odd::new(BoxedUint::from_be_hex("d397b84d98a4c26138ed1b695a8106ead91d553bf06041b62d3fdc50a041e222b8f4529689c1b82c5e71554f5dd69fa2f4b6158cf0dbeb57811a0fc327e1f28e74fe74d3bc166c1eabdc1b8b57b934ca8be5b00b4f29975bcc99acaf415b59bb28a6782bb41a2c3c2976b3c18dbadef62f00c6bb226640095096c0cc60d22fe7ef987d75c6a81b10d96bf292028af110dc7cc1bbc43d22adab379a0cd5d8078cc780ff5cd6209dea34c922cf784f7717e428d75b5aec8ff30e5f0141510766e2e0ab8d473c84e8710b2b98227c3db095337ad3452f19e2b9bfbccdd8148abf6776fa552775e6e75956e45229ae5a9c46949bab1e622f0e48f56524a84ed3483b", 2048).unwrap()).unwrap(), 65537, - BoxedUint::from_be_hex("00c4e70c689162c94c660828191b52b4d8392115df486a9adbe831e458d73958320dc1b755456e93701e9702d76fb0b92f90e01d1fe248153281fe79aa9763a92fae69d8d7ecd144de29fa135bd14f9573e349e45031e3b76982f583003826c552e89a397c1a06bd2163488630d92e8c2bb643d7abef700da95d685c941489a46f54b5316f62b5d2c3a7f1bbd134cb37353a44683fdc9d95d36458de22f6c44057fe74a0a436c4308f73f4da42f35c47ac16a7138d483afc91e41dc3a1127382e0c0f5119b0221b4fc639d6b9c38177a6de9b526ebd88c38d7982c07f98a0efd877d508aae275b946915c02e2e1106d175d74ec6777f5e80d12c053d9c7be1e341", bits).unwrap(), + BoxedUint::from_be_hex("c4e70c689162c94c660828191b52b4d8392115df486a9adbe831e458d73958320dc1b755456e93701e9702d76fb0b92f90e01d1fe248153281fe79aa9763a92fae69d8d7ecd144de29fa135bd14f9573e349e45031e3b76982f583003826c552e89a397c1a06bd2163488630d92e8c2bb643d7abef700da95d685c941489a46f54b5316f62b5d2c3a7f1bbd134cb37353a44683fdc9d95d36458de22f6c44057fe74a0a436c4308f73f4da42f35c47ac16a7138d483afc91e41dc3a1127382e0c0f5119b0221b4fc639d6b9c38177a6de9b526ebd88c38d7982c07f98a0efd877d508aae275b946915c02e2e1106d175d74ec6777f5e80d12c053d9c7be1e341", 2048).unwrap(), vec![ - BoxedUint::from_be_hex("00f827bbf3a41877c7cc59aebf42ed4b29c32defcb8ed96863d5b090a05a8930dd624a21c9dcf9838568fdfa0df65b8462a5f2ac913d6c56f975532bd8e78fb07bd405ca99a484bcf59f019bbddcb3933f2bce706300b4f7b110120c5df9018159067c35da3061a56c8635a52b54273b31271b4311f0795df6021e6355e1a42e61", bits).unwrap(), - BoxedUint::from_be_hex("00da4817ce0089dd36f2ade6a3ff410c73ec34bf1b4f6bda38431bfede11cef1f7f6efa70e5f8063a3b1f6e17296ffb15feefa0912a0325b8d1fd65a559e717b5b961ec345072e0ec5203d03441d29af4d64054a04507410cf1da78e7b6119d909ec66e6ad625bf995b279a4b3c5be7d895cd7c5b9c4c497fde730916fcdb4e41b", bits).unwrap() + BoxedUint::from_be_hex("f827bbf3a41877c7cc59aebf42ed4b29c32defcb8ed96863d5b090a05a8930dd624a21c9dcf9838568fdfa0df65b8462a5f2ac913d6c56f975532bd8e78fb07bd405ca99a484bcf59f019bbddcb3933f2bce706300b4f7b110120c5df9018159067c35da3061a56c8635a52b54273b31271b4311f0795df6021e6355e1a42e61", 1024).unwrap(), + BoxedUint::from_be_hex("da4817ce0089dd36f2ade6a3ff410c73ec34bf1b4f6bda38431bfede11cef1f7f6efa70e5f8063a3b1f6e17296ffb15feefa0912a0325b8d1fd65a559e717b5b961ec345072e0ec5203d03441d29af4d64054a04507410cf1da78e7b6119d909ec66e6ad625bf995b279a4b3c5be7d895cd7c5b9c4c497fde730916fcdb4e41b", 1024).unwrap() ], ).unwrap() } From 2badedec343faf537b3af03c7d69ee2409d84938 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 19:59:03 +0200 Subject: [PATCH 41/51] add doc comments --- src/traits/keys.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/traits/keys.rs b/src/traits/keys.rs index 2525117a..adc78172 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -20,8 +20,10 @@ pub trait PublicKeyParts { (self.n().bits() as usize + 7) / 8 } + /// Returns the parameters for montgomery operations. fn n_params(&self) -> BoxedMontyParams; + /// Returns precision (in bits) of `n`. fn n_bits_precision(&self) -> u32 { self.n().bits_precision() } @@ -47,7 +49,10 @@ pub trait PrivateKeyParts: PublicKeyParts { /// Returns an iterator over the CRT Values fn crt_values(&self) -> Option<&[CrtValue]>; + /// Returns the params for `p` if precomupted. fn p_params(&self) -> Option<&BoxedMontyParams>; + + /// Returns the params for `q` if precomupted. fn q_params(&self) -> Option<&BoxedMontyParams>; } From ee6b31a1929812ef0f216f929ab6ccdbaf66700d Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 20:10:39 +0200 Subject: [PATCH 42/51] improve feature selection --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 32f7e700..548a55d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ pkcs8 = { version = "=0.11.0-pre.0", default-features = false, features = ["allo signature = { version = "=2.3.0-pre.3", default-features = false , features = ["alloc", "digest", "rand_core"] } spki = { version = "=0.8.0-pre.0", default-features = false, features = ["alloc"] } zeroize = { version = "1.5", features = ["alloc"] } -crypto-bigint = { version = "0.6.0-rc.0", features = ["zeroize", "alloc"] } +crypto-bigint = { version = "0.6.0-rc.0", default-features = false, features = ["zeroize", "alloc"] } crypto-primes = { version = "0.6.0-pre.0" } # optional dependencies @@ -50,11 +50,11 @@ name = "key" [features] default = ["std", "pem"] hazmat = [] -getrandom = ["rand_core/getrandom"] +getrandom = ["rand_core/getrandom", "crypto-bigint/rand_core"] serde = ["dep:serde", "dep:serdect", "crypto-bigint/serde"] pem = ["pkcs1/pem", "pkcs8/pem"] pkcs5 = ["pkcs8/encryption"] -std = ["digest/std", "pkcs1/std", "pkcs8/std", "rand_core/std", "signature/std"] +std = ["digest/std", "pkcs1/std", "pkcs8/std", "rand_core/std", "signature/std", "crypto-bigint/std"] [package.metadata.docs.rs] features = ["std", "pem", "serde", "hazmat", "sha2"] From 64386b4571bb4dc69030ca18000804f250fbc42d Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 20:12:45 +0200 Subject: [PATCH 43/51] drop nightly feature --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 62be1e6d..13042f36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,7 @@ jobs: with: toolchain: ${{ matrix.rust }} - uses: RustCrypto/actions/cargo-hack-install@master - - run: cargo hack test --release --feature-powerset --exclude-features nightly,getrandom,serde + - run: cargo hack test --release --feature-powerset --exclude-features getrandom,serde - run: cargo test --release --features getrandom - run: cargo test --release --features serde @@ -66,5 +66,5 @@ jobs: - uses: dtolnay/rust-toolchain@master with: toolchain: nightly-2023-10-01 - - run: cargo test --release --features nightly + - run: cargo test --release - run: cargo build --benches From 53781fb837e4e83a7a5fbe15ba455a93abdd382a Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 20:13:25 +0200 Subject: [PATCH 44/51] update subtle min version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 548a55d6..c8672846 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ rust-version = "1.73" [dependencies] rand_core = { version = "0.6.4", default-features = false } const-oid = { version = "=0.10.0-pre.2", default-features = false } -subtle = { version = "2.1.1", default-features = false } +subtle = { version = "2.6.1", default-features = false } digest = { version = "=0.11.0-pre.8", default-features = false, features = ["alloc", "oid"] } pkcs1 = { version = "=0.8.0-pre.0", default-features = false, features = ["alloc", "pkcs8"] } pkcs8 = { version = "=0.11.0-pre.0", default-features = false, features = ["alloc"] } From 9c15ea920e132d29ef64c40bdb5c5e78049de02e Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2024 20:15:23 +0200 Subject: [PATCH 45/51] happy clippy --- src/algorithms/generate.rs | 2 +- src/algorithms/rsa.rs | 10 +++++----- src/encoding.rs | 2 +- src/key.rs | 4 ++-- src/pkcs1v15.rs | 2 +- src/pss.rs | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/algorithms/generate.rs b/src/algorithms/generate.rs index 034cc985..dae13294 100644 --- a/src/algorithms/generate.rs +++ b/src/algorithms/generate.rs @@ -109,7 +109,7 @@ pub(crate) fn generate_multi_prime_key_with_exp( Ok(RsaPrivateKeyComponents { n: n_final, - e: exp.clone(), + e: exp, d: d_final, primes, }) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index f659fa5c..705db92d 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -48,7 +48,7 @@ pub fn rsa_decrypt( let bits = d.bits_precision(); let c = if let Some(ref mut rng) = rng { - let (blinded, unblinder) = blind(rng, priv_key, &c, &n_params); + let (blinded, unblinder) = blind(rng, priv_key, c, &n_params); ir = Some(unblinder); blinded.widen(bits) } else { @@ -60,7 +60,7 @@ pub fn rsa_decrypt( let m = if is_multiprime || !has_precomputes { // c^d (mod n) - pow_mod_params(&c, &d, n_params.clone()) + pow_mod_params(&c, d, n_params.clone()) } else { // We have the precalculated values needed for the CRT. @@ -78,10 +78,10 @@ pub fn rsa_decrypt( // m1 = c^dP mod p let cp = BoxedMontyForm::new(c.clone(), p_params.clone()); - let mut m1 = cp.pow(&dp); + let mut m1 = cp.pow(dp); // m2 = c^dQ mod q let cq = BoxedMontyForm::new(c, q_params.clone()); - let m2 = cq.pow(&dq).retrieve(); + let m2 = cq.pow(dq).retrieve(); // (m1 - m2) mod p = (m1 mod p) - (m2 mod p) mod p let m2r = BoxedMontyForm::new(m2.clone(), p_params.clone()); @@ -200,7 +200,7 @@ fn unblind(m: &BoxedUint, unblinder: &BoxedUint, n_params: BoxedMontyParams) -> /// Computes `base.pow_mod(exp, n)` with precomputed `n_params`. fn pow_mod_params(base: &BoxedUint, exp: &BoxedUint, n_params: BoxedMontyParams) -> BoxedUint { - let base = reduce(&base, n_params); + let base = reduce(base, n_params); base.pow(exp).retrieve() } diff --git a/src/encoding.rs b/src/encoding.rs index 34860749..0084ac13 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -58,7 +58,7 @@ impl TryFrom> for RsaPrivateKey { let n = BoxedUint::from_be_slice(pkcs1_key.modulus.as_bytes(), bits) .map_err(|_| key_malformed)?; - let n = Option::from(Odd::new(n)).ok_or_else(|| key_malformed)?; + let n = Option::from(Odd::new(n)).ok_or(key_malformed)?; // exponent potentially needs padding let mut e_slice = [0u8; 8]; diff --git a/src/key.rs b/src/key.rs index 4cb52a94..1db11d78 100644 --- a/src/key.rs +++ b/src/key.rs @@ -140,7 +140,7 @@ impl From<&RsaPrivateKey> for RsaPublicKey { let n_params = PublicKeyParts::n_params(private_key); RsaPublicKey { n: n.clone(), - e: e.clone(), + e, n_params, } } @@ -547,7 +547,7 @@ impl PrivateKeyParts for RsaPrivateKey { /// Check that the public key is well formed and has an exponent within acceptable bounds. #[inline] pub fn check_public(public_key: &impl PublicKeyParts) -> Result<()> { - check_public_with_max_size(&public_key.n(), public_key.e(), RsaPublicKey::MAX_SIZE) + check_public_with_max_size(public_key.n(), public_key.e(), RsaPublicKey::MAX_SIZE) } /// Check that the public key is well formed and has an exponent within acceptable bounds. diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index 3ac3bdc0..b0f17dd4 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -214,7 +214,7 @@ fn verify(pub_key: &RsaPublicKey, prefix: &[u8], hashed: &[u8], sig: &BoxedUint) return Err(Error::Verification); } - let em = uint_to_be_pad(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; + let em = uint_to_be_pad(rsa_encrypt(pub_key, sig)?, pub_key.size())?; pkcs1v15_sign_unpad(prefix, hashed, &em, pub_key.size()) } diff --git a/src/pss.rs b/src/pss.rs index 855069d7..9a59ab1e 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -136,7 +136,7 @@ pub(crate) fn verify( return Err(Error::Verification); } - let mut em = uint_to_be_pad(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; + let mut em = uint_to_be_pad(rsa_encrypt(pub_key, sig)?, pub_key.size())?; emsa_pss_verify(hashed, &mut em, salt_len, digest, pub_key.n().bits() as _) } @@ -155,7 +155,7 @@ where return Err(Error::Verification); } - let mut em = uint_to_be_pad(rsa_encrypt(pub_key, &sig)?, pub_key.size())?; + let mut em = uint_to_be_pad(rsa_encrypt(pub_key, sig)?, pub_key.size())?; emsa_pss_verify_digest::(hashed, &mut em, salt_len, pub_key.n().bits() as _) } From 926e94736fecbdf641e0c8af629885953906857d Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 7 Jul 2024 16:22:55 +0200 Subject: [PATCH 46/51] pad pass keys --- src/pss.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/pss.rs b/src/pss.rs index 9a59ab1e..a7282ccf 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -281,17 +281,20 @@ mod test { // tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V // -----END RSA PRIVATE KEY----- - let bits = 512; - RsaPrivateKey::from_components( - Odd::new(BoxedUint::from_be_hex("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077", bits).unwrap()).unwrap(), - 65537, - BoxedUint::from_be_hex("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861", bits).unwrap(), - vec![ - BoxedUint::from_be_hex("98920366548084643601728869055592650835572950932266967461790948584315647051443",bits).unwrap(), - BoxedUint::from_be_hex("94560208308847015747498523884063394671606671904944666360068158221458669711639", bits).unwrap() - ], + let n= BoxedUint::from_be_hex("0000009353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077", 640).unwrap(); + let d= BoxedUint::from_be_hex("0000007266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861", 640).unwrap(); + let p = BoxedUint::from_be_hex( + "00098920366548084643601728869055592650835572950932266967461790948584315647051443", + 320, ) - .unwrap() + .unwrap(); + let q = BoxedUint::from_be_hex( + "00094560208308847015747498523884063394671606671904944666360068158221458669711639", + 320, + ) + .unwrap(); + + RsaPrivateKey::from_components(Odd::new(n).unwrap(), 65537, d, vec![p, q]).unwrap() } #[test] From f7477780bdab3eb19ec73258193b93482d4013f5 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 11 Aug 2024 13:14:22 +0200 Subject: [PATCH 47/51] fix recovery --- Cargo.lock | 84 +++++++++++++++++++++++++++++++++---------- Cargo.toml | 2 +- src/algorithms/rsa.rs | 48 +++++++++++++++---------- src/key.rs | 21 +++++------ 4 files changed, 104 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60b994d7..8e879cdd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "cbc" version = "0.1.2" @@ -121,9 +127,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.6.0-rc.0" +version = "0.6.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4d6fbc60a5516ff886af2c5994fb2bdfa6fbe2168468100bd87e6c09caf08c" +checksum = "e43027691f1c055da3da4f7d96af09fcec420d435d5616e51f29afd0811c56a7" dependencies = [ "num-traits", "rand_core", @@ -203,7 +209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -316,6 +322,12 @@ dependencies = [ "libm", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "pbkdf2" version = "0.12.2" @@ -375,9 +387,12 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" @@ -507,7 +522,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -544,18 +559,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97" dependencies = [ "proc-macro2", "quote", @@ -564,9 +579,9 @@ dependencies = [ [[package]] name = "serde_test" -version = "1.0.176" +version = "1.0.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a2f49ace1498612d14f7e0b8245519584db8299541dfe31a06374a828d620ab" +checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed" dependencies = [ "serde", ] @@ -652,9 +667,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.68" +version = "2.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "837a7e8026c6ce912ff01cefbe8cafc2f8010ac49682e2a3d9decc3bce1ecaaf" dependencies = [ "proc-macro2", "quote", @@ -663,14 +678,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -693,9 +709,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wait-timeout" @@ -721,6 +737,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -785,6 +810,27 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zeroize" version = "1.8.1" diff --git a/Cargo.toml b/Cargo.toml index c8672846..f3e489a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ pkcs8 = { version = "=0.11.0-pre.0", default-features = false, features = ["allo signature = { version = "=2.3.0-pre.3", default-features = false , features = ["alloc", "digest", "rand_core"] } spki = { version = "=0.8.0-pre.0", default-features = false, features = ["alloc"] } zeroize = { version = "1.5", features = ["alloc"] } -crypto-bigint = { version = "0.6.0-rc.0", default-features = false, features = ["zeroize", "alloc"] } +crypto-bigint = { version = "0.6.0-rc.2", default-features = false, features = ["zeroize", "alloc"] } crypto-primes = { version = "0.6.0-pre.0" } # optional dependencies diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 705db92d..0f4325aa 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -221,33 +221,41 @@ pub fn recover_primes( d: &BoxedUint, ) -> Result<(BoxedUint, BoxedUint)> { // Check precondition - if e <= 2u64.pow(16) || e >= 2u64.pow(256) { + + // Note: because e is at most u64::MAX, it is already + // known to be < 2**256 + if e <= 2u64.pow(16) { return Err(Error::InvalidArguments); } // 1. Let a = (de – 1) × GCD(n – 1, de – 1). - let one = BoxedUint::one(); - let e = BoxedUint::from(e); - - let a1 = d * &e - &one; - let a2 = (n.as_ref() - &one).gcd(&(d * e - &one)).unwrap(); + let bits = d.bits_precision() * 2; + let one = BoxedUint::one().widen(bits); + let e = BoxedUint::from(e).widen(bits); + let d = d.widen(bits); + let n = n.as_ref().widen(bits); + + let a1 = &d * &e - &one; + let a2 = (&n - &one).gcd(&a1); let a = a1 * a2; + let n = n.widen(a.bits_precision()); // 2. Let m = floor(a /n) and r = a – m n, so that a = m n + r and 0 ≤ r < n. - let m = &a / n; - let r = a - &m * n.as_ref(); + let m = &a / NonZero::new(n.clone()).expect("checked"); + let r = a - &m * &n; // 3. Let b = ( (n – r)/(m + 1) ) + 1; if b is not an integer or b^2 ≤ 4n, then output an error indicator, // and exit without further processing. - let modulus_check = (n.as_ref() - &r) % NonZero::new(&m + &one).unwrap(); + let modulus_check = (&n - &r) % NonZero::new(&m + &one).unwrap(); if (!modulus_check.is_zero()).into() { return Err(Error::InvalidArguments); } - let b = (n.as_ref() - &r) / NonZero::new((&m + &one) + one).unwrap(); + let b = ((&n - &r) / NonZero::new(&m + &one).unwrap()) + one; let four = BoxedUint::from(4u32); - let four_n = n.as_ref() * four; + let four_n = &n * four; let b_squared = b.square(); + if b_squared <= four_n { return Err(Error::InvalidArguments); } @@ -263,7 +271,8 @@ pub fn recover_primes( return Err(Error::InvalidArguments); } - let two = NonZero::new(BoxedUint::from(2u64)).unwrap(); + let bits = std::cmp::max(b.bits_precision(), y.bits_precision()); + let two = NonZero::new(BoxedUint::from(2u64)).unwrap().widen(bits); let p = (&b + &y) / &two; let q = (b - y) / two; @@ -323,9 +332,10 @@ pub(crate) fn compute_private_exponent_carmicheal( let q1 = q - &BoxedUint::one(); // LCM inlined - let gcd = p1.gcd(&q1).unwrap(); + let gcd = p1.gcd(&q1); let lcm = p1 / NonZero::new(gcd).unwrap() * &q1; - if let Some(d) = BoxedUint::from(exp).inv_mod(&lcm).into() { + let exp = BoxedUint::from(exp).widen(lcm.bits_precision()); + if let Some(d) = exp.inv_mod(&lcm).into() { Ok(d) } else { // `exp` evenly divides `lcm` @@ -339,13 +349,13 @@ mod tests { #[test] fn recover_primes_works() { - let bits = 512; + let bits = 2048; - let n = BoxedUint::from_be_hex("00d397b84d98a4c26138ed1b695a8106ead91d553bf06041b62d3fdc50a041e222b8f4529689c1b82c5e71554f5dd69fa2f4b6158cf0dbeb57811a0fc327e1f28e74fe74d3bc166c1eabdc1b8b57b934ca8be5b00b4f29975bcc99acaf415b59bb28a6782bb41a2c3c2976b3c18dbadef62f00c6bb226640095096c0cc60d22fe7ef987d75c6a81b10d96bf292028af110dc7cc1bbc43d22adab379a0cd5d8078cc780ff5cd6209dea34c922cf784f7717e428d75b5aec8ff30e5f0141510766e2e0ab8d473c84e8710b2b98227c3db095337ad3452f19e2b9bfbccdd8148abf6776fa552775e6e75956e45229ae5a9c46949bab1e622f0e48f56524a84ed3483b", bits).unwrap(); + let n = BoxedUint::from_be_hex("d397b84d98a4c26138ed1b695a8106ead91d553bf06041b62d3fdc50a041e222b8f4529689c1b82c5e71554f5dd69fa2f4b6158cf0dbeb57811a0fc327e1f28e74fe74d3bc166c1eabdc1b8b57b934ca8be5b00b4f29975bcc99acaf415b59bb28a6782bb41a2c3c2976b3c18dbadef62f00c6bb226640095096c0cc60d22fe7ef987d75c6a81b10d96bf292028af110dc7cc1bbc43d22adab379a0cd5d8078cc780ff5cd6209dea34c922cf784f7717e428d75b5aec8ff30e5f0141510766e2e0ab8d473c84e8710b2b98227c3db095337ad3452f19e2b9bfbccdd8148abf6776fa552775e6e75956e45229ae5a9c46949bab1e622f0e48f56524a84ed3483b", bits).unwrap(); let e = 65537; - let d = BoxedUint::from_be_hex("00c4e70c689162c94c660828191b52b4d8392115df486a9adbe831e458d73958320dc1b755456e93701e9702d76fb0b92f90e01d1fe248153281fe79aa9763a92fae69d8d7ecd144de29fa135bd14f9573e349e45031e3b76982f583003826c552e89a397c1a06bd2163488630d92e8c2bb643d7abef700da95d685c941489a46f54b5316f62b5d2c3a7f1bbd134cb37353a44683fdc9d95d36458de22f6c44057fe74a0a436c4308f73f4da42f35c47ac16a7138d483afc91e41dc3a1127382e0c0f5119b0221b4fc639d6b9c38177a6de9b526ebd88c38d7982c07f98a0efd877d508aae275b946915c02e2e1106d175d74ec6777f5e80d12c053d9c7be1e341", bits).unwrap(); - let p = BoxedUint::from_be_hex("00f827bbf3a41877c7cc59aebf42ed4b29c32defcb8ed96863d5b090a05a8930dd624a21c9dcf9838568fdfa0df65b8462a5f2ac913d6c56f975532bd8e78fb07bd405ca99a484bcf59f019bbddcb3933f2bce706300b4f7b110120c5df9018159067c35da3061a56c8635a52b54273b31271b4311f0795df6021e6355e1a42e61", bits).unwrap(); - let q = BoxedUint::from_be_hex("00da4817ce0089dd36f2ade6a3ff410c73ec34bf1b4f6bda38431bfede11cef1f7f6efa70e5f8063a3b1f6e17296ffb15feefa0912a0325b8d1fd65a559e717b5b961ec345072e0ec5203d03441d29af4d64054a04507410cf1da78e7b6119d909ec66e6ad625bf995b279a4b3c5be7d895cd7c5b9c4c497fde730916fcdb4e41b", bits).unwrap(); + let d = BoxedUint::from_be_hex("c4e70c689162c94c660828191b52b4d8392115df486a9adbe831e458d73958320dc1b755456e93701e9702d76fb0b92f90e01d1fe248153281fe79aa9763a92fae69d8d7ecd144de29fa135bd14f9573e349e45031e3b76982f583003826c552e89a397c1a06bd2163488630d92e8c2bb643d7abef700da95d685c941489a46f54b5316f62b5d2c3a7f1bbd134cb37353a44683fdc9d95d36458de22f6c44057fe74a0a436c4308f73f4da42f35c47ac16a7138d483afc91e41dc3a1127382e0c0f5119b0221b4fc639d6b9c38177a6de9b526ebd88c38d7982c07f98a0efd877d508aae275b946915c02e2e1106d175d74ec6777f5e80d12c053d9c7be1e341", bits).unwrap(); + let p = BoxedUint::from_be_hex("f827bbf3a41877c7cc59aebf42ed4b29c32defcb8ed96863d5b090a05a8930dd624a21c9dcf9838568fdfa0df65b8462a5f2ac913d6c56f975532bd8e78fb07bd405ca99a484bcf59f019bbddcb3933f2bce706300b4f7b110120c5df9018159067c35da3061a56c8635a52b54273b31271b4311f0795df6021e6355e1a42e61", bits / 2).unwrap(); + let q = BoxedUint::from_be_hex("da4817ce0089dd36f2ade6a3ff410c73ec34bf1b4f6bda38431bfede11cef1f7f6efa70e5f8063a3b1f6e17296ffb15feefa0912a0325b8d1fd65a559e717b5b961ec345072e0ec5203d03441d29af4d64054a04507410cf1da78e7b6119d909ec66e6ad625bf995b279a4b3c5be7d895cd7c5b9c4c497fde730916fcdb4e41b", bits / 2).unwrap(); let (mut p1, mut q1) = recover_primes(&NonZero::new(n).unwrap(), e, &d).unwrap(); diff --git a/src/key.rs b/src/key.rs index 1db11d78..5c38c162 100644 --- a/src/key.rs +++ b/src/key.rs @@ -865,17 +865,14 @@ mod tests { e_raw[..e.len()].copy_from_slice(&e); let e = u64::from_be_bytes(e_raw); - let bits = 512; - RsaPrivateKey::from_components( - Odd::new(BoxedUint::from_be_slice(&n, bits).unwrap()).unwrap(), - e, - BoxedUint::from_be_slice(&d, bits).unwrap(), - primes - .iter() - .map(|p| BoxedUint::from_be_slice(p, bits).unwrap()) - .collect(), - ) - .unwrap(); + let bits = 4096; + let n = Odd::new(BoxedUint::from_be_slice(&n, bits).unwrap()).unwrap(); + let d = BoxedUint::from_be_slice(&d, bits).unwrap(); + let primes = primes + .iter() + .map(|p| BoxedUint::from_be_slice(p, bits / 2).unwrap()) + .collect(); + RsaPrivateKey::from_components(n, e, d, primes).unwrap(); } #[test] @@ -942,7 +939,7 @@ mod tests { 1b6db7f88268aaf89f0b33b905d72c25338b13e61a51873c2d427021a3f29207 179ad32f423793f0c090dda025ce41df0e94afbc80ab5eda9b1a268aa2553a99" ), - 4096, + 2 * 4096, ) .unwrap(); From bfba03afde145273f5c6cb227778abf575624937 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 11 Aug 2024 13:18:27 +0200 Subject: [PATCH 48/51] disable slow tests for now --- src/algorithms/generate.rs | 3 ++- src/key.rs | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/algorithms/generate.rs b/src/algorithms/generate.rs index dae13294..93f33630 100644 --- a/src/algorithms/generate.rs +++ b/src/algorithms/generate.rs @@ -158,5 +158,6 @@ mod tests { key_generation!(key_generation_multi_5_64, 5, 64); key_generation!(key_generation_multi_8_576, 8, 576); - key_generation!(key_generation_multi_16_1024, 16, 1024); + // TODO: reenable, currently slow + // key_generation!(key_generation_multi_16_1024, 16, 1024); } diff --git a/src/key.rs b/src/key.rs index 5c38c162..b962ae22 100644 --- a/src/key.rs +++ b/src/key.rs @@ -721,7 +721,8 @@ mod tests { key_generation!(key_generation_multi_5_64, 5, 64); key_generation!(key_generation_multi_8_576, 8, 576); - key_generation!(key_generation_multi_16_1024, 16, 1024); + // TODO: reenable, currently slow + // key_generation!(key_generation_multi_16_1024, 16, 1024); #[test] fn test_negative_decryption_value() { @@ -939,7 +940,7 @@ mod tests { 1b6db7f88268aaf89f0b33b905d72c25338b13e61a51873c2d427021a3f29207 179ad32f423793f0c090dda025ce41df0e94afbc80ab5eda9b1a268aa2553a99" ), - 2 * 4096, + 8192, ) .unwrap(); From 7da4ec2ffae2bc14304533375f386eb2f796da09 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 11 Aug 2024 14:06:00 +0200 Subject: [PATCH 49/51] fix most pss tests --- src/pss.rs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/pss.rs b/src/pss.rs index a7282ccf..6b40b3a9 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -262,8 +262,8 @@ mod test { use crate::pss::{BlindedSigningKey, Pss, Signature, SigningKey, VerifyingKey}; use crate::{RsaPrivateKey, RsaPublicKey}; - use crypto_bigint::{BoxedUint, Odd}; use hex_literal::hex; + use pkcs1::DecodeRsaPrivateKey; use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; use sha1::{Digest, Sha1}; use signature::hazmat::{PrehashVerifier, RandomizedPrehashSigner}; @@ -281,20 +281,18 @@ mod test { // tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V // -----END RSA PRIVATE KEY----- - let n= BoxedUint::from_be_hex("0000009353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077", 640).unwrap(); - let d= BoxedUint::from_be_hex("0000007266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861", 640).unwrap(); - let p = BoxedUint::from_be_hex( - "00098920366548084643601728869055592650835572950932266967461790948584315647051443", - 320, - ) - .unwrap(); - let q = BoxedUint::from_be_hex( - "00094560208308847015747498523884063394671606671904944666360068158221458669711639", - 320, - ) - .unwrap(); - - RsaPrivateKey::from_components(Odd::new(n).unwrap(), 65537, d, vec![p, q]).unwrap() + let pem = r#" +-----BEGIN RSA PRIVATE KEY----- +MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 +fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu +/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu +RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/ +EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A +IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS +tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V +-----END RSA PRIVATE KEY-----"#; + + RsaPrivateKey::from_pkcs1_pem(pem).unwrap() } #[test] @@ -324,6 +322,7 @@ mod test { for (text, sig, expected) in &tests { let digest = Sha1::digest(text.as_bytes()).to_vec(); let result = pub_key.verify(Pss::new::(), &digest, sig); + match expected { true => result.expect("failed to verify"), false => { From f61ed754deda583f1d92351787ee68335021b7b0 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 11 Aug 2024 15:02:34 +0200 Subject: [PATCH 50/51] fix proptest --- src/algorithms/rsa.rs | 3 ++- tests/proptests.proptest-regressions | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/proptests.proptest-regressions diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 0f4325aa..b4ece553 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -98,10 +98,11 @@ pub fn rsa_decrypt( m.0 }; + // Ensure output precision matches input precision + let m = m.shorten(n_params.bits_precision()); match ir { Some(ref ir) => { // unblind - let m = m.shorten(n_params.bits_precision()); let res = unblind(&m, ir, n_params); Ok(res) } diff --git a/tests/proptests.proptest-regressions b/tests/proptests.proptest-regressions new file mode 100644 index 00000000..145a36aa --- /dev/null +++ b/tests/proptests.proptest-regressions @@ -0,0 +1,7 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 6eb8993a76d99005d1cb0f3d848d5390c3e0f4f2de4a7517eccfb477f74e13a0 # shrinks to private_key = RsaPrivateKey { pubkey_components: RsaPublicKey { n: NonZero(BoxedUint(0x8347C96BF9CDBB267650CB931400D5091139DB988E11C5AAF9EAC86BA5D4EA3EEBA0569077555B3FA4CE0D41300461BF8926A34B7993A48B1F3F69CAB3158DFB)), e: 65537, n_params: BoxedMontyParams { modulus: Odd(BoxedUint(0x8347C96BF9CDBB267650CB931400D5091139DB988E11C5AAF9EAC86BA5D4EA3EEBA0569077555B3FA4CE0D41300461BF8926A34B7993A48B1F3F69CAB3158DFB)), one: BoxedUint(0x7CB83694063244D989AF346CEBFF2AF6EEC6246771EE3A55061537945A2B15C1145FA96F88AAA4C05B31F2BECFFB9E4076D95CB4866C5B74E0C096354CEA7205), r2: BoxedUint(0x70E018F6DD63DB9D8182776C303A6B688E9D44CEE054FF801E11E9DEA040862E9E8EC3E4CC0FF3B0D573D09C381621AB35B7C6CDC49098E583F643AAC2238D65), r3: BoxedUint(0x1ADF6E5E9A880615C0CC586BB70BA0D657CF3F1624A68671A192471E75F4CD56A401C11B483909871F0FA8554275EA17ABA04BE17F88AF9B749F44D591277079), mod_neg_inv: Limb(0xD0EBDD5E695C8ACD) } }, d: BoxedUint(0x00000000000000000000000000000000000000000000000000000000000000002F08B129763E3726F88CC9E2CFEFDC637B40776498C1D5480472118C3FC5A08694CCAE7DCBFD25B7850C79332F5F100111BEED9DC0A7B8D8C37EB657E4985081), primes: [BoxedUint(0x981BE188EF711A1E2C840EC3CE9A7F3B7F5BB8E81F09A5A13E00EF2F895F4213), BoxedUint(0xDCF20F8FD566A26BC0FD581259F9A2AABF0ADB6C01F2A5ADD2AEFA0DEAA5C179)], precomputed: Some(PrecomputedValues { dp: BoxedUint(0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000053084D3A51F2BC9E2210C87A8CCA7B8FBFFB12D9EB2F79F1A6061E8B2583116F), dq: BoxedUint(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007056BB46DCB044A1190D373C8D76FA186AEE7046686F218251FF19B0FDBFADB1), qinv: BoxedMontyForm { montgomery_form: BoxedUint(0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000682511332F037EAFDE67A19620CFDC9961A7FF261F4F185D49E5EF21E2686753), params: BoxedMontyParams { modulus: Odd(BoxedUint(0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000981BE188EF711A1E2C840EC3CE9A7F3B7F5BB8E81F09A5A13E00EF2F895F4213)), one: BoxedUint(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006BB5F6A9EDD4349E0EF3418B86FD1D88DAF170653B6F050CAD2062140743E1EE), r2: BoxedUint(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003C67CD14A702D9D3E7D7790AE0DB96B7E2DA351552A50382262CF0D0BB51E17D), r3: BoxedUint(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C83D6B4CE99FAFBB23D7586BA520C62B5206D43755A767BEBB5764A015BF27D), mod_neg_inv: Limb(0xC61D8CFC698327E5) } }, p_params: BoxedMontyParams { modulus: Odd(BoxedUint(0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000981BE188EF711A1E2C840EC3CE9A7F3B7F5BB8E81F09A5A13E00EF2F895F4213)), one: BoxedUint(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006BB5F6A9EDD4349E0EF3418B86FD1D88DAF170653B6F050CAD2062140743E1EE), r2: BoxedUint(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003C67CD14A702D9D3E7D7790AE0DB96B7E2DA351552A50382262CF0D0BB51E17D), r3: BoxedUint(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C83D6B4CE99FAFBB23D7586BA520C62B5206D43755A767BEBB5764A015BF27D), mod_neg_inv: Limb(0xC61D8CFC698327E5) }, q_params: BoxedMontyParams { modulus: Odd(BoxedUint(0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000DCF20F8FD566A26BC0FD581259F9A2AABF0ADB6C01F2A5ADD2AEFA0DEAA5C179)), one: BoxedUint(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007FFB34771D54239EC9DEDC1D2108D7D70D73B05E764B8E38EEE1014C49C29BF5), r2: BoxedUint(0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A29B3272D65244B833205BCB2F0670190F04A5C945B416487C3F470C9A6126F6), r3: BoxedUint(0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033E334261962415DBDE417A3E2844C84E5252176396B638A3873E3B5A75352DE), mod_neg_inv: Limb(0x6092436DE4BA2737) } }) }, msg = [] From 74d319718699aa1553e36ea592bd2bbe07083023 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 11 Aug 2024 15:18:58 +0200 Subject: [PATCH 51/51] fixup --- src/algorithms/rsa.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index b4ece553..9e2f37d9 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -272,7 +272,7 @@ pub fn recover_primes( return Err(Error::InvalidArguments); } - let bits = std::cmp::max(b.bits_precision(), y.bits_precision()); + let bits = core::cmp::max(b.bits_precision(), y.bits_precision()); let two = NonZero::new(BoxedUint::from(2u64)).unwrap().widen(bits); let p = (&b + &y) / &two; let q = (b - y) / two;