quantica/ml_dsa/sha3.rs
1//! SHA-3 / SHAKE high-level wrappers used by ML-DSA (FIPS 204).
2//!
3//! This module no longer carries its own copy of the Keccak
4//! permutation: it builds on top of the shared sponge core in
5//! `crate::sha3`. The ML-DSA-specific surface (`sha3_256`,
6//! `sha3_512`, `shake128`, `shake256`, `h_init`, `g_init`, plus the
7//! `KeccakState` re-export consumed by the rest of the algorithm) is
8//! unchanged.
9
10pub use crate::sha3::KeccakState;
11
12use crate::sha3::{SHA3_256_RATE, SHA3_512_RATE, SHAKE128_RATE, SHAKE256_RATE};
13
14/// Compute SHA3-256 over the input and return the 32-byte digest.
15pub fn sha3_256(input: &[u8]) -> [u8; 32] {
16 let mut state = KeccakState::new(SHA3_256_RATE, 0x06);
17 state.absorb(input);
18 let mut out = [0u8; 32];
19 state.squeeze(&mut out);
20 out
21}
22
23/// Compute SHA3-512 over the input and return the 64-byte digest.
24pub fn sha3_512(input: &[u8]) -> [u8; 64] {
25 let mut state = KeccakState::new(SHA3_512_RATE, 0x06);
26 state.absorb(input);
27 let mut out = [0u8; 64];
28 state.squeeze(&mut out);
29 out
30}
31
32/// Create a new SHAKE128 extendable-output function (XOF) context.
33///
34/// SHAKE128 uses a rate of 168 bytes and domain separator 0x1f. Used
35/// by ML-DSA for the G function (matrix expansion).
36pub fn shake128() -> KeccakState {
37 KeccakState::new(SHAKE128_RATE, 0x1f)
38}
39
40/// Create a new SHAKE256 extendable-output function (XOF) context.
41///
42/// SHAKE256 uses a rate of 136 bytes and domain separator 0x1f. Used
43/// by ML-DSA for the H function (hashing, key derivation, signing).
44pub fn shake256() -> KeccakState {
45 KeccakState::new(SHAKE256_RATE, 0x1f)
46}
47
48/// Convenience function: absorb `input` into SHAKE256 and squeeze
49/// into `out`.
50pub fn shake256_digest(input: &[u8], out: &mut [u8]) {
51 let mut state = shake256();
52 state.absorb(input);
53 state.squeeze(out);
54}
55
56/// Convenience function: absorb `input` into SHAKE128 and squeeze
57/// into `out`.
58pub fn shake128_digest(input: &[u8], out: &mut [u8]) {
59 let mut state = shake128();
60 state.absorb(input);
61 state.squeeze(out);
62}
63
64/// Initialize the ML-DSA H function (SHAKE256 with streaming
65/// interface). Alias for [`shake256`], named to match FIPS 204.
66pub fn h_init() -> KeccakState {
67 shake256()
68}
69
70/// Initialize the ML-DSA G function (SHAKE128 with streaming
71/// interface). Alias for [`shake128`], named to match FIPS 204.
72pub fn g_init() -> KeccakState {
73 shake128()
74}