libsoliton 0.1.3

Core cryptographic library for the LO protocol — hybrid post-quantum key exchange, signatures, ratchet, and storage encryption
Documentation
//! SHA3-256 hashing (FIPS 202).

use sha3::{Digest, Sha3_256};

/// Compute SHA3-256 hash of `data`.
#[must_use]
pub fn hash(data: &[u8]) -> [u8; 32] {
    Sha3_256::digest(data).into()
}

/// Compute the hex-encoded fingerprint (SHA3-256) of a public key.
#[must_use]
pub fn fingerprint_hex(pk: &[u8]) -> String {
    let digest = hash(pk);
    hex_encode(&digest)
}

/// Encode bytes as lowercase hex string.
fn hex_encode(bytes: &[u8]) -> String {
    use std::fmt::Write;
    let mut s = String::with_capacity(bytes.len() * 2);
    for &b in bytes {
        // fmt::Write for String is infallible — the Result is always Ok.
        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);
    }
}