Sign up/in/out and authentication.
[recipes.git] / backend / src / hash.rs
1 use std::{string::String, env::consts::OS};
2
3 use argon2::{
4 password_hash::{
5 Error,
6 rand_core::OsRng,
7 PasswordHash, PasswordHasher, PasswordVerifier, SaltString
8 },
9 Argon2
10 };
11
12 pub fn hash(password: &str) -> Result<String, Box<dyn std::error::Error>> {
13 let salt = SaltString::generate(&mut OsRng);
14 let argon2 = Argon2::default();
15 argon2.hash_password(password.as_bytes(), &salt).map(|h| h.to_string()).map_err(|e| e.into())
16 }
17
18 pub fn verify_password(password: &str, hashed_password: &str) -> Result<bool, Box<dyn std::error::Error>> {
19 let argon2 = Argon2::default();
20 let parsed_hash = PasswordHash::new(hashed_password)?;
21 Ok(argon2.verify_password(password.as_bytes(), &parsed_hash).is_ok())
22 }
23
24 #[cfg(test)]
25 mod test {
26 use super::*;
27
28 #[test]
29 fn simple_case() -> Result<(), Box<dyn std::error::Error>> {
30 let password = "12345";
31 let hash = hash(password)?;
32 println!("hash: {}", &hash);
33 assert!(verify_password(password, &hash)?);
34 assert!(!verify_password("54321", &hash)?);
35 Ok(())
36 }
37
38 #[test]
39 fn password_with_special_characters() -> Result<(), Box<dyn std::error::Error>> {
40 let password = "éà ä_\\😺🎮🇨🇭";
41 let hash = hash(password)?;
42 println!("hash: {}", &hash);
43 assert!(verify_password(password, &hash)?);
44 Ok(())
45 }
46 }