use sha3::{Digest, Sha3_256};
#[must_use]
pub fn hash(data: &[u8]) -> [u8; 32] {
Sha3_256::digest(data).into()
}
#[must_use]
pub fn fingerprint_hex(pk: &[u8]) -> String {
let digest = hash(pk);
hex_encode(&digest)
}
fn hex_encode(bytes: &[u8]) -> String {
use std::fmt::Write;
let mut s = String::with_capacity(bytes.len() * 2);
for &b in bytes {
let _ = write!(s, "{b:02x}");
}
s
}
#[cfg(test)]
mod tests {
use super::*;
use hex_literal::hex;
#[test]
fn empty_input() {
assert_eq!(
hash(b""),
hex!("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a")
);
}
#[test]
fn abc() {
assert_eq!(
hash(b"abc"),
hex!("3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532")
);
}
#[test]
fn long_message() {
assert_eq!(
hash(b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"),
hex!("41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376")
);
}
#[test]
fn fingerprint_hex_format() {
let fp = fingerprint_hex(b"test");
assert_eq!(fp.len(), 64);
assert!(
fp.chars()
.all(|c| c.is_ascii_hexdigit() && !c.is_ascii_uppercase())
);
}
#[test]
fn fingerprint_hex_deterministic() {
let a = fingerprint_hex(b"test");
let b = fingerprint_hex(b"test");
assert_eq!(a, b);
}
#[test]
fn fingerprint_hex_matches_hash() {
let data = b"hello world";
let fp = fingerprint_hex(data);
let expected = hex::encode(hash(data));
assert_eq!(fp, expected);
}
}