Skip to main content

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 [KeyMaterialInternal] 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 [KeyMaterialInternal::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 [KeyMaterialInternal] 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::{KeyMaterialInternal, KeyType};
118// end of doc-only imports
119
120mod keccak;
121mod sha3;
122mod shake;
123/*** String constants ***/
124pub const SHA3_224_NAME: &str = "SHA3-224";
125pub const SHA3_256_NAME: &str = "SHA3-256";
126pub const SHA3_384_NAME: &str = "SHA3-384";
127pub const SHA3_512_NAME: &str = "SHA3-512";
128pub const SHAKE128_NAME: &str = "SHAKE128";
129pub const SHAKE256_NAME: &str = "SHAKE256";
130
131/*** pub types ***/
132pub use sha3::SHA3;
133pub use shake::SHAKE;
134pub type SHA3_224 = SHA3<SHA3_224Params>;
135pub type SHA3_256 = SHA3<SHA3_256Params>;
136pub type SHA3_384 = SHA3<SHA3_384Params>;
137pub type SHA3_512 = SHA3<SHA3_512Params>;
138pub type SHAKE128 = SHAKE<SHAKE128Params>;
139pub type SHAKE256 = SHAKE<SHAKE256Params>;
140
141/*** Param traits ***/
142trait SHA3Params: HashAlgParams {
143    const SIZE: KeccakSize;
144}
145
146// TODO: more elegant to macro this?
147impl Algorithm for SHA3_224 {
148    const ALG_NAME: &'static str = SHA3_224_NAME;
149    const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_112bit;
150}
151impl HashAlgParams for SHA3_224 {
152    const OUTPUT_LEN: usize = 28;
153    // const BLOCK_LEN: usize = 64;
154    const BLOCK_LEN: usize = 144; // FIPS 202 Table 3
155}
156pub struct SHA3_224Params;
157impl Algorithm for SHA3_224Params {
158    const ALG_NAME: &'static str = SHA3_224_NAME;
159    const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_112bit;
160}
161impl HashAlgParams for SHA3_224Params {
162    const OUTPUT_LEN: usize = 28;
163    // const BLOCK_LEN: usize = 64;
164    const BLOCK_LEN: usize = 144; // FIPS 202 Table 3
165}
166impl SHA3Params for SHA3_224Params {
167    const SIZE: KeccakSize = KeccakSize::_224;}
168
169impl Algorithm for SHA3_256 {
170    const ALG_NAME: &'static str = SHA3_256_NAME;
171    const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
172}
173impl HashAlgParams for SHA3_256 {
174    const OUTPUT_LEN: usize = 32;
175    // const BLOCK_LEN: usize = 64;
176    const BLOCK_LEN: usize = 136; // FIPS 202 Table 3
177}
178pub struct SHA3_256Params;
179impl Algorithm for SHA3_256Params {
180    const ALG_NAME: &'static str = SHA3_256_NAME;
181    const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
182}
183impl HashAlgParams for SHA3_256Params {
184    const OUTPUT_LEN: usize = 32;
185    // const BLOCK_LEN: usize = 64;
186    const BLOCK_LEN: usize = 136; // FIPS 202 Table 3
187}
188impl SHA3Params for SHA3_256Params {
189    const SIZE: KeccakSize = KeccakSize::_256;
190}
191
192pub struct SHA3_384Params;
193impl Algorithm for SHA3_384 {
194    const ALG_NAME: &'static str = SHA3_384_NAME;
195    const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_192bit;
196}
197impl HashAlgParams for SHA3_384 {
198    const OUTPUT_LEN: usize = 48;
199    // const BLOCK_LEN: usize = 128;
200    const BLOCK_LEN: usize = 104; // FIPS 202 Table 3
201}
202impl Algorithm for SHA3_384Params {
203    const ALG_NAME: &'static str = SHA3_384_NAME;
204    const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_192bit;
205}
206impl HashAlgParams for SHA3_384Params {
207    const OUTPUT_LEN: usize = 48;
208    // const BLOCK_LEN: usize = 128;
209    const BLOCK_LEN: usize = 104; // FIPS 202 Table 3
210}
211impl SHA3Params for SHA3_384Params {
212    const SIZE: KeccakSize = KeccakSize::_384;
213}
214
215pub struct SHA3_512Params;
216impl Algorithm for SHA3_512 {
217    const ALG_NAME: &'static str = SHA3_512_NAME;
218    const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_256bit;
219}
220impl HashAlgParams for SHA3_512 {
221    const OUTPUT_LEN: usize = 64;
222    // const BLOCK_LEN: usize = 128;
223    const BLOCK_LEN: usize = 72; // FIPS 202 Table 3
224}
225impl Algorithm for SHA3_512Params {
226    const ALG_NAME: &'static str = SHA3_512_NAME;
227    const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_256bit;
228}
229impl HashAlgParams for SHA3_512Params {
230    const OUTPUT_LEN: usize = 64;
231    // const BLOCK_LEN: usize = 128;
232    const BLOCK_LEN: usize = 72; // FIPS 202 Table 3
233}
234impl SHA3Params for SHA3_512Params {
235    const SIZE: KeccakSize = KeccakSize::_512;
236}
237
238trait SHAKEParams: Algorithm {
239    const SIZE: KeccakSize;
240}
241pub struct SHAKE128Params;
242impl Algorithm for SHAKE128Params {
243    const ALG_NAME: &'static str = SHAKE128_NAME;
244    const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
245}
246impl SHAKEParams for SHAKE128Params {
247    const SIZE: KeccakSize = KeccakSize::_128;
248}
249
250pub struct SHAKE256Params;
251impl Algorithm for SHAKE256Params {
252    const ALG_NAME: &'static str = SHAKE256_NAME;
253    const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_256bit;
254}
255impl SHAKEParams for SHAKE256Params {
256    const SIZE: KeccakSize = KeccakSize::_256;
257}
258