krypteia-tessera 0.2.0

Shared pure-Rust hash, XOF, MAC and KDF primitives for the krypteia workspace: SHA-1/2/3, Keccak, SHAKE/cSHAKE, RIPEMD-160, BLAKE2/BLAKE3, HMAC, SP 800-185 (KMAC/TupleHash/ParallelHash), the KDF family (HKDF, PBKDF2, SP 800-108, scrypt, Argon2), MGF1 and CRC-16/32. no_std, zero runtime dependencies.
Documentation
// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 Cédric Mesnil <cslashm@pm.me>

//! Minimal hash traits for the krypteia workspace.
//!
//! A deliberately small, RustCrypto-`digest`-inspired surface — just
//! enough for the workspace's own generic code (PRFs, MGF1, the FIPS
//! 204/205 message-encoding helpers) to be written once over any hash.
//! Output sizes are passed as caller-provided slices to keep the trait
//! `no_std` and allocation-free.

/// A fixed-output hash function (SHA-2, SHA-3, …).
pub trait Digest: Sized {
    /// The digest length in octets.
    const OUTPUT_LEN: usize;

    /// The internal block size in octets — the rate for the
    /// Merkle–Damgård / sponge construction. Needed by keyed
    /// constructions such as HMAC.
    const BLOCK_LEN: usize;

    /// Create a fresh hasher.
    fn new() -> Self;

    /// Absorb a chunk of input. May be called repeatedly.
    fn update(&mut self, data: &[u8]);

    /// Consume the hasher and write the digest into `out`.
    ///
    /// `out` must be at least [`Digest::OUTPUT_LEN`] octets; only the
    /// first `OUTPUT_LEN` octets are written.
    fn finalize(self, out: &mut [u8]);

    /// One-shot convenience: `update(data)` then `finalize(out)`.
    fn digest(data: &[u8], out: &mut [u8]) {
        let mut h = Self::new();
        h.update(data);
        h.finalize(out);
    }
}

/// An extendable-output function (SHAKE128/256, cSHAKE, …).
pub trait Xof: Sized {
    /// The sponge rate in octets (bytes absorbed per permutation).
    const BLOCK_LEN: usize;

    /// Create a fresh XOF in the absorbing state.
    fn new() -> Self;

    /// Absorb a chunk of input. May be called repeatedly before the
    /// first `squeeze`.
    fn update(&mut self, data: &[u8]);

    /// Squeeze output bytes. May be called repeatedly to obtain an
    /// arbitrarily long stream.
    fn squeeze(&mut self, out: &mut [u8]);
}