use alloc::string::String;
use sha2::{Digest, Sha256};
#[must_use]
pub fn group_id(xcdr2_keyhash: &[u8]) -> String {
let mut h = Sha256::new();
h.update(xcdr2_keyhash);
let digest = h.finalize();
let mut out = String::with_capacity(64);
for b in digest {
let _ = core::fmt::Write::write_fmt(&mut out, core::format_args!("{b:02x}"));
}
out
}
#[cfg(test)]
#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
mod tests {
use super::*;
#[test]
fn empty_keyhash_yields_known_sha256() {
let id = group_id(b"");
assert_eq!(
id,
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
);
}
#[test]
fn keyhash_length_always_64_lowercase_hex() {
for sample in [b"a".as_slice(), b"abc".as_slice(), &[0u8; 64]] {
let id = group_id(sample);
assert_eq!(id.len(), 64);
assert!(
id.chars()
.all(|c| c.is_ascii_hexdigit() && !c.is_ascii_uppercase())
);
}
}
#[test]
fn distinct_keyhash_yields_distinct_group_id() {
let a = group_id(b"\x00\x00\x00\x07");
let b = group_id(b"\x00\x00\x00\x08");
assert_ne!(a, b);
}
#[test]
fn solidus_in_key_safe() {
let with_slash = group_id(b"EU/DE\x00Foo");
let without = group_id(b"EUDEXFoo");
assert_ne!(with_slash, without);
}
#[test]
fn deterministic_across_calls() {
let a = group_id(b"\x00\x01\x02\x03");
let b = group_id(b"\x00\x01\x02\x03");
assert_eq!(a, b);
}
}