use sha2::{Digest, Sha256};
#[must_use]
pub fn finding_id(
technique_id: &str,
target_url: &str,
oracle_class: &str,
method: &str,
strategy_id: &str,
) -> String {
let mut hasher = Sha256::new();
hasher.update(technique_id.as_bytes());
hasher.update(b"|");
hasher.update(target_url.as_bytes());
hasher.update(b"|");
hasher.update(oracle_class.as_bytes());
hasher.update(b"|");
hasher.update(method.as_bytes());
hasher.update(b"|");
hasher.update(strategy_id.as_bytes());
let hash = hasher.finalize();
hex::encode(&hash[..6])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn finding_id_is_12_hex_chars() {
let id = finding_id(
"cp-if-none-match",
"https://example.com/api",
"Existence",
"GET",
"s1",
);
assert_eq!(id.len(), 12);
assert!(id.chars().all(|c| c.is_ascii_hexdigit()));
}
#[test]
fn finding_id_is_deterministic() {
let a = finding_id("t1", "https://x.com", "Existence", "GET", "s1");
let b = finding_id("t1", "https://x.com", "Existence", "GET", "s1");
assert_eq!(a, b);
}
#[test]
fn finding_id_differs_on_input_change() {
let a = finding_id("t1", "https://x.com", "Existence", "GET", "s1");
let b = finding_id("t1", "https://x.com", "Existence", "POST", "s1");
assert_ne!(a, b);
}
}