yggdrasil/auth/
password.rs1#[cfg(feature = "server")]
7use argon2::{
8 password_hash::{phc::PasswordHash, PasswordHasher, PasswordVerifier},
9 Argon2,
10};
11
12#[cfg(feature = "server")]
13pub fn hash_password(password: &str) -> Result<String, argon2::password_hash::Error> {
15 let argon2 = Argon2::default();
16 let password_hash = argon2.hash_password(password.as_bytes())?;
17 Ok(password_hash.to_string())
18}
19
20#[cfg(feature = "server")]
21pub fn verify_password(password: &str, hash: &str) -> Result<bool, argon2::password_hash::Error> {
23 let parsed_hash = PasswordHash::new(hash)?;
24 let argon2 = Argon2::default();
25 match argon2.verify_password(password.as_bytes(), &parsed_hash) {
26 Ok(()) => Ok(true),
27 Err(argon2::password_hash::Error::PasswordInvalid) => Ok(false),
28 Err(e) => Err(e),
29 }
30}
31
32#[cfg(all(test, feature = "server"))]
33mod tests {
34 use super::*;
35
36 #[test]
37 fn verify_legacy_argon2id_phc() {
38 let hash = "$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$CTFhFdXPJO1aFaMaO6Mm5c8y7cJHAph8ArZWb2GRPPc";
41 assert_eq!(verify_password("password", hash), Ok(true));
42 assert_eq!(verify_password("sassword", hash), Ok(false));
43 }
44
45 #[test]
46 fn hash_and_verify_roundtrip() {
47 let hash = hash_password("mypassword123").unwrap();
48 assert!(verify_password("mypassword123", &hash).unwrap());
49 }
50
51 #[test]
52 fn verify_wrong_password_returns_false() {
53 let hash = hash_password("correctpassword").unwrap();
54 assert!(!verify_password("wrongpassword", &hash).unwrap());
55 }
56
57 #[test]
58 fn different_hashes_for_same_password() {
59 let hash1 = hash_password("samepassword").unwrap();
60 let hash2 = hash_password("samepassword").unwrap();
61 assert_ne!(hash1, hash2);
62 }
63
64 #[test]
65 fn verify_invalid_hash_returns_error() {
66 let result = verify_password("password", "not-a-valid-hash");
67 assert!(result.is_err());
68 }
69
70 #[test]
71 fn hash_empty_password() {
72 let hash = hash_password("").unwrap();
73 assert!(verify_password("", &hash).unwrap());
74 }
75
76 #[test]
77 fn hash_long_password() {
78 let long_pw = "a".repeat(1000);
79 let hash = hash_password(&long_pw).unwrap();
80 assert!(verify_password(&long_pw, &hash).unwrap());
81 }
82}