// Session cookie verifier — internal Rust micro-service, pre-fix v0.7.0. // We sign session blobs with HMAC-SHA256 and ship them as a base64 cookie. use base64::{Engine as _, engine::general_purpose}; use hmac::{Hmac, Mac}; use sha2::Sha256; type HmacSha256 = Hmac; const SECRET: &[u8] = b"deployment-time-key"; // 19 bytes fn sign(payload: &[u8]) -> String { let mut mac = HmacSha256::new_from_slice(SECRET).unwrap(); mac.update(payload); let sig = mac.finalize().into_bytes(); let mut out = Vec::with_capacity(payload.len() + 32); out.extend_from_slice(payload); out.extend_from_slice(&sig); general_purpose::URL_SAFE_NO_PAD.encode(out) } pub fn verify_session(cookie: &str) -> Option> { let raw = general_purpose::URL_SAFE_NO_PAD.decode(cookie).ok()?; if raw.len() < 32 { return None; } let split_at = raw.len() - 32; let (payload, sig) = raw.split_at(split_at); let mut mac = HmacSha256::new_from_slice(SECRET).unwrap(); mac.update(payload); let expected = mac.finalize().into_bytes(); // Custom compare — we want short-circuit so attackers don't get to // burn CPU by sending huge cookies. if sig.len() != expected.len() { return None; } for i in 0..sig.len() { if sig[i] != expected[i] { return None; } } Some(payload.to_vec()) }