From 9f4eb661d9a2cc6e9794dd9d7f6340c63c45c384 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Mon, 19 Jan 2026 13:17:58 -0800 Subject: [PATCH] rand_core: upcoming API breaks A recent change in the upcoming rand_core 0.10.0-rc-4 dropped the implied `CryptoRng: RngCore` from the trait. This forces any consumer to make the requirement explicit. This commit prepares for that. --- cms/src/builder.rs | 34 +++++++++++++------------ cms/src/builder/kari.rs | 7 +++-- cms/tests/builder.rs | 9 ++++--- phc/src/salt.rs | 10 ++++---- pkcs5/src/pbes2.rs | 8 +++--- pkcs8/src/encrypted_private_key_info.rs | 7 +++-- pkcs8/src/private_key_info.rs | 7 +++-- pkcs8/src/traits.rs | 9 ++++--- x509-cert/src/builder.rs | 7 ++--- x509-cert/src/serial_number.rs | 9 ++++--- x509-ocsp/src/builder/request.rs | 4 +-- x509-ocsp/src/builder/response.rs | 4 +-- x509-ocsp/src/ext.rs | 4 +-- 13 files changed, 68 insertions(+), 51 deletions(-) diff --git a/cms/src/builder.rs b/cms/src/builder.rs index b81367bfd..c79fb824e 100644 --- a/cms/src/builder.rs +++ b/cms/src/builder.rs @@ -26,8 +26,10 @@ use alloc::{ vec::Vec, }; use cipher::{ - BlockModeEncrypt, Iv, Key, KeyIvInit, block_padding::Pkcs7, crypto_common::Generate, - rand_core::CryptoRng, + BlockModeEncrypt, Iv, Key, KeyIvInit, + block_padding::Pkcs7, + crypto_common::Generate, + rand_core::{CryptoRng, RngCore}, }; use const_oid::ObjectIdentifier; use core::{cmp::Ordering, fmt, marker::PhantomData}; @@ -437,7 +439,7 @@ impl<'s> SignedDataBuilder<'s> { S: RandomizedSigner, S::VerifyingKey: EncodePublicKey, Signature: SignatureBitStringEncoding, - R: CryptoRng + ?Sized, + R: CryptoRng + RngCore + ?Sized, { let signer_info = signer_info_builder .build_with_rng::(signer, rng) @@ -482,7 +484,7 @@ impl<'s> SignedDataBuilder<'s> { S: AsyncRandomizedSigner, S::VerifyingKey: EncodePublicKey, Signature: SignatureBitStringEncoding, - R: CryptoRng + ?Sized, + R: CryptoRng + RngCore + ?Sized, { let signer_info = signer_info_builder .build_with_rng_async::(signer, rng) @@ -606,7 +608,7 @@ impl<'s> SignedDataBuilder<'s> { /// formats. All implementations must implement this trait. pub trait RecipientInfoBuilder { /// Associated Rng type - type Rng: CryptoRng + ?Sized; + type Rng: CryptoRng + RngCore + ?Sized; /// Return the recipient info type fn recipient_info_type(&self) -> RecipientInfoType; @@ -668,9 +670,9 @@ impl KeyTransRecipientInfoBuilder { } } -impl RecipientInfoBuilder for KeyTransRecipientInfoBuilder +impl RecipientInfoBuilder for KeyTransRecipientInfoBuilder where - R: CryptoRng, + R: CryptoRng + RngCore + ?Sized, { type Rng = R; @@ -739,9 +741,9 @@ impl KekRecipientInfoBuilder { } } -impl RecipientInfoBuilder for KekRecipientInfoBuilder +impl RecipientInfoBuilder for KekRecipientInfoBuilder where - R: CryptoRng, + R: CryptoRng + RngCore + ?Sized, { type Rng = R; @@ -782,7 +784,7 @@ pub trait PwriEncryptor { /// including eventual parameters (e.g. the used iv). fn key_encryption_algorithm(&self) -> Result; /// Encrypt the padded content-encryption key twice following RFC 3211, § 2.3.1 - fn encrypt_rfc3211( + fn encrypt_rfc3211( &mut self, padded_content_encryption_key: &[u8], rng: &mut R, @@ -830,10 +832,10 @@ where } } -impl PasswordRecipientInfoBuilder +impl PasswordRecipientInfoBuilder where P: PwriEncryptor, - R: CryptoRng, + R: CryptoRng + RngCore + ?Sized, { /// Wrap the content-encryption key according to [RFC 3211, §2.3.1]: /// .... @@ -874,7 +876,7 @@ where impl RecipientInfoBuilder for PasswordRecipientInfoBuilder where P: PwriEncryptor, - R: CryptoRng + ?Sized, + R: CryptoRng + RngCore + ?Sized, { type Rng = R; @@ -933,7 +935,7 @@ impl OtherRecipientInfoBuilder { impl RecipientInfoBuilder for OtherRecipientInfoBuilder where - R: CryptoRng + ?Sized, + R: CryptoRng + RngCore + ?Sized, { type Rng = R; @@ -1017,7 +1019,7 @@ impl<'c, R> EnvelopedDataBuilder<'c, R> { impl<'c, R> EnvelopedDataBuilder<'c, R> where - R: CryptoRng + ?Sized, + R: CryptoRng + RngCore + ?Sized, { /// Add recipient info. A builder is used, which generates a `RecipientInfo` according to /// RFC 5652 § 6.2, when `EnvelopedData` is built. @@ -1214,7 +1216,7 @@ fn encrypt_data( rng: &mut R, ) -> Result<(Vec, Vec, AlgorithmIdentifierOwned)> where - R: CryptoRng + ?Sized, + R: CryptoRng + RngCore + ?Sized, { match encryption_algorithm_identifier { ContentEncryptionAlgorithm::Aes128Cbc => encrypt_block_mode!( diff --git a/cms/src/builder/kari.rs b/cms/src/builder/kari.rs index cd9586851..15760c5fb 100644 --- a/cms/src/builder/kari.rs +++ b/cms/src/builder/kari.rs @@ -8,7 +8,7 @@ // Super imports use super::{ - AlgorithmIdentifierOwned, CryptoRng, RecipientInfoBuilder, RecipientInfoType, Result, + AlgorithmIdentifierOwned, CryptoRng, RecipientInfoBuilder, RecipientInfoType, Result, RngCore, UserKeyingMaterial, utils::kw::{KeyWrapAlgorithm, WrappedKey}, }; @@ -250,10 +250,9 @@ where }) } } -impl RecipientInfoBuilder - for KeyAgreeRecipientInfoBuilder +impl RecipientInfoBuilder for KeyAgreeRecipientInfoBuilder where - R: CryptoRng, + R: CryptoRng + RngCore + ?Sized, KA: KeyAgreementAlgorithm + AssociatedOid, C: CurveArithmetic + AssociatedOid + PointCompression, AffinePoint: FromEncodedPoint + ToEncodedPoint, diff --git a/cms/tests/builder.rs b/cms/tests/builder.rs index 9c36c089b..eae6ac47c 100644 --- a/cms/tests/builder.rs +++ b/cms/tests/builder.rs @@ -23,7 +23,7 @@ use pem_rfc7468::LineEnding; use pkcs5::pbes2::Pbkdf2Params; use rand::rngs::SysRng; use rsa::pkcs1::DecodeRsaPrivateKey; -use rsa::rand_core::{CryptoRng, TryRngCore}; +use rsa::rand_core::{CryptoRng, RngCore, TryRngCore}; use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey}; use rsa::{pkcs1v15, pss}; use sha2::Sha256; @@ -690,7 +690,10 @@ fn test_create_password_recipient_info() { key_derivation_params: pkcs5::pbes2::Pbkdf2Params, } impl<'a> Aes128CbcPwriEncryptor<'a> { - pub fn new(challenge_password: &'a [u8], rng: &mut R) -> Self { + pub fn new( + challenge_password: &'a [u8], + rng: &mut R, + ) -> Self { let mut key_encryption_iv = [0u8; 16]; rng.fill_bytes(key_encryption_iv.as_mut_slice()); let key_encryption_iv = key_encryption_iv.into(); @@ -708,7 +711,7 @@ fn test_create_password_recipient_info() { } impl PwriEncryptor for Aes128CbcPwriEncryptor<'_> { const BLOCK_LENGTH_BITS: usize = 128; // AES block length - fn encrypt_rfc3211( + fn encrypt_rfc3211( &mut self, padded_content_encryption_key: &[u8], _rng: &mut R, diff --git a/phc/src/salt.rs b/phc/src/salt.rs index 98e5fb978..086140d82 100644 --- a/phc/src/salt.rs +++ b/phc/src/salt.rs @@ -8,7 +8,7 @@ use core::{ str::{self, FromStr}, }; #[cfg(feature = "rand_core")] -use rand_core::{CryptoRng, TryCryptoRng}; +use rand_core::{CryptoRng, RngCore, TryCryptoRng, TryRngCore}; /// Error message used with `expect` for when internal invariants are violated /// (i.e. the contents of a [`Salt`] should always be valid) @@ -117,14 +117,14 @@ impl Salt { /// Generate a random [`Salt`] from the given [`CryptoRng`]. #[cfg(feature = "rand_core")] - pub fn from_rng(rng: &mut R) -> Self { + pub fn from_rng(rng: &mut R) -> Self { let Ok(out) = Self::try_from_rng(rng); out } /// Generate a random [`Salt`] from the given [`TryCryptoRng`]. #[cfg(feature = "rand_core")] - pub fn try_from_rng( + pub fn try_from_rng( rng: &mut R, ) -> core::result::Result { let mut bytes = [0u8; Self::RECOMMENDED_LENGTH]; @@ -256,14 +256,14 @@ impl SaltString { /// Generate a random B64-encoded [`SaltString`] from [`CryptoRng`]. #[cfg(feature = "rand_core")] - pub fn from_rng(rng: &mut R) -> Self { + pub fn from_rng(rng: &mut R) -> Self { let Ok(out) = Self::try_from_rng(rng); out } /// Generate a random B64-encoded [`SaltString`] from [`TryCryptoRng`]. #[cfg(feature = "rand_core")] - pub fn try_from_rng( + pub fn try_from_rng( rng: &mut R, ) -> core::result::Result { Ok(Salt::try_from_rng(rng)?.to_salt_string()) diff --git a/pkcs5/src/pbes2.rs b/pkcs5/src/pbes2.rs index 29b8bfce0..86b7fa5b3 100644 --- a/pkcs5/src/pbes2.rs +++ b/pkcs5/src/pbes2.rs @@ -19,7 +19,7 @@ use der::{ }; #[cfg(feature = "rand_core")] -use rand_core::CryptoRng; +use rand_core::{CryptoRng, RngCore}; #[cfg(all(feature = "alloc", feature = "pbes2"))] use alloc::vec::Vec; @@ -106,7 +106,7 @@ impl Parameters { /// This is currently an alias for [`Parameters::scrypt`]. See that method /// for more information. #[cfg(all(feature = "pbes2", feature = "rand_core"))] - pub fn recommended(rng: &mut R) -> Self { + pub fn recommended(rng: &mut R) -> Self { Self::scrypt(rng) } @@ -118,7 +118,7 @@ impl Parameters { /// This will use AES-256-CBC as the encryption algorithm and SHA-256 as /// the hash function for PBKDF2. #[cfg(feature = "rand_core")] - pub fn pbkdf2(rng: &mut R) -> Self { + pub fn pbkdf2(rng: &mut R) -> Self { let mut iv = [0u8; Self::DEFAULT_IV_LEN]; rng.fill_bytes(&mut iv); @@ -169,7 +169,7 @@ impl Parameters { /// /// [RustCrypto/formats#1205]: https://github.com/RustCrypto/formats/issues/1205 #[cfg(all(feature = "pbes2", feature = "rand_core"))] - pub fn scrypt(rng: &mut R) -> Self { + pub fn scrypt(rng: &mut R) -> Self { let mut iv = [0u8; Self::DEFAULT_IV_LEN]; rng.fill_bytes(&mut iv); diff --git a/pkcs8/src/encrypted_private_key_info.rs b/pkcs8/src/encrypted_private_key_info.rs index 1f84c1f2c..1be7622f4 100644 --- a/pkcs8/src/encrypted_private_key_info.rs +++ b/pkcs8/src/encrypted_private_key_info.rs @@ -12,7 +12,10 @@ use pkcs5::EncryptionScheme; use der::{SecretDocument, asn1::OctetString}; #[cfg(feature = "encryption")] -use {pkcs5::pbes2, rand_core::CryptoRng}; +use { + pkcs5::pbes2, + rand_core::{CryptoRng, RngCore}, +}; #[cfg(feature = "pem")] use der::pem::PemLabel; @@ -64,7 +67,7 @@ where /// Encrypt the given ASN.1 DER document using a symmetric encryption key /// derived from the provided password. #[cfg(feature = "encryption")] - pub(crate) fn encrypt( + pub(crate) fn encrypt( rng: &mut R, password: impl AsRef<[u8]>, doc: &[u8], diff --git a/pkcs8/src/private_key_info.rs b/pkcs8/src/private_key_info.rs index e41a7a28e..cb0d02833 100644 --- a/pkcs8/src/private_key_info.rs +++ b/pkcs8/src/private_key_info.rs @@ -17,7 +17,10 @@ use der::{ #[cfg(feature = "encryption")] use { - crate::EncryptedPrivateKeyInfoRef, der::zeroize::Zeroizing, pkcs5::pbes2, rand_core::CryptoRng, + crate::EncryptedPrivateKeyInfoRef, + der::zeroize::Zeroizing, + pkcs5::pbes2, + rand_core::{CryptoRng, RngCore}, }; #[cfg(feature = "pem")] @@ -148,7 +151,7 @@ where /// - p: 1 /// - Cipher: AES-256-CBC (best available option for PKCS#5 encryption) #[cfg(feature = "encryption")] - pub fn encrypt( + pub fn encrypt( &self, rng: &mut R, password: impl AsRef<[u8]>, diff --git a/pkcs8/src/traits.rs b/pkcs8/src/traits.rs index 394089ee3..51da2e255 100644 --- a/pkcs8/src/traits.rs +++ b/pkcs8/src/traits.rs @@ -6,7 +6,10 @@ use crate::{Error, PrivateKeyInfoRef, Result}; use der::SecretDocument; #[cfg(feature = "encryption")] -use {crate::EncryptedPrivateKeyInfoRef, rand_core::CryptoRng}; +use { + crate::EncryptedPrivateKeyInfoRef, + rand_core::{CryptoRng, RngCore}, +}; #[cfg(feature = "pem")] use { @@ -101,7 +104,7 @@ pub trait EncodePrivateKey { /// Create an [`SecretDocument`] containing the ciphertext of /// a PKCS#8 encoded private key encrypted under the given `password`. #[cfg(feature = "encryption")] - fn to_pkcs8_encrypted_der( + fn to_pkcs8_encrypted_der( &self, rng: &mut R, password: impl AsRef<[u8]>, @@ -119,7 +122,7 @@ pub trait EncodePrivateKey { /// Serialize this private key as an encrypted PEM-encoded PKCS#8 private /// key using the `provided` to derive an encryption key. #[cfg(all(feature = "encryption", feature = "pem"))] - fn to_pkcs8_encrypted_pem( + fn to_pkcs8_encrypted_pem( &self, rng: &mut R, password: impl AsRef<[u8]>, diff --git a/x509-cert/src/builder.rs b/x509-cert/src/builder.rs index bb054eea8..ec657852f 100644 --- a/x509-cert/src/builder.rs +++ b/x509-cert/src/builder.rs @@ -4,7 +4,8 @@ use alloc::vec; use core::fmt; use der::{Encode, asn1::BitString, referenced::OwnedToRef}; use signature::{ - AsyncRandomizedSigner, AsyncSigner, Keypair, RandomizedSigner, Signer, rand_core::CryptoRng, + AsyncRandomizedSigner, AsyncSigner, Keypair, RandomizedSigner, Signer, + rand_core::{CryptoRng, RngCore}, }; use spki::{ DynSignatureAlgorithmIdentifier, EncodePublicKey, ObjectIdentifier, SignatureBitStringEncoding, @@ -347,7 +348,7 @@ pub trait Builder: Sized { S: Keypair + DynSignatureAlgorithmIdentifier, S::VerifyingKey: EncodePublicKey, Signature: SignatureBitStringEncoding, - R: CryptoRng + ?Sized, + R: CryptoRng + RngCore + ?Sized, { let blob = self.finalize(signer)?; @@ -539,7 +540,7 @@ pub trait AsyncBuilder: Sized { S: Keypair + DynSignatureAlgorithmIdentifier, S::VerifyingKey: EncodePublicKey, Signature: SignatureBitStringEncoding, - R: CryptoRng + ?Sized, + R: CryptoRng + RngCore + ?Sized, { let blob = self.finalize(signer)?; diff --git a/x509-cert/src/serial_number.rs b/x509-cert/src/serial_number.rs index ce286ed88..18e9f6f06 100644 --- a/x509-cert/src/serial_number.rs +++ b/x509-cert/src/serial_number.rs @@ -8,7 +8,10 @@ use der::{ asn1::{self, Int}, }; #[cfg(feature = "builder")] -use {alloc::vec, signature::rand_core::CryptoRng}; +use { + alloc::vec, + signature::rand_core::{CryptoRng, RngCore}, +}; use crate::certificate::{Profile, Rfc5280}; @@ -77,7 +80,7 @@ impl SerialNumber

{ /// of output from the CSPRNG. This currently defaults to a 17-bytes long serial number. /// /// [ballot 164]: https://cabforum.org/2016/03/31/ballot-164/ - pub fn generate(rng: &mut R) -> Self { + pub fn generate(rng: &mut R) -> Self { Self::generate_with_prefix(&[], 17, rng) .expect("a random of 17 is acceptable, and rng may not fail") } @@ -91,7 +94,7 @@ impl SerialNumber

{ /// equal or below 19 (to account for leading sign disambiguation, and the maximum length of 20). /// /// [ballot 164]: https://cabforum.org/2016/03/31/ballot-164/ - pub fn generate_with_prefix( + pub fn generate_with_prefix( prefix: &[u8], rand_len: usize, rng: &mut R, diff --git a/x509-ocsp/src/builder/request.rs b/x509-ocsp/src/builder/request.rs index 45cb587fd..0a0d72073 100644 --- a/x509-ocsp/src/builder/request.rs +++ b/x509-ocsp/src/builder/request.rs @@ -3,7 +3,7 @@ use crate::{OcspRequest, Request, Signature, TbsRequest, Version, builder::Error}; use alloc::vec::Vec; use der::Encode; -use rand_core::CryptoRng; +use rand_core::{CryptoRng, RngCore}; use signature::{RandomizedSigner, Signer}; use spki::{DynSignatureAlgorithmIdentifier, SignatureBitStringEncoding}; use x509_cert::{ @@ -148,7 +148,7 @@ impl OcspRequestBuilder { where S: RandomizedSigner + DynSignatureAlgorithmIdentifier, Sig: SignatureBitStringEncoding, - R: CryptoRng + ?Sized, + R: CryptoRng + RngCore + ?Sized, { let signature_algorithm = signer.signature_algorithm_identifier()?; let signature = signer diff --git a/x509-ocsp/src/builder/response.rs b/x509-ocsp/src/builder/response.rs index 7152418b0..776ac3305 100644 --- a/x509-ocsp/src/builder/response.rs +++ b/x509-ocsp/src/builder/response.rs @@ -6,7 +6,7 @@ use crate::{ }; use alloc::vec::Vec; use der::Encode; -use rand_core::CryptoRng; +use rand_core::{CryptoRng, RngCore}; use signature::{RandomizedSigner, Signer}; use spki::{DynSignatureAlgorithmIdentifier, SignatureBitStringEncoding}; use x509_cert::{ @@ -168,7 +168,7 @@ impl OcspResponseBuilder { where S: RandomizedSigner + DynSignatureAlgorithmIdentifier, Sig: SignatureBitStringEncoding, - R: CryptoRng + ?Sized, + R: CryptoRng + RngCore + ?Sized, { let tbs_response_data = self.into_response_data(produced_at); let signature_algorithm = signer.signature_algorithm_identifier()?; diff --git a/x509-ocsp/src/ext.rs b/x509-ocsp/src/ext.rs index 457a8f4a5..601784e8c 100644 --- a/x509-ocsp/src/ext.rs +++ b/x509-ocsp/src/ext.rs @@ -21,7 +21,7 @@ use x509_cert::{ }; #[cfg(feature = "rand")] -use rand_core::CryptoRng; +use rand_core::{CryptoRng, RngCore}; // x509-cert's is not exported macro_rules! impl_extension { @@ -64,7 +64,7 @@ impl Nonce { #[cfg(feature = "rand")] pub fn generate(rng: &mut R, length: usize) -> Result where - R: CryptoRng + ?Sized, + R: CryptoRng + RngCore + ?Sized, { let mut bytes = alloc::vec![0; length]; rng.fill_bytes(&mut bytes);