hefesto 1.0.0

Double envelope encryption — AES-256-GCM + Argon2id for multi-tenant applications
Documentation
use hmac::{Hmac, Mac};
use sha2::Sha256;

type HmacSha256 = Hmac<Sha256>;

pub(crate) fn hash_for_lookup(value: &str, tenant_key: &str) -> String {
    let mut mac =
        HmacSha256::new_from_slice(tenant_key.as_bytes()).expect("HMAC accepts any key length");
    mac.update(value.as_bytes());
    hex::encode(mac.finalize().into_bytes())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn deterministic() {
        let h1 = hash_for_lookup("user@example.com", "tenant_key");
        let h2 = hash_for_lookup("user@example.com", "tenant_key");
        assert_eq!(h1, h2);
    }

    #[test]
    fn different_values_different_hashes() {
        let h1 = hash_for_lookup("a@example.com", "key");
        let h2 = hash_for_lookup("b@example.com", "key");
        assert_ne!(h1, h2);
    }

    #[test]
    fn different_tenant_keys_different_hashes() {
        let h1 = hash_for_lookup("user@example.com", "tenant_a");
        let h2 = hash_for_lookup("user@example.com", "tenant_b");
        assert_ne!(h1, h2);
    }

    #[test]
    fn output_is_valid_hex() {
        let h = hash_for_lookup("test", "key");
        assert!(h.chars().all(|c| c.is_ascii_hexdigit()));
        assert_eq!(h.len(), 64);
    }
}