use anyhow::{anyhow, Result};
use rand::rngs::OsRng;
use argon2::{
password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
Argon2,
};
#[allow(clippy::missing_errors_doc)]
pub fn hash_password(password: &str) -> Result<String> {
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
let hash = argon2
.hash_password(password.as_bytes(), &salt)
.map_err(|e| anyhow!("password hash failed: {e}"))?;
Ok(hash.to_string())
}
#[allow(clippy::missing_errors_doc)]
pub fn verify_password(password: &str, hash: &str) -> Result<bool> {
let parsed = PasswordHash::new(hash).map_err(|e| anyhow!("invalid hash format: {e}"))?;
Ok(Argon2::default()
.verify_password(password.as_bytes(), &parsed)
.is_ok())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hash_and_verify() {
let hash = hash_password("test123").unwrap();
assert!(verify_password("test123", &hash).unwrap());
assert!(!verify_password("wrong", &hash).unwrap());
}
}