bouncycastle_sha3/lib.rs
1//! Implements SHA3 as per NIST FIPS 202.
2//!
3//! # Examples
4//! ## Hash
5//! Hash functionality is accessed via the [Hash] trait,
6//! which is implemented by [SHA3_224], [SHA3_256], [SHA3_384] and [SHA3_512].
7//!
8//! The simplest usage is via the one-shot functions.
9//! ```
10//! use bouncycastle_core_interface::traits::Hash;
11//! use bouncycastle_sha3 as sha3;
12//!
13//! let data: &[u8] = b"Hello, world!";
14//! let output: Vec<u8> = sha3::SHA3_256::new().hash(data);
15//! ```
16//!
17//! More advanced usage will require creating a SHA3 or SHAKE object to hold state between successive calls,
18//! for example if input is received in chunks and not all available at the same time:
19//!
20//! ```
21//! use bouncycastle_core_interface::traits::Hash;
22//! use bouncycastle_sha3 as sha3;
23//!
24//! let data: &[u8] = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F
25//! \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F
26//! \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F
27//! \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
28//! let mut sha3 = sha3::SHA3_256::new();
29//!
30//! for chunk in data.chunks(16) {
31//! sha3.do_update(chunk);
32//! }
33//!
34//! let output: Vec<u8> = sha3.do_final();
35//! ```
36//!
37//! It is also possible to provide input where the final byte contains less than 8 bits of data (ie is a partial byte);
38//! for example, the following code uses only 3 bits of the final byte:
39//! ```
40//! use bouncycastle_core_interface::traits::Hash;
41//! use bouncycastle_sha3 as sha3;
42//!
43//! let data: &[u8] = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
44//! let mut sha3 = sha3::SHA3_256::new();
45//! sha3.do_update(&data[..data.len()-1]);
46//! let final_byte = data[data.len()-1];
47//! let output: Vec<u8> = sha3.do_final_partial_bits(final_byte, 3).expect("Failed to finalize hash state.");
48//! ```
49//!
50//! ## XOF
51//! SHA3 offers Extendable-Output Functions in the form of SHAKE, which is accessed through the [XOF] trait,
52//! which is implemented by [SHAKE128] and [SHAKE256].
53//! The difference from [Hash] is that SHAKE can produce output of any length.
54//!
55//! The simplest usage is via the static functions. The following example produces a 16 byte (128-bit) and 16KiB output:
56//!```
57//! use bouncycastle_core_interface::traits::XOF;
58//! use bouncycastle_sha3 as sha3;
59//!
60//! let data: &[u8] = b"Hello, world!";
61//! let output_16byte: Vec<u8> = sha3::SHAKE128::new().hash_xof(data, 16);
62//! let output_16KiB: Vec<u8> = sha3::SHAKE128::new().hash_xof(data, 16 * 1024);
63//! ```
64//!
65//! As with [Hash] above, the [XOF] trait has streaming APIs in the form of [XOF::absorb] and [XOF::squeeze].
66//! Unlike [Hash::do_final], [XOF::squeeze] can be called multiple times.
67//! The following code produces the same output as the previous example:
68//!```
69//! use bouncycastle_core_interface::traits::XOF;
70//! use bouncycastle_sha3 as sha3;
71//!
72//! let data: &[u8] = b"Hello, world!";
73//! let mut shake = sha3::SHAKE128::new();
74//! shake.absorb(data).expect("Failed to absorb data.");
75//! let output_16byte: Vec<u8> = shake.squeeze(16).expect("Is infallible");
76//!
77//! let mut shake = sha3::SHAKE128::new();
78//! let mut output_16KiB: Vec<u8> = vec![];
79//! for i in 0..16 { output_16KiB.extend_from_slice(&shake.squeeze(1024).expect("Is infallible")) }
80//! ```
81//!
82//! ## KDF
83//! SHA3 offers Key Derivation Functions in the form of KDF, which is accessed through the [KDF] trait,
84//! which is implemented by all SHA3 and SHAKE variants.
85//! [KDF] acts on [KeyMaterialSized] objects as both the input and output values.
86//! In the case of SHA3, the [KDF] interfaces are simple wrapper functions around the underlying SHA3 or SHAKE
87//! primitive that correctly maintains the length and entropy metadata of the key material that it is acting on.
88//! This is intended to act as a developer ait to prevent some classes of developer mistakes, such as
89//! deriving a cryptographic key from uninitialized (aka zeroized) input key material, or using low-entropy
90//! input key material to derive a MAC, symmetric, or asymmetric key.
91//!
92//! ```
93//! use bouncycastle_core_interface::traits::KDF;
94//! use bouncycastle_core_interface::key_material::{KeyMaterial256, KeyType};
95//! use bouncycastle_sha3 as sha3;
96//!
97//! let input_key = KeyMaterial256::from_bytes(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F").unwrap();
98//! let output_key = sha3::SHA3_256::new().derive_key(&input_key, b"Additional input").unwrap();
99//!```
100//! In the previous example, since [KeyMaterialSized::from_bytes] cannot know the amount of entropy in the input data,
101//! it automatically tags it as [KeyType::BytesLowEntropy], and thus [SHA3::derive_key] produces an output key
102//! which also has type [KeyType::BytesLowEntropy].
103//! This would also be the case even if the input had type
104//! [KeyType::BytesFullEntropy] since the input [KeyMaterialSized] is 16 bytes but [SHA3_256] needs at least 32 bytes of
105//! full-entropy input key material in order to be able to produce full entropy output key material.
106
107#![forbid(unsafe_code)]
108#![allow(private_bounds)]
109
110use crate::keccak::{KeccakSize};
111use bouncycastle_core_interface::traits::{Algorithm, HashAlgParams, SecurityStrength};
112
113// imports needed for docs
114#[allow(unused_imports)]
115use bouncycastle_core_interface::traits::{Hash, KDF, XOF};
116#[allow(unused_imports)]
117use bouncycastle_core_interface::key_material::{KeyMaterialSized, KeyType};
118// end of doc-only imports
119
120mod keccak;
121mod sha3;
122mod shake;
123
124/*** String constants ***/
125pub const SHA3_224_NAME: &str = "SHA3-224";
126pub const SHA3_256_NAME: &str = "SHA3-256";
127pub const SHA3_384_NAME: &str = "SHA3-384";
128pub const SHA3_512_NAME: &str = "SHA3-512";
129pub const SHAKE128_NAME: &str = "SHAKE128";
130pub const SHAKE256_NAME: &str = "SHAKE256";
131
132/*** pub types ***/
133pub use sha3::SHA3;
134pub use shake::SHAKE;
135pub type SHA3_224 = SHA3<SHA3_224Params>;
136pub type SHA3_256 = SHA3<SHA3_256Params>;
137pub type SHA3_384 = SHA3<SHA3_384Params>;
138pub type SHA3_512 = SHA3<SHA3_512Params>;
139pub type SHAKE128 = SHAKE<SHAKE128Params>;
140pub type SHAKE256 = SHAKE<SHAKE256Params>;
141
142/*** Param traits ***/
143
144/// Private trait on purpose so that only the NIST-approved params can be used.
145trait SHA3Params: HashAlgParams {
146 const SIZE: KeccakSize;
147}
148
149// TODO: more elegant to macro this?
150impl Algorithm for SHA3_224 {
151 const ALG_NAME: &'static str = SHA3_224_NAME;
152 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_112bit;
153}
154impl HashAlgParams for SHA3_224 {
155 const OUTPUT_LEN: usize = 28;
156 // const BLOCK_LEN: usize = 64;
157 const BLOCK_LEN: usize = 144; // FIPS 202 Table 3
158}
159pub struct SHA3_224Params;
160impl Algorithm for SHA3_224Params {
161 const ALG_NAME: &'static str = SHA3_224_NAME;
162 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_112bit;
163}
164impl HashAlgParams for SHA3_224Params {
165 const OUTPUT_LEN: usize = 28;
166 // const BLOCK_LEN: usize = 64;
167 const BLOCK_LEN: usize = 144; // FIPS 202 Table 3
168}
169impl SHA3Params for SHA3_224Params {
170 const SIZE: KeccakSize = KeccakSize::_224;}
171
172impl Algorithm for SHA3_256 {
173 const ALG_NAME: &'static str = SHA3_256_NAME;
174 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
175}
176impl HashAlgParams for SHA3_256 {
177 const OUTPUT_LEN: usize = 32;
178 // const BLOCK_LEN: usize = 64;
179 const BLOCK_LEN: usize = 136; // FIPS 202 Table 3
180}
181pub struct SHA3_256Params;
182impl Algorithm for SHA3_256Params {
183 const ALG_NAME: &'static str = SHA3_256_NAME;
184 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
185}
186impl HashAlgParams for SHA3_256Params {
187 const OUTPUT_LEN: usize = 32;
188 // const BLOCK_LEN: usize = 64;
189 const BLOCK_LEN: usize = 136; // FIPS 202 Table 3
190}
191impl SHA3Params for SHA3_256Params {
192 const SIZE: KeccakSize = KeccakSize::_256;
193}
194
195pub struct SHA3_384Params;
196impl Algorithm for SHA3_384 {
197 const ALG_NAME: &'static str = SHA3_384_NAME;
198 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_192bit;
199}
200impl HashAlgParams for SHA3_384 {
201 const OUTPUT_LEN: usize = 48;
202 // const BLOCK_LEN: usize = 128;
203 const BLOCK_LEN: usize = 104; // FIPS 202 Table 3
204}
205impl Algorithm for SHA3_384Params {
206 const ALG_NAME: &'static str = SHA3_384_NAME;
207 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_192bit;
208}
209impl HashAlgParams for SHA3_384Params {
210 const OUTPUT_LEN: usize = 48;
211 // const BLOCK_LEN: usize = 128;
212 const BLOCK_LEN: usize = 104; // FIPS 202 Table 3
213}
214impl SHA3Params for SHA3_384Params {
215 const SIZE: KeccakSize = KeccakSize::_384;
216}
217
218pub struct SHA3_512Params;
219impl Algorithm for SHA3_512 {
220 const ALG_NAME: &'static str = SHA3_512_NAME;
221 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_256bit;
222}
223impl HashAlgParams for SHA3_512 {
224 const OUTPUT_LEN: usize = 64;
225 // const BLOCK_LEN: usize = 128;
226 const BLOCK_LEN: usize = 72; // FIPS 202 Table 3
227}
228impl Algorithm for SHA3_512Params {
229 const ALG_NAME: &'static str = SHA3_512_NAME;
230 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_256bit;
231}
232impl HashAlgParams for SHA3_512Params {
233 const OUTPUT_LEN: usize = 64;
234 // const BLOCK_LEN: usize = 128;
235 const BLOCK_LEN: usize = 72; // FIPS 202 Table 3
236}
237impl SHA3Params for SHA3_512Params {
238 const SIZE: KeccakSize = KeccakSize::_512;
239}
240
241trait SHAKEParams: Algorithm {
242 const SIZE: KeccakSize;
243}
244pub struct SHAKE128Params;
245impl Algorithm for SHAKE128Params {
246 const ALG_NAME: &'static str = SHAKE128_NAME;
247 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
248}
249impl SHAKEParams for SHAKE128Params {
250 const SIZE: KeccakSize = KeccakSize::_128;
251}
252
253pub struct SHAKE256Params;
254impl Algorithm for SHAKE256Params {
255 const ALG_NAME: &'static str = SHAKE256_NAME;
256 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_256bit;
257}
258impl SHAKEParams for SHAKE256Params {
259 const SIZE: KeccakSize = KeccakSize::_256;
260}
261