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
14 changes: 10 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ digest = { path = "digest" }
signature = { path = "signature" }

getrandom = { git = "https://github.com/rust-random/getrandom" }
phc = { git = "https://github.com/RustCrypto/formats" }
13 changes: 2 additions & 11 deletions password-hash/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,10 @@ as well as a `no_std`-friendly implementation of the PHC string format
"""

[dependencies]
base64ct = "1.7"
subtle = { version = "2", default-features = false }

# optional dependencies
getrandom = { version = "0.3", optional = true, default-features = false }
rand_core = { version = "0.10.0-rc-2", optional = true, default-features = false }
phc = { version = "0.3.0-pre", optional = true, default-features = false }

[features]
default = ["phc", "rand_core"]
alloc = ["base64ct/alloc"]
getrandom = ["dep:getrandom"]
phc = []
rand_core = ["dep:rand_core"]
alloc = ["phc?/alloc"]

[package.metadata.docs.rs]
all-features = true
63 changes: 63 additions & 0 deletions password-hash/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//! Error types.

use core::fmt;

/// Result type.
pub type Result<T> = core::result::Result<T, Error>;

/// Password hashing errors.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Error {
/// Unsupported algorithm.
Algorithm,

/// Cryptographic error.
Crypto,

/// Encoding errors (e.g. Base64).
EncodingInvalid,

/// Out of memory (heap allocation failure).
OutOfMemory,

/// Output size invalid.
OutputSize,

/// Invalid named parameter.
ParamInvalid {
/// Parameter name.
name: &'static str,
},

/// Invalid parameters.
ParamsInvalid,

/// Invalid password.
PasswordInvalid,

/// Invalid salt.
SaltInvalid,
Comment on lines +24 to +40
Copy link
Copy Markdown
Member Author

@tarcieri tarcieri Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: several of these are significantly less fine-grained, notably you can't tell whether salts and outputs are too small or too big. Hopefully people can figure it out from context, though we may consider adding it back.

The ParamInvalid error should be a significant improvement in that it informs you exactly which parameter was invalid (although perhaps does a poor job of telling you why)


/// Invalid algorithm version.
Version,
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> {
match self {
Self::Algorithm => write!(f, "unsupported algorithm"),
Self::Crypto => write!(f, "cryptographic error"),
Self::EncodingInvalid => write!(f, "invalid encoding"),
Self::OutOfMemory => write!(f, "out of memory"),
Self::OutputSize => write!(f, "password hash output size invalid"),
Self::ParamInvalid { name } => write!(f, "invalid parameter: {name:?}"),
Self::ParamsInvalid => write!(f, "invalid parameters"),
Self::PasswordInvalid => write!(f, "invalid password"),
Self::SaltInvalid => write!(f, "invalid salt"),
Self::Version => write!(f, "invalid algorithm version"),
}
}
}

impl core::error::Error for Error {}
178 changes: 0 additions & 178 deletions password-hash/src/errors.rs

This file was deleted.

23 changes: 10 additions & 13 deletions password-hash/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,12 @@
#[allow(unused_extern_crates)]
extern crate alloc;

#[cfg(feature = "rand_core")]
pub use rand_core;
mod error;

pub mod errors;
#[cfg(feature = "phc")]
pub mod phc;
pub use crate::error::{Error, Result};

pub use crate::errors::{Error, Result};
#[cfg(feature = "phc")]
pub use phc;

/// DEPRECATED: import this as `password_hash::phc::PasswordHash`.
#[cfg(feature = "phc")]
Expand All @@ -46,11 +44,11 @@ pub use crate::errors::{Error, Result};
)]
pub type PasswordHash = phc::PasswordHash;

/// DEPRECATED: import this as `password_hash::phc::PasswordHashString`.
/// DEPRECATED: use `password_hash::phc::PasswordHash` or `String`
#[cfg(all(feature = "alloc", feature = "phc"))]
#[deprecated(
since = "0.6.0",
note = "import as `password_hash::phc::PasswordHashString` instead"
note = "use `password_hash::phc::PasswordHash` or `String`"
)]
pub type PasswordHashString = phc::PasswordHashString;

Expand Down Expand Up @@ -97,13 +95,12 @@ pub trait CustomizedPasswordHasher<H> {

/// Trait for password verification.
///
/// Generic around a password hash to be returned (typically [`PasswordHash`])
/// Generic around a password hash to be returned (typically [`phc::PasswordHash`])
///
/// Automatically impl'd for any type that impls [`PasswordHasher`] with [`PasswordHash`] as `H`.
/// Automatically impl'd for type that impl [`PasswordHasher`] with [`phc::PasswordHash`] as `H`.
///
/// This trait is object safe and can be used to implement abstractions over
/// multiple password hashing algorithms. One such abstraction is provided by
/// the [`PasswordHash::verify_password`] method.
/// multiple password hashing algorithms.
pub trait PasswordVerifier<H> {
/// Compute this password hashing function against the provided password
/// using the parameters from the provided password hash and see if the
Expand Down Expand Up @@ -135,7 +132,7 @@ impl<T: CustomizedPasswordHasher<phc::PasswordHash>> PasswordVerifier<phc::Passw
_ => (),
}

Err(Error::Password)
Err(Error::PasswordInvalid)
}
}

Expand Down
Loading