Skip to main content

lib_q_sha3/
lib.rs

1//! SHA-3 family for lib-Q: fixed-output **SHA-3** (FIPS 202), **SHAKE** and **cSHAKE** XOFs, **TurboSHAKE**. Raw pre-FIPS **Keccak** digests are in [`lib_q_keccak_digest`](https://github.com/Enkom-Tech/libQ/tree/main/lib-q-keccak-digest).
2//!
3//! # Re-exports
4//!
5//! - [`digest`]: the `digest` crate (version unified with the workspace).
6//! - [`Digest`], [`Update`], [`ExtendableOutput`], [`ExtendableOutputReset`], [`XofReader`], [`CustomizedInit`], [`CollisionResistance`]: common [`digest`](https://docs.rs/digest) traits, re-exported at the root. For XOFs use [`Update`], [`ExtendableOutput`], and [`XofReader`]. If a module imports both [`Digest`] and [`Update`], disambiguate [`Digest::update`] and [`Update::update`] with explicit trait paths.
7//!
8//! # Modules
9//!
10//! - [`cshake`]: cSHAKE-128/256 (NIST SP 800-185).
11//! - [`turbo_shake`]: TurboSHAKE-128/256 (12-round Keccak; used by RFC 9861 KangarooTwelve in [`lib_q_k12`](https://github.com/Enkom-Tech/libQ/tree/main/lib-q-k12)).
12//! - [`block_core`]: low-level cores and Keccak state for composition (e.g. K12); not needed for typical hashing.
13//!
14//! The rest of the API is re-exported at the crate root for discoverability. See the crate **README** (front page of docs) for standards links, feature flags, and **security** considerations.
15//!
16//! # Crate features
17//!
18//! Optional Cargo features: `alloc`, `oid`, `zeroize`, `asm` (see the README *Feature flags* table).
19//! On [docs.rs](https://docs.rs/lib-q-sha3), this crate is built with `all-features`; rustdoc
20//! marks APIs that require a Cargo feature automatically. The `zeroize` feature enables
21//! [`ZeroizeOnDrop`](https://docs.rs/digest/latest/digest/trait.ZeroizeOnDrop.html) (from the `zeroize` feature) on supported types.
22//!
23//! # `sha3_256` vs `Sha3_256`
24//!
25//! [`sha3_256`](fn.sha3_256.html) is a small convenience for one-shot hashing. Prefer [`Sha3_256`] with the [`Digest`] trait when reusing a hasher or when you need serialization / OID features.
26
27#![no_std]
28#![doc = include_str!("../README.md")]
29#![doc(
30    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
31    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
32)]
33#![forbid(unsafe_code)]
34#![warn(missing_docs, missing_debug_implementations)]
35
36pub use digest::{
37    self,
38    CollisionResistance,
39    CustomizedInit,
40    Digest,
41    ExtendableOutput,
42    ExtendableOutputReset,
43    Update,
44    XofReader,
45};
46
47/// Block-level types and Keccak cores for advanced composition (e.g. K12). Most callers should use the crate-root types.
48pub mod block_core;
49/// cSHAKE-128 and cSHAKE-256 (NIST SP 800-185). Types are re-exported at the crate root.
50pub mod cshake;
51/// Four-way batched TurboSHAKE (AVX2-accelerated leaf hashing for KangarooTwelve).
52pub mod parallel;
53/// TurboSHAKE-128 and TurboSHAKE-256. Types are re-exported at the crate root.
54pub mod turbo_shake;
55
56use block_core::{
57    SpongeHasherCore,
58    SpongeReaderCore,
59};
60#[doc(inline)]
61pub use cshake::{
62    CShake128,
63    CShake128Reader,
64    CShake256,
65    CShake256Reader,
66};
67use digest::consts::{
68    U0,
69    U16,
70    U28,
71    U32,
72    U48,
73    U64,
74    U72,
75    U104,
76    U136,
77    U144,
78    U168,
79};
80#[doc(inline)]
81pub use turbo_shake::{
82    TurboShake128,
83    TurboShake128Reader,
84    TurboShake256,
85    TurboShake256Reader,
86};
87
88/// One-shot **SHA3-256** (FIPS 202) over `data`.
89///
90/// Equivalent to [`Sha3_256`]`::`[`digest`](Digest::digest)`(data)` but may inline more aggressively. For incremental input or state serialization, use [`Sha3_256`] and [`Digest`].
91#[inline(always)]
92pub fn sha3_256(data: &[u8]) -> [u8; 32] {
93    let mut hasher = Sha3_256::new();
94    Digest::update(&mut hasher, data);
95    hasher.finalize().into()
96}
97
98// Paddings
99const SHA3_PAD: u8 = 0x06;
100const SHAKE_PAD: u8 = 0x1F;
101const CSHAKE_PAD: u8 = 0x04;
102
103const PLEN: usize = 25;
104const DEFAULT_ROUND_COUNT: usize = 24;
105
106/// XOR a (partial) block into the Keccak state lanes (little-endian).
107///
108/// Shared Keccak-sponge helper used by both the block API and cSHAKE; lives at the crate root
109/// so neither module has to depend on the other.
110pub(crate) fn xor_block(state: &mut [u64; PLEN], block: &[u8]) {
111    assert!(block.len() < 8 * PLEN);
112
113    let (chunks, rem) = block.as_chunks::<8>();
114    for (s, chunk) in state.iter_mut().zip(chunks) {
115        *s ^= u64::from_le_bytes(*chunk);
116    }
117
118    if !rem.is_empty() {
119        let mut buf = [0u8; 8];
120        buf[..rem.len()].copy_from_slice(rem);
121        let n = block.len() / 8;
122        state[n] ^= u64::from_le_bytes(buf);
123    }
124}
125
126digest::buffer_fixed!(
127    /// SHA-3-224 (FIPS 202).
128    pub struct Sha3_224(SpongeHasherCore<U144, U28, SHA3_PAD>);
129    oid: "2.16.840.1.101.3.4.2.7";
130    impl: FixedHashTraits;
131);
132digest::buffer_fixed!(
133    /// SHA-3-256 (FIPS 202).
134    pub struct Sha3_256(SpongeHasherCore<U136, U32, SHA3_PAD>);
135    oid: "2.16.840.1.101.3.4.2.8";
136    impl: FixedHashTraits;
137);
138digest::buffer_fixed!(
139    /// SHA-3-384 (FIPS 202).
140    pub struct Sha3_384(SpongeHasherCore<U104, U48, SHA3_PAD>);
141    oid: "2.16.840.1.101.3.4.2.9";
142    impl: FixedHashTraits;
143);
144digest::buffer_fixed!(
145    /// SHA-3-512 (FIPS 202).
146    pub struct Sha3_512(SpongeHasherCore<U72, U64, SHA3_PAD>);
147    oid: "2.16.840.1.101.3.4.2.10";
148    impl: FixedHashTraits;
149);
150digest::buffer_xof!(
151    /// SHAKE128 (FIPS 202, extendable output).
152    pub struct Shake128(SpongeHasherCore<U168, U0, SHAKE_PAD>);
153    oid: "2.16.840.1.101.3.4.2.11";
154    impl: XofHasherTraits;
155    /// SHAKE128 XOF output reader.
156    pub struct Shake128Reader(SpongeReaderCore<U168>);
157    impl: XofReaderTraits;
158);
159digest::buffer_xof!(
160    /// SHAKE256 (FIPS 202, extendable output).
161    pub struct Shake256(SpongeHasherCore<U136, U0, SHAKE_PAD>);
162    oid: "2.16.840.1.101.3.4.2.12";
163    impl: XofHasherTraits;
164    /// SHAKE256 XOF output reader.
165    pub struct Shake256Reader(SpongeReaderCore<U136>);
166    impl: XofReaderTraits;
167);
168
169impl CollisionResistance for Shake128 {
170    // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=31
171    type CollisionResistance = U16;
172}
173
174impl CollisionResistance for Shake256 {
175    // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=31
176    type CollisionResistance = U32;
177}