From a841265765bc37beffca052db7b1f08275624151 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 8 Nov 2026 14:28:52 -0700 Subject: [PATCH] Bump `crypto-bigint` to v0.7.11 This release includes security and performance enhancements. It also deprecates `bits(_vartime)` in favor of the new `std`-aligned `bit_width(_vartime)` which is updated in this commit. --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/algorithms/generate.rs | 6 +++--- src/algorithms/rsa.rs | 4 ++-- src/encoding.rs | 4 ++-- src/private_key.rs | 9 +++++---- src/pss.rs | 12 ++++++------ src/public_key.rs | 4 ++-- src/traits/keys.rs | 2 +- tests/generate.rs | 2 +- 10 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4f56add..1fad3096 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -281,9 +281,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c035cb64cba03dad2fb921f3e218785e8cf9a41790da5eb3a1400f62fa2be11" +checksum = "914c195c4d7fbc5ed7f88d14cbf85914d5c664967658d43404b263913a477e82" dependencies = [ "cpubits", "ctutils", @@ -326,9 +326,9 @@ dependencies = [ [[package]] name = "ctutils" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2376ffd6f96d8a9db59875b4b6b0237d6900b5baf64279714e05493ce64828a" +checksum = "261af4dc7a06ea8a527a8717d8cbba3417530d6ea14e1edb3de6b67806be474f" dependencies = [ "cmov", ] diff --git a/Cargo.toml b/Cargo.toml index 12ecf524..0dae1aee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ default-members = ["."] resolver = "3" [workspace.dependencies] -crypto-bigint = { version = "0.7.10", default-features = false, features = ["zeroize", "alloc"] } +crypto-bigint = { version = "0.7.11", default-features = false, features = ["zeroize", "alloc"] } rand = "0.10" rand_core = { version = "0.10", default-features = false } zeroize = { version = "1.8", default-features = false, features = ["alloc"] } diff --git a/src/algorithms/generate.rs b/src/algorithms/generate.rs index 2f8b7e78..4ca54581 100644 --- a/src/algorithms/generate.rs +++ b/src/algorithms/generate.rs @@ -87,12 +87,12 @@ 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).map_err(|_| Error::Rng)?; - todo -= prime.bits() as usize; + todo -= prime.bit_width() as usize; } let n = compute_modulus(&primes); - if n.bits() as usize != bit_size { + if n.bit_width() as usize != bit_size { // This should never happen for nprimes == 2 because // generate_prime_with_rng should set the top two bits in each prime. // For nprimes > 2 we hope it does not happen often. @@ -180,7 +180,7 @@ mod tests { let components = generate_multi_prime_key_with_exp(&mut rng, $multi, $size, exp.clone()) .unwrap(); - assert_eq!(components.n.bits(), $size); + assert_eq!(components.n.bit_width(), $size); assert_eq!(components.primes.len(), $multi); } } diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 2d61f732..6ab2740b 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -33,7 +33,7 @@ use crate::traits::keys::{PrivateKeyParts, PublicKeyParts}; #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn rsa_encrypt(key: &K, m: &BoxedUint) -> Result { let e = key.e(); - let res = pow_mod_params_vartime_exp_bits(m, e, e.bits(), key.n_params()); + let res = pow_mod_params_vartime_exp_bits(m, e, e.bit_width(), key.n_params()); Ok(res) } @@ -229,7 +229,7 @@ fn blind( let blinded = { // r^e (mod n) let e = key.e(); - let mut rpowe = pow_mod_params_vartime_exp_bits(&r, e, e.bits(), n_params); + let mut rpowe = pow_mod_params_vartime_exp_bits(&r, e, e.bit_width(), n_params); // c * r^e (mod n) let c = c.mul_mod(&rpowe, n_params.modulus().as_nz_ref()); rpowe.zeroize(); diff --git a/src/encoding.rs b/src/encoding.rs index 65089f00..86de7a90 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -104,8 +104,8 @@ impl pkcs1::EncodeRsaPrivateKey for PrivateKey { let bits = self.d().bits_precision(); - debug_assert!(bits >= self.primes[0].bits_vartime()); - debug_assert!(bits >= self.primes[1].bits_vartime()); + debug_assert!(bits >= self.primes[0].bit_width_vartime()); + debug_assert!(bits >= self.primes[1].bit_width_vartime()); let exponent1 = Zeroizing::new( (self.d() diff --git a/src/private_key.rs b/src/private_key.rs index da553bb5..d0252180 100644 --- a/src/private_key.rs +++ b/src/private_key.rs @@ -241,7 +241,7 @@ impl PrivateKey { // The modulus may come in padded with zeros, shorten it // to ensure optimal performance of arithmetic operations. - let n_bits = n.bits_vartime(); + let n_bits = n.bit_width_vartime(); let n = n.resize_unchecked(n_bits); // Use a public storage width even when the caller supplies a short or zero-padded `d`. @@ -290,7 +290,7 @@ impl PrivateKey { let primes = primes .into_iter() .map(|p| { - if p.bits() > prime_bits { + if p.bit_width() > prime_bits { return Err(Error::InvalidPrime); } @@ -1059,7 +1059,8 @@ mod tests { .unwrap(); assert_eq!(key.d(), &d); let prime_precision = - BoxedUint::zero_with_precision(key.n().bits().div_ceil(2)).bits_precision(); + BoxedUint::zero_with_precision(key.n().bit_width().div_ceil(2)) + .bits_precision(); for prime in key.primes() { assert_eq!(prime.bits_precision(), prime_precision); } @@ -1115,7 +1116,7 @@ mod tests { components.primes, ) .unwrap(); - assert_eq!(PublicKeyParts::n(&private_key).bits(), $size); + assert_eq!(PublicKeyParts::n(&private_key).bit_width(), $size); test_key_basics(&private_key); } diff --git a/src/pss.rs b/src/pss.rs index 7ac5393c..ab2db2ef 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -263,7 +263,7 @@ where D: Digest + FixedOutputReset, { let mut em = decode_signature(pub_key, sig)?; - let em_bits = pub_key.n().bits() as usize - 1; + let em_bits = pub_key.n().bit_width() as usize - 1; emsa_pss_verify(hashed, &mut em, salt_len, digest, em_bits) } @@ -277,7 +277,7 @@ where D: Digest + FixedOutputReset, { let mut em = decode_signature(pub_key, sig)?; - let em_bits = pub_key.n().bits() as usize - 1; + let em_bits = pub_key.n().bit_width() as usize - 1; emsa_pss_verify_digest::(hashed, &mut em, salt_len, em_bits) } @@ -299,9 +299,9 @@ fn decode_signature(pub_key: &PublicKey, signature: &[u8]) -> Result> { // // Check the public representative's width before calling infallible I2OSP; discarding a nonzero // leading octet is invalid. - let em_bits = pub_key.n().bits() as usize - 1; + let em_bits = pub_key.n().bit_width() as usize - 1; let em_len = em_bits.div_ceil(8); - if m.bits() as usize > 8 * em_len { + if m.bit_width() as usize > 8 * em_len { return Err(Error::Verification); } Ok(i2osp(m, em_len)) @@ -363,7 +363,7 @@ where T: TryCryptoRng + ?Sized, D: Digest + FixedOutputReset, { - let em_bits = priv_key.n().bits() - 1; + let em_bits = priv_key.n().bit_width() - 1; let em = emsa_pss_encode(hashed, em_bits as _, salt, digest)?; @@ -382,7 +382,7 @@ where T: TryCryptoRng + ?Sized, D: Digest + FixedOutputReset, { - let em_bits = priv_key.n().bits() - 1; + let em_bits = priv_key.n().bit_width() - 1; let em = emsa_pss_encode_digest::(hashed, em_bits as _, salt)?; let em = os2ip(&em, priv_key.n_bits_precision())?; diff --git a/src/public_key.rs b/src/public_key.rs index 877b7f0c..67b072f5 100644 --- a/src/public_key.rs +++ b/src/public_key.rs @@ -111,7 +111,7 @@ impl PublicKey { return Err(Error::InvalidArguments); } - if (n.bits_vartime() as usize) < *size_range_bits.start() { + if (n.bit_width_vartime() as usize) < *size_range_bits.start() { return Err(Error::ModulusTooSmall); } @@ -232,7 +232,7 @@ pub(crate) fn check_public(public_key: &impl PublicKeyParts) -> Result<()> { #[inline] fn check_public_with_max_size(n: &BoxedUint, e: &BoxedUint, max_size: Option) -> Result<()> { if let Some(max_size) = max_size { - if n.bits_vartime() as usize > max_size { + if n.bit_width_vartime() as usize > max_size { return Err(Error::ModulusTooLarge); } } diff --git a/src/traits/keys.rs b/src/traits/keys.rs index 607bacd2..bf48c620 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -21,7 +21,7 @@ pub trait PublicKeyParts { /// Ciphertexts and signatures have this length, including any leading zero octets. /// This may be smaller than the modulus's allocated storage width. fn size(&self) -> usize { - (self.n().bits() as usize).div_ceil(8) + (self.n().bit_width() as usize).div_ceil(8) } /// Returns the parameters for montgomery operations. diff --git a/tests/generate.rs b/tests/generate.rs index 34f58838..004e3344 100644 --- a/tests/generate.rs +++ b/tests/generate.rs @@ -17,7 +17,7 @@ fn rng() -> ChaCha8Rng { fn check_key(key: &PrivateKey) { assert_eq!(PrivateKey::DEFAULT_BITS, 3072); - assert_eq!(key.n().bits(), 3072); + assert_eq!(key.n().bit_width(), 3072); assert_eq!(key.e(), &BoxedUint::from(65537u64)); assert_eq!(key.primes().len(), 2); assert_ne!(key.primes()[0], key.primes()[1]);