use std::sync::LazyLock;
#[derive(Debug, thiserror::Error)]
#[error("failed to hash password")]
pub struct PasswordError(#[source] bcrypt::BcryptError);
pub fn hash_password(password: &str) -> Result<String, PasswordError> {
bcrypt::hash(password, bcrypt::DEFAULT_COST).map_err(PasswordError)
}
pub fn verify_password(password: &str, hash: &str) -> bool {
bcrypt::verify(password, hash).unwrap_or(false)
}
pub fn dummy_hash() -> &'static str {
static HASH: LazyLock<String> = LazyLock::new(|| {
let password: [u8; 16] = rand::random();
bcrypt::hash(password, bcrypt::DEFAULT_COST).expect("hashing a random password")
});
&HASH
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hash_round_trip() {
let hash = hash_password("correct horse").unwrap();
assert!(verify_password("correct horse", &hash));
assert!(!verify_password("wrong horse", &hash));
assert!(!verify_password("correct horse", "not a hash"));
assert!(!verify_password("", dummy_hash()));
}
}