Skip to content

Commit 70faf07

Browse files
authored
password-hash: expose salt generating helper functions (#2128)
Right now there's not a way to generate a random salt in the context of MCF password hashes when not using the high-level `PasswordHash::hash_password` API, e.g. for KDF usage, which is to say that for PHC password hashes `phc::Salt::generate` is fine for this purpose since it now provides raw bytes, but password hashes which use MCF don't have access to that type. This is often still documented as using some static value with a comment saying it needs to be unique. Instead we should provide a reusable solution in the rustdoc. These can potentially be replaced with the `crypto_common::Generate` trait and something like a `RecommendedLengthSalt` type after there's a new `getrandom` crate prerelease, but in the meantime these helper functions seem like a reasonable enough stopgap, and can potentially stick around and use the `Generate` trait for you.
1 parent 7ecfdeb commit 70faf07

2 files changed

Lines changed: 28 additions & 3 deletions

File tree

password-hash/src/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ impl fmt::Display for Error {
6666

6767
impl core::error::Error for Error {}
6868

69+
#[cfg(feature = "getrandom")]
70+
impl From<getrandom::Error> for Error {
71+
fn from(_: getrandom::Error) -> Self {
72+
// TODO(tarcieri): should we have a specific variant for RNGs errors?
73+
Error::Crypto
74+
}
75+
}
76+
6977
#[cfg(feature = "phc")]
7078
impl From<phc::Error> for Error {
7179
fn from(err: phc::Error) -> Self {

password-hash/src/lib.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub use crate::error::{Error, Result};
3737
pub use phc;
3838

3939
#[cfg(feature = "rand_core")]
40-
pub use rand_core::{self, TryCryptoRng};
40+
pub use rand_core;
4141

4242
/// DEPRECATED: import this as `password_hash::phc::PasswordHash`.
4343
#[cfg(feature = "phc")]
@@ -61,6 +61,9 @@ use core::{
6161
str::FromStr,
6262
};
6363

64+
#[cfg(feature = "rand_core")]
65+
use rand_core::TryCryptoRng;
66+
6467
/// Numeric version identifier for password hashing algorithms.
6568
pub type Version = u32;
6669

@@ -94,8 +97,7 @@ pub trait PasswordHasher<H> {
9497
/// A large random salt will be generated automatically.
9598
#[cfg(feature = "getrandom")]
9699
fn hash_password(&self, password: &[u8]) -> Result<H> {
97-
let mut salt = [0u8; RECOMMENDED_SALT_LEN];
98-
getrandom::fill(&mut salt).map_err(|_| Error::Crypto)?;
100+
let salt = try_generate_salt()?;
99101
self.hash_password_with_salt(password, &salt)
100102
}
101103

@@ -211,3 +213,18 @@ pub trait McfHasher {
211213
/// algorithm-specific rules so hashers must parse a raw string themselves.
212214
fn upgrade_mcf_hash(&self, hash: &str) -> Result<phc::PasswordHash>;
213215
}
216+
217+
/// Generate a random salt value of the recommended length using the system's secure RNG.
218+
#[cfg(feature = "getrandom")]
219+
pub fn generate_salt() -> [u8; RECOMMENDED_SALT_LEN] {
220+
try_generate_salt().expect("RNG failure")
221+
}
222+
223+
/// Try generating a random salt value of the recommended length using the system's secure RNG,
224+
/// returning errors if they occur.
225+
#[cfg(feature = "getrandom")]
226+
pub fn try_generate_salt() -> core::result::Result<[u8; RECOMMENDED_SALT_LEN], getrandom::Error> {
227+
let mut salt = [0u8; RECOMMENDED_SALT_LEN];
228+
getrandom::fill(&mut salt)?;
229+
Ok(salt)
230+
}

0 commit comments

Comments
 (0)