From a051190c68dc0e98f72fe0d670651630f5129e4c Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 13 Dec 2025 08:24:54 -0700 Subject: [PATCH] password-hash: add `rand_core` feature Adds a `PasswordHash::hash_password_with_rng` method gated on the `rand_core` feature which uses a `TryCryptoRng` to generate a random salt, analogous to the `getrandom`-based `PasswordHash::hash_password`. --- Cargo.lock | 2 ++ password-hash/Cargo.toml | 2 ++ password-hash/src/lib.rs | 20 +++++++++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index f78b545b..7ec68de8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,6 +326,7 @@ version = "0.6.0-rc.5" dependencies = [ "getrandom", "phc", + "rand_core", ] [[package]] @@ -345,6 +346,7 @@ checksum = "c61f960577aaac5c259bc0866d685ba315c0ed30793c602d7287f54980913863" dependencies = [ "base64ct", "getrandom", + "rand_core", "subtle", ] diff --git a/password-hash/Cargo.toml b/password-hash/Cargo.toml index c5d03536..48aae959 100644 --- a/password-hash/Cargo.toml +++ b/password-hash/Cargo.toml @@ -19,10 +19,12 @@ as well as a `no_std`-friendly implementation of the PHC string format [dependencies] getrandom = { version = "0.3", optional = true, default-features = false } phc = { version = "0.6.0-rc.0", optional = true, default-features = false } +rand_core = { version = "0.10.0-rc-2", optional = true, default-features = false } [features] alloc = ["phc?/alloc"] getrandom = ["dep:getrandom", "phc?/getrandom"] +rand_core = ["dep:rand_core", "phc?/rand_core"] [package.metadata.docs.rs] all-features = true diff --git a/password-hash/src/lib.rs b/password-hash/src/lib.rs index 292c8b04..09813c2b 100644 --- a/password-hash/src/lib.rs +++ b/password-hash/src/lib.rs @@ -36,6 +36,9 @@ pub use crate::error::{Error, Result}; #[cfg(feature = "phc")] pub use phc; +#[cfg(feature = "rand_core")] +pub use rand_core::{self, TryCryptoRng}; + /// DEPRECATED: import this as `password_hash::phc::PasswordHash`. #[cfg(feature = "phc")] #[deprecated( @@ -71,7 +74,7 @@ pub type Version = u32; /// > over exactly 16 bytes). 16 bytes encode as 22 characters in B64. /// /// [PHC string format specification]: https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md#function-duties -#[cfg(feature = "getrandom")] +#[cfg(any(feature = "getrandom", feature = "rand_core"))] const RECOMMENDED_SALT_LEN: usize = 16; /// High-level trait for password hashing functions. @@ -95,6 +98,21 @@ pub trait PasswordHasher { getrandom::fill(&mut salt).map_err(|_| Error::Crypto)?; self.hash_password_with_salt(password, &salt) } + + /// Compute the hash `H` from the given password, potentially using configuration stored in + /// `&self` for the parameters, or otherwise the recommended defaults. + /// + /// A large random salt will be generated automatically from the provided RNG. + #[cfg(feature = "rand_core")] + fn hash_password_with_rng( + &self, + rng: &mut R, + password: &[u8], + ) -> Result { + let mut salt = [0u8; RECOMMENDED_SALT_LEN]; + rng.try_fill_bytes(&mut salt).map_err(|_| Error::Crypto)?; + self.hash_password_with_salt(password, &salt) + } } /// Trait for password hashing functions which support customization.