-use std::{string::String, env::consts::OS};
+use std::string::String;
use argon2::{
- password_hash::{
- Error,
- rand_core::OsRng,
- PasswordHash, PasswordHasher, PasswordVerifier, SaltString
- },
- Argon2
+ password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
+ Argon2,
};
pub fn hash(password: &str) -> Result<String, Box<dyn std::error::Error>> {
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
- argon2.hash_password(password.as_bytes(), &salt).map(|h| h.to_string()).map_err(|e| e.into())
-}
\ No newline at end of file
+ argon2
+ .hash_password(password.as_bytes(), &salt)
+ .map(|h| h.to_string())
+ .map_err(|e| e.into())
+}
+
+pub fn verify_password(
+ password: &str,
+ hashed_password: &str,
+) -> Result<bool, Box<dyn std::error::Error>> {
+ let argon2 = Argon2::default();
+ let parsed_hash = PasswordHash::new(hashed_password)?;
+ Ok(argon2
+ .verify_password(password.as_bytes(), &parsed_hash)
+ .is_ok())
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn simple_case() -> Result<(), Box<dyn std::error::Error>> {
+ let password = "12345";
+ let hash = hash(password)?;
+ println!("hash: {}", &hash);
+ assert!(verify_password(password, &hash)?);
+ assert!(!verify_password("54321", &hash)?);
+ Ok(())
+ }
+
+ #[test]
+ fn password_with_special_characters() -> Result<(), Box<dyn std::error::Error>> {
+ let password = "éà ä_\\😺🎮🇨🇭";
+ let hash = hash(password)?;
+ println!("hash: {}", &hash);
+ assert!(verify_password(password, &hash)?);
+ Ok(())
+ }
+}