krypteia-quantica 0.1.0

Pure-Rust post-quantum cryptography: FIPS 203 ML-KEM, FIPS 204 ML-DSA, and FIPS 205 SLH-DSA. First-order arithmetic masking, shuffled NTT, FORS recompute-and-compare redundancy, constant-time rejection sampling. Targets embedded (no_std), STM32 M0/M4/M33, ESP32-C3 RISC-V. Zero runtime dependencies.
Documentation
//! SHA-3 / SHAKE high-level wrappers used by ML-DSA (FIPS 204).
//!
//! This module no longer carries its own copy of the Keccak
//! permutation: it builds on top of the shared sponge core in
//! `crate::sha3`. The ML-DSA-specific surface (`sha3_256`,
//! `sha3_512`, `shake128`, `shake256`, `h_init`, `g_init`, plus the
//! `KeccakState` re-export consumed by the rest of the algorithm) is
//! unchanged.

pub use crate::sha3::KeccakState;

use crate::sha3::{SHA3_256_RATE, SHA3_512_RATE, SHAKE128_RATE, SHAKE256_RATE};

/// Compute SHA3-256 over the input and return the 32-byte digest.
pub fn sha3_256(input: &[u8]) -> [u8; 32] {
    let mut state = KeccakState::new(SHA3_256_RATE, 0x06);
    state.absorb(input);
    let mut out = [0u8; 32];
    state.squeeze(&mut out);
    out
}

/// Compute SHA3-512 over the input and return the 64-byte digest.
pub fn sha3_512(input: &[u8]) -> [u8; 64] {
    let mut state = KeccakState::new(SHA3_512_RATE, 0x06);
    state.absorb(input);
    let mut out = [0u8; 64];
    state.squeeze(&mut out);
    out
}

/// Create a new SHAKE128 extendable-output function (XOF) context.
///
/// SHAKE128 uses a rate of 168 bytes and domain separator 0x1f. Used
/// by ML-DSA for the G function (matrix expansion).
pub fn shake128() -> KeccakState {
    KeccakState::new(SHAKE128_RATE, 0x1f)
}

/// Create a new SHAKE256 extendable-output function (XOF) context.
///
/// SHAKE256 uses a rate of 136 bytes and domain separator 0x1f. Used
/// by ML-DSA for the H function (hashing, key derivation, signing).
pub fn shake256() -> KeccakState {
    KeccakState::new(SHAKE256_RATE, 0x1f)
}

/// Convenience function: absorb `input` into SHAKE256 and squeeze
/// into `out`.
pub fn shake256_digest(input: &[u8], out: &mut [u8]) {
    let mut state = shake256();
    state.absorb(input);
    state.squeeze(out);
}

/// Convenience function: absorb `input` into SHAKE128 and squeeze
/// into `out`.
pub fn shake128_digest(input: &[u8], out: &mut [u8]) {
    let mut state = shake128();
    state.absorb(input);
    state.squeeze(out);
}

/// Initialize the ML-DSA H function (SHAKE256 with streaming
/// interface). Alias for [`shake256`], named to match FIPS 204.
pub fn h_init() -> KeccakState {
    shake256()
}

/// Initialize the ML-DSA G function (SHAKE128 with streaming
/// interface). Alias for [`shake128`], named to match FIPS 204.
pub fn g_init() -> KeccakState {
    shake128()
}