tiny_keccak/
kmac.rs

1use crate::{bits_to_rate, left_encode, right_encode, CShake, Hasher, IntoXof, Xof};
2
3/// The `KMAC` pseudo-random functions defined in [`SP800-185`].
4///
5/// The KECCAK Message Authentication Code (`KMAC`) algorithm is a `PRF` and keyed hash function based
6/// on KECCAK. It provides variable-length output, and unlike [`SHAKE`] and [`cSHAKE`], altering the
7/// requested output length generates a new, unrelated output. KMAC has two variants, [`KMAC128`] and
8/// [`KMAC256`], built from [`cSHAKE128`] and [`cSHAKE256`], respectively. The two variants differ somewhat in
9/// their technical security properties.
10///
11/// # Usage
12///
13/// ```toml
14/// [dependencies]
15/// tiny-keccak = { version = "2.0.0", features = ["kmac"] }
16/// ```
17///
18/// [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf
19/// [`KMAC128`]: struct.Kmac.html#method.v128
20/// [`KMAC256`]: struct.Kmac.html#method.v256
21/// [`SHAKE`]: struct.Shake.html
22/// [`cSHAKE`]: struct.CShake.html
23/// [`cSHAKE128`]: struct.CShake.html#method.v128
24/// [`cSHAKE256`]: struct.CShake.html#method.v256
25#[derive(Clone)]
26pub struct Kmac {
27    state: CShake,
28}
29
30impl Kmac {
31    /// Creates  new [`Kmac`] hasher with a security level of 128 bits.
32    ///
33    /// [`Kmac`]: struct.Kmac.html
34    pub fn v128(key: &[u8], custom_string: &[u8]) -> Kmac {
35        Kmac::new(key, custom_string, 128)
36    }
37
38    /// Creates  new [`Kmac`] hasher with a security level of 256 bits.
39    ///
40    /// [`Kmac`]: struct.Kmac.html
41    pub fn v256(key: &[u8], custom_string: &[u8]) -> Kmac {
42        Kmac::new(key, custom_string, 256)
43    }
44
45    fn new(key: &[u8], custom_string: &[u8], bits: usize) -> Kmac {
46        let rate = bits_to_rate(bits);
47        let mut state = CShake::new(b"KMAC", custom_string, bits);
48        state.update(left_encode(rate).value());
49        state.update(left_encode(key.len() * 8).value());
50        state.update(key);
51        state.fill_block();
52        Kmac { state }
53    }
54}
55
56impl Hasher for Kmac {
57    fn update(&mut self, input: &[u8]) {
58        self.state.update(input)
59    }
60
61    fn finalize(mut self, output: &mut [u8]) {
62        self.state.update(right_encode(output.len() * 8).value());
63        self.state.finalize(output)
64    }
65}
66
67/// The `KMACXOF` extendable-output functions defined in [`SP800-185`].
68///
69/// # Usage
70///
71/// ```toml
72/// [dependencies]
73/// tiny-keccak = { version = "2.0.0", features = ["kmac"] }
74/// ```
75///
76/// # Example
77///
78/// ```
79/// # use tiny_keccak::{Kmac, Xof, IntoXof, Hasher};
80/// let input = b"hello world";
81/// let mut output = [0u8; 64];
82/// let mut kmac = Kmac::v256(b"", b"");
83/// kmac.update(input);
84/// let mut xof = kmac.into_xof();
85/// xof.squeeze(&mut output[..32]);
86/// xof.squeeze(&mut output[32..]);
87/// ```
88///
89/// ---
90///
91/// [`KmacXof`] can be created only by using [`Kmac::IntoXof`] interface.
92///
93/// [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf
94/// [`KmacXof`]: struct.KmacXof.html
95/// [`Kmac::IntoXof`]: struct.Kmac.html#impl-IntoXof
96#[derive(Clone)]
97pub struct KmacXof {
98    state: CShake,
99}
100
101impl IntoXof for Kmac {
102    type Xof = KmacXof;
103
104    fn into_xof(mut self) -> Self::Xof {
105        self.state.update(right_encode(0).value());
106        KmacXof { state: self.state }
107    }
108}
109
110impl Xof for KmacXof {
111    fn squeeze(&mut self, output: &mut [u8]) {
112        self.state.squeeze(output)
113    }
114}