Skip to content

Commit

Permalink
password-auth: replace VerifyError with Error enum (#429)
Browse files Browse the repository at this point in the history
`VerifyError` was previously the return type for the `verify_password`
function which has two distinct error cases:

- Password hash failed to parse
- Password is invalid

This commit replaces `VerifyError` with an `Error` enum which captures
both cases.

It leverages the `ParseError` type which was added in #428.
  • Loading branch information
tarcieri committed Jun 24, 2023
1 parent bb416f9 commit 45826c5
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion password-auth/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "password-auth"
version = "0.1.1"
version = "0.2.0-pre"
description = """
Password authentication library with a focus on simplicity and ease-of-use,
with support for Argon2, PBKDF2, and scrypt password hashing algorithms
Expand Down
53 changes: 40 additions & 13 deletions password-auth/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,41 @@
//! Error types.

use alloc::string::ToString;
use core::fmt;

/// Password hash parse errors.
/// Error type.
#[derive(Clone, Copy, Debug)]
pub enum Error {
/// Password hash parsing errors.
Parse(ParseError),

/// Password is invalid.
PasswordInvalid,
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Parse(err) => write!(f, "{err}"),
Self::PasswordInvalid => write!(f, "password is invalid"),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

impl From<ParseError> for Error {
fn from(err: ParseError) -> Error {
Error::Parse(err)
}
}

/// Password hash parse errors.
// This type has no public constructor and deliberately keeps
// `password_hash::Error` out of the public API so it can evolve
// independently (e.g. get to 1.0 faster)
#[derive(Clone, Copy)]
pub struct ParseError(password_hash::Error);

impl ParseError {
Expand All @@ -13,24 +45,19 @@ impl ParseError {
}
}

impl fmt::Display for ParseError {
impl fmt::Debug for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", &self.0)
f.debug_tuple("ParseError")
.field(&self.0.to_string())
.finish()
}
}

#[cfg(feature = "std")]
impl std::error::Error for ParseError {}

/// Password hash verification errors.
#[derive(Clone, Copy, Debug)]
pub struct VerifyError;

impl fmt::Display for VerifyError {
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("password verification error")
write!(f, "{}", &self.0)
}
}

#[cfg(feature = "std")]
impl std::error::Error for VerifyError {}
impl std::error::Error for ParseError {}
8 changes: 4 additions & 4 deletions password-auth/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extern crate std;

mod errors;

pub use crate::errors::{ParseError, VerifyError};
pub use crate::errors::{Error, ParseError};

use alloc::string::{String, ToString};
use password_hash::{ParamsString, PasswordHash, PasswordHasher, PasswordVerifier, SaltString};
Expand Down Expand Up @@ -78,8 +78,8 @@ fn generate_phc_hash<'a>(
/// - `Ok(())` if the password hash verified successfully
/// - `Err(VerifyError)` if the hash didn't parse successfully or the password
/// failed to verify against the hash.
pub fn verify_password(password: impl AsRef<[u8]>, hash: &str) -> Result<(), VerifyError> {
let hash = PasswordHash::new(hash).map_err(|_| VerifyError)?;
pub fn verify_password(password: impl AsRef<[u8]>, hash: &str) -> Result<(), Error> {
let hash = PasswordHash::new(hash).map_err(ParseError::new)?;

let algs: &[&dyn PasswordVerifier] = &[
#[cfg(feature = "argon2")]
Expand All @@ -91,7 +91,7 @@ pub fn verify_password(password: impl AsRef<[u8]>, hash: &str) -> Result<(), Ver
];

hash.verify_password(algs, password)
.map_err(|_| VerifyError)
.map_err(|_| Error::PasswordInvalid)
}

/// Determine if the given password hash is using the recommended algorithm and
Expand Down

0 comments on commit 45826c5

Please sign in to comment.