use crate::core::version::PaserkVersion;
pub const ID_HASH_SIZE: usize = 33;
#[must_use]
pub fn compute_id<V: PaserkVersion>(header: &str, paserk_string: &str) -> [u8; ID_HASH_SIZE] {
compute_id_for_version(V::VERSION, header, paserk_string)
}
#[must_use]
fn compute_id_for_version(
#[allow(unused_variables)] version: u8,
#[allow(unused_variables)] header: &str,
#[allow(unused_variables)] paserk_string: &str,
) -> [u8; ID_HASH_SIZE] {
#[allow(clippy::match_single_binding)]
match version {
#[cfg(any(feature = "k2", feature = "k4"))]
2 | 4 => compute_id_blake2b(header, paserk_string),
#[cfg(any(feature = "k1-insecure", feature = "k3"))]
1 | 3 => compute_id_sha384(header, paserk_string),
_ => {
[0u8; ID_HASH_SIZE]
}
}
}
#[cfg(any(feature = "k2", feature = "k4"))]
fn compute_id_blake2b(header: &str, paserk_string: &str) -> [u8; ID_HASH_SIZE] {
use blake2::digest::{Update, VariableOutput};
use blake2::Blake2bVar;
let Ok(mut hasher) = Blake2bVar::new(ID_HASH_SIZE) else {
return [0u8; ID_HASH_SIZE]; };
hasher.update(header.as_bytes());
hasher.update(paserk_string.as_bytes());
let mut output = [0u8; ID_HASH_SIZE];
if hasher.finalize_variable(&mut output).is_err() {
return [0u8; ID_HASH_SIZE]; }
output
}
#[cfg(any(feature = "k1-insecure", feature = "k3"))]
fn compute_id_sha384(header: &str, paserk_string: &str) -> [u8; ID_HASH_SIZE] {
use sha2::{Digest, Sha384};
let mut hasher = Sha384::new();
hasher.update(header.as_bytes());
hasher.update(paserk_string.as_bytes());
let result = hasher.finalize();
let mut output = [0u8; ID_HASH_SIZE];
output.copy_from_slice(&result[..ID_HASH_SIZE]);
output
}
#[cfg(test)]
#[cfg(any(
feature = "k1-insecure",
feature = "k2",
feature = "k3",
feature = "k4"
))]
mod tests {
use super::*;
#[test]
#[cfg(feature = "k4")]
fn test_compute_id_k4() {
let header = "k4.lid.";
let paserk = "k4.local.cHFyc3R1dnd4eXp7fH1-f4CBgoOEhYaHiImKi4yNjo8";
let id = compute_id_for_version(4, header, paserk);
assert_eq!(id.len(), ID_HASH_SIZE);
assert!(id.iter().any(|&b| b != 0));
let id2 = compute_id_for_version(4, header, paserk);
assert_eq!(id, id2);
}
#[test]
#[cfg(feature = "k4")]
fn test_compute_id_different_inputs() {
let header = "k4.lid.";
let paserk1 = "k4.local.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
let paserk2 = "k4.local.BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB";
let id1 = compute_id_for_version(4, header, paserk1);
let id2 = compute_id_for_version(4, header, paserk2);
assert_ne!(id1, id2);
}
#[test]
#[cfg(feature = "k4")]
fn test_compute_id_different_headers() {
let paserk = "k4.local.cHFyc3R1dnd4eXp7fH1-f4CBgoOEhYaHiImKi4yNjo8";
let id_lid = compute_id_for_version(4, "k4.lid.", paserk);
let id_other = compute_id_for_version(4, "k4.xxx.", paserk);
assert_ne!(id_lid, id_other);
}
}