sha3/lib.rs
1//! SHA-3 Hash Functions
2//!
3//! This crate provides portable, pure Rust implementations of the SHA-3 hashing
4//! functions standardized in [FIPS 202].
5//!
6//! # Limitations
7//!
8//! This software is intended as a learning exercise and not for production use.
9//!
10//! Performance has thus far not been a priority. This implementation is likely
11//! orders of magnitude slower than optimized ones.
12//!
13//! We currently only expose functions to hash a complete byte slice `&[u8]`.
14//! Individual bits or multiple inputs that update the hash are currently not
15//! supported.
16//!
17//! We currently do not implement the SHAKE extendable-output functions
18//! described in [FIPS 202].
19//!
20//! # Example Usage
21//! ```
22//! # use sha3::sha3_256;
23//! #
24//! let message = b"your input bytes";
25//! let hash: [u8; 32] = sha3_256(message);
26//! let expected = "414d4b6d11a92aaeeebe35f9374942f563848d345631bf5537407252dca6b378";
27//! assert_eq!(expected, hex::encode(hash))
28//! ```
29//!
30//! [FIPS 202]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
31
32mod keccak;
33
34use crate::keccak::keccak;
35
36// TODO: remove code duplication. Use a macro?
37
38/// SHA-3 Hash with 224 bits (28 bytes) output.
39pub fn sha3_224(message: &[u8]) -> [u8; 28] {
40 let mut output = [0; 28];
41 const CAPACITY: usize = 224 * 2;
42 const RATE: usize = 1600 - CAPACITY;
43 keccak(RATE, CAPACITY, message, &mut output);
44 output
45}
46
47/// SHA-3 Hash with 256 bits (32 bytes) output.
48pub fn sha3_256(message: &[u8]) -> [u8; 32] {
49 let mut output = [0; 32];
50 const CAPACITY: usize = 256 * 2;
51 const RATE: usize = 1600 - CAPACITY;
52 keccak(RATE, CAPACITY, message, &mut output);
53 output
54}
55
56/// SHA-3 Hash with 384 bits (48 bytes) output.
57pub fn sha3_384(message: &[u8]) -> [u8; 48] {
58 let mut output = [0; 48];
59 const CAPACITY: usize = 384 * 2;
60 const RATE: usize = 1600 - CAPACITY;
61 keccak(RATE, CAPACITY, message, &mut output);
62 output
63}
64
65/// SHA-3 Hash with 512 bits (64 bytes) output.
66pub fn sha3_512(message: &[u8]) -> [u8; 64] {
67 let mut output = [0; 64];
68 const CAPACITY: usize = 512 * 2;
69 const RATE: usize = 1600 - CAPACITY;
70 keccak(RATE, CAPACITY, message, &mut output);
71 output
72}
73
74#[cfg(test)]
75mod tests {
76
77 use crate::sha3_256;
78
79 #[test]
80 fn can_hash() {
81 let input = b"some input string";
82 sha3_256(&input[..]);
83 }
84
85 #[cfg(not(miri))]
86 #[test]
87 fn compare_to_libcrux() {
88 // Go beyond one block
89 for i in 0..300 {
90 let input = vec![0; i];
91 let my_hash = sha3_256(&input[..]);
92 let other_hash = libcrux_sha3::sha256(&input);
93 assert_eq!(my_hash, other_hash.as_slice(), "len {i} hash differs");
94 }
95 }
96}