ic_sha3/
lib.rs

1//! Wrappers around SHA-3 and related hash functions.
2
3#![forbid(unsafe_code)]
4#![warn(rust_2018_idioms)]
5#![forbid(missing_docs)]
6#![warn(future_incompatible)]
7
8/// Keccak-256 hash function.
9///
10/// Hash function with constant 256-bit (32 bytes) output.
11/// Note that this is not the same as the [SHA-3 standard](https://csrc.nist.gov/pubs/fips/202/final)
12/// which uses a different padding scheme. Keccak-256 is the hash function used for example in Ethereum.
13///
14/// # Examples
15///
16/// An example of using Keccak-256 to hash data piece by piece:
17/// ```
18/// use std::io::Write;
19/// use ic_sha3::Keccak256;
20///
21/// let mut hasher = Keccak256::new();
22/// hasher.write("Hello ").write("world!");
23/// let result = hasher.finalize();
24/// assert_eq!(result[..], hex::decode("ecd0e108a98e192af1d2c25055f4e3bed784b5c877204e73219a5203251feaab")
25/// .expect("valid hex string")[..]);
26/// ```
27///
28/// An example of using Keccak-256 to hash an entire buffer in one go:
29/// ```
30/// use ic_sha3::Keccak256;
31///
32/// let result = Keccak256::hash("Hello world!");
33/// assert_eq!(result[..], hex::decode("ecd0e108a98e192af1d2c25055f4e3bed784b5c877204e73219a5203251feaab")
34/// .expect("valid hex string")[..]);
35/// ```
36#[derive(Default)]
37pub struct Keccak256 {
38    state: sha3::Keccak256,
39}
40
41impl Keccak256 {
42    /// Byte length of the Keccak-256 output.
43    pub const DIGEST_LEN: usize = 32;
44
45    /// Creates a new Keccak256 hasher.
46    pub fn new() -> Self {
47        Self::default()
48    }
49
50    /// Updates the state using the provided `data`.
51    pub fn write<T: AsRef<[u8]>>(&mut self, data: T) -> &mut Self {
52        use sha3::Digest;
53        self.state.update(data);
54        self
55    }
56
57    /// Hashes the given `data`.
58    pub fn hash<T: AsRef<[u8]>>(data: T) -> [u8; Self::DIGEST_LEN] {
59        let mut hasher = Keccak256::new();
60        hasher.write(data);
61        hasher.finalize()
62    }
63
64    /// Finishes the hashing.
65    pub fn finalize(self) -> [u8; Self::DIGEST_LEN] {
66        use sha3::Digest;
67        self.state.finalize().into()
68    }
69}
70
71#[derive(Clone, Default)]
72/// SHAKE256 hasher state.
73pub struct Shake256 {
74    state: sha3::Shake256,
75}
76
77impl Shake256 {
78    /// Creates a new instance.
79    pub fn new() -> Self {
80        Self::default()
81    }
82
83    /// Updates the state using the provided `data`.
84    pub fn update(&mut self, data: impl AsRef<[u8]>) -> &mut Self {
85        use sha3::digest::Update;
86        self.state.update(data.as_ref());
87        self
88    }
89
90    /// Retrieves an XOF reader and consumes the hasher instance.
91    pub fn finalize_xof(self) -> Shake256XofReader {
92        use sha3::digest::ExtendableOutput;
93        Shake256XofReader {
94            state: self.state.finalize_xof(),
95        }
96    }
97}
98
99/// SHAKE256 reader state.
100pub struct Shake256XofReader {
101    state: sha3::Shake256Reader,
102}
103
104impl Shake256XofReader {
105    /// Reads XOF output into a buffer. Can be called an unlimited number of times.
106    pub fn read(&mut self, buf: &mut [u8]) {
107        use sha3::digest::XofReader;
108        self.state.read(buf)
109    }
110}