use argon2::password_hash::rand_core::OsRng; use argon2::password_hash::SaltString; use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier}; /// Verifies that the given password matches the given hash. pub fn verify(hash: &str, password: &str) -> bool { let parsed_hash = match PasswordHash::new(hash) { Ok(hash) => hash, Err(_) => return false, // TODO: log an error }; Argon2::default().verify_password(password.as_bytes(), &parsed_hash).is_ok() } /// Hashes the given password. pub fn hash(password: &str) -> String { let salt = SaltString::generate(&mut OsRng); let hash = Argon2::default().hash_password(password.as_bytes(), &salt).unwrap(); hash.to_string() } #[cfg(test)] mod tests { use super::*; #[test] fn test_password_hashes_match() { // this is a well-known example password: // https://knowyourmeme.com/memes/hunter2 let password = "hunter2"; let hashed_password = hash(password); let hashed_other = hash("not-the-password"); assert!(verify(&hashed_password, password)); assert!(!verify(&hashed_other, password)); } }