Skip to main content

trojan_auth/
hash.rs

1//! Password hashing utilities.
2
3use sha2::{Digest, Sha224};
4
5/// Compute SHA224 hash and return as lowercase hex string.
6///
7/// This is the standard hash function used by the Trojan protocol.
8///
9/// # Example
10/// ```
11/// use trojan_auth::sha224_hex;
12///
13/// let hash = sha224_hex("password123");
14/// assert_eq!(hash.len(), 56); // SHA224 = 224 bits = 28 bytes = 56 hex chars
15/// ```
16#[inline]
17pub fn sha224_hex(input: &str) -> String {
18    let mut hasher = Sha224::new();
19    hasher.update(input.as_bytes());
20    let digest = hasher.finalize();
21    hex::encode(digest)
22}
23
24/// Verify if a hash matches a plaintext password.
25#[inline]
26pub fn verify_password(password: &str, hash: &str) -> bool {
27    sha224_hex(password) == hash
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    #[test]
35    fn test_sha224_hex() {
36        // Known test vector
37        let hash = sha224_hex("password");
38        assert_eq!(hash.len(), 56);
39        assert!(hash.chars().all(|c| c.is_ascii_hexdigit()));
40    }
41
42    #[test]
43    fn test_verify_password() {
44        let hash = sha224_hex("test123");
45        assert!(verify_password("test123", &hash));
46        assert!(!verify_password("wrong", &hash));
47    }
48
49    #[test]
50    fn test_consistency() {
51        let password = "my_secret_password";
52        let hash1 = sha224_hex(password);
53        let hash2 = sha224_hex(password);
54        assert_eq!(hash1, hash2);
55    }
56}