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}