tiny_keccak/
tuple_hash.rs

1use crate::{left_encode, right_encode, CShake, Hasher, IntoXof, Xof};
2
3/// The `TupleHash` hash functions defined in [`SP800-185`].
4///
5/// `TupleHash` is designed to provide a generic, misuse-resistant way to combine a sequence of
6/// strings for hashing such that, for example, a `TupleHash` computed on the tuple (`"abc"` ,`"d"`) will
7/// produce a different hash value than a `TupleHash` computed on the tuple (`"ab"`,`"cd"`), even though
8/// all the remaining input parameters are kept the same, and the two resulting concatenated
9/// strings, without string encoding, are identical.
10///
11/// # Usage
12///
13/// ```toml
14/// [dependencies]
15/// tiny-keccak = { version = "2.0.0", features = ["tuple_hash"] }
16/// ```
17///
18/// [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf
19#[derive(Clone)]
20pub struct TupleHash {
21    state: CShake,
22}
23
24impl TupleHash {
25    /// Creates  new [`TupleHash`] hasher with a security level of 128 bits.
26    ///
27    /// [`TupleHash`]: struct.TupleHash.html
28    pub fn v128(custom_string: &[u8]) -> TupleHash {
29        TupleHash::new(custom_string, 128)
30    }
31
32    /// Creates  new [`TupleHash`] hasher with a security level of 256 bits.
33    ///
34    /// [`TupleHash`]: struct.TupleHash.html
35    pub fn v256(custom_string: &[u8]) -> TupleHash {
36        TupleHash::new(custom_string, 256)
37    }
38
39    fn new(custom_string: &[u8], bits: usize) -> TupleHash {
40        TupleHash {
41            state: CShake::new(b"TupleHash", custom_string, bits),
42        }
43    }
44}
45
46impl Hasher for TupleHash {
47    fn update(&mut self, input: &[u8]) {
48        self.state.update(left_encode(input.len() * 8).value());
49        self.state.update(input)
50    }
51
52    fn finalize(mut self, output: &mut [u8]) {
53        self.state.update(right_encode(output.len() * 8).value());
54        self.state.finalize(output)
55    }
56}
57
58/// The `TupleHashXOF` extendable-output functions defined in [`SP800-185`].
59///
60/// # Usage
61///
62/// ```toml
63/// [dependencies]
64/// tiny-keccak = { version = "2.0.0", features = ["tuple_hash"] }
65/// ```
66///
67/// # Example
68///
69/// ```
70/// # use tiny_keccak::{TupleHash, Xof, IntoXof, Hasher};
71/// let input = b"hello world";
72/// let mut output = [0u8; 64];
73/// let mut hasher = TupleHash::v256(b"");
74/// hasher.update(input);
75/// let mut xof = hasher.into_xof();
76/// xof.squeeze(&mut output[..32]);
77/// xof.squeeze(&mut output[32..]);
78/// ```
79///
80/// ---
81///
82/// [`TupleHashXof`] can be created only by using [`TupleHash::IntoXof`] interface.
83///
84///
85/// [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf
86/// [`TupleHashXof`]: struct.TupleHashXof.html
87/// [`TupleHash::IntoXof`]: struct.TupleHash.html#impl-IntoXof
88#[derive(Clone)]
89pub struct TupleHashXof {
90    state: CShake,
91}
92
93impl IntoXof for TupleHash {
94    type Xof = TupleHashXof;
95
96    fn into_xof(mut self) -> TupleHashXof {
97        self.state.update(right_encode(0).value());
98        TupleHashXof { state: self.state }
99    }
100}
101
102impl Xof for TupleHashXof {
103    fn squeeze(&mut self, output: &mut [u8]) {
104        self.state.squeeze(output)
105    }
106}