Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions password-hash/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ impl fmt::Display for Error {

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

#[cfg(feature = "getrandom")]
impl From<getrandom::Error> for Error {
fn from(_: getrandom::Error) -> Self {
// TODO(tarcieri): should we have a specific variant for RNGs errors?
Error::Crypto
}
}

#[cfg(feature = "phc")]
impl From<phc::Error> for Error {
fn from(err: phc::Error) -> Self {
Expand Down
23 changes: 20 additions & 3 deletions password-hash/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub use crate::error::{Error, Result};
pub use phc;

#[cfg(feature = "rand_core")]
pub use rand_core::{self, TryCryptoRng};
pub use rand_core;

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

#[cfg(feature = "rand_core")]
use rand_core::TryCryptoRng;

/// Numeric version identifier for password hashing algorithms.
pub type Version = u32;

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

Expand Down Expand Up @@ -211,3 +213,18 @@ pub trait McfHasher {
/// algorithm-specific rules so hashers must parse a raw string themselves.
fn upgrade_mcf_hash(&self, hash: &str) -> Result<phc::PasswordHash>;
}

/// Generate a random salt value of the recommended length using the system's secure RNG.
#[cfg(feature = "getrandom")]
pub fn generate_salt() -> [u8; RECOMMENDED_SALT_LEN] {
try_generate_salt().expect("RNG failure")
}

/// Try generating a random salt value of the recommended length using the system's secure RNG,
/// returning errors if they occur.
#[cfg(feature = "getrandom")]
pub fn try_generate_salt() -> core::result::Result<[u8; RECOMMENDED_SALT_LEN], getrandom::Error> {
let mut salt = [0u8; RECOMMENDED_SALT_LEN];
getrandom::fill(&mut salt)?;
Ok(salt)
}