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}