1const RC: [u64; 24] = [
17 0x0000_0000_0000_0001,
18 0x0000_0000_0000_8082,
19 0x8000_0000_0000_808a,
20 0x8000_0000_8000_8000,
21 0x0000_0000_0000_808b,
22 0x0000_0000_8000_0001,
23 0x8000_0000_8000_8081,
24 0x8000_0000_0000_8009,
25 0x0000_0000_0000_008a,
26 0x0000_0000_0000_0088,
27 0x0000_0000_8000_8009,
28 0x0000_0000_8000_000a,
29 0x0000_0000_8000_808b,
30 0x8000_0000_0000_008b,
31 0x8000_0000_0000_8089,
32 0x8000_0000_0000_8003,
33 0x8000_0000_0000_8002,
34 0x8000_0000_0000_0080,
35 0x0000_0000_0000_800a,
36 0x8000_0000_8000_000a,
37 0x8000_0000_8000_8081,
38 0x8000_0000_0000_8080,
39 0x0000_0000_8000_0001,
40 0x8000_0000_8000_8008,
41];
42
43const RHO: [u32; 25] = [
45 0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14,
50];
51
52fn keccak_f1600(a: &mut [u64; 25]) {
54 for &rc in &RC {
55 let mut c = [0u64; 5];
57 for (x, cx) in c.iter_mut().enumerate() {
58 *cx = a[x] ^ a[x + 5] ^ a[x + 10] ^ a[x + 15] ^ a[x + 20];
59 }
60 for x in 0..5 {
61 let d = c[(x + 4) % 5] ^ c[(x + 1) % 5].rotate_left(1);
62 for a in a.iter_mut().skip(x).step_by(5) {
63 *a ^= d;
64 }
65 }
66 let mut b = [0u64; 25];
68 for x in 0..5 {
69 for y in 0..5 {
70 b[y + 5 * ((2 * x + 3 * y) % 5)] = a[x + 5 * y].rotate_left(RHO[x + 5 * y]);
71 }
72 }
73 for y in 0..5 {
75 for x in 0..5 {
76 a[x + 5 * y] = b[x + 5 * y] ^ (!b[(x + 1) % 5 + 5 * y] & b[(x + 2) % 5 + 5 * y]);
77 }
78 }
79 a[0] ^= rc;
81 }
82}
83
84#[derive(Clone, Debug)]
87struct Keccak {
88 state: [u64; 25],
89 pos: usize,
91 rate: usize,
92}
93
94impl Keccak {
95 fn new(rate: usize) -> Self {
96 debug_assert!(rate <= 200 && rate.is_multiple_of(8));
97 Keccak {
98 state: [0; 25],
99 pos: 0,
100 rate,
101 }
102 }
103
104 fn xor_into(state: &mut [u64; 25], start: usize, data: &[u8]) {
105 for (j, &b) in data.iter().enumerate() {
106 let i = start + j;
107 state[i / 8] ^= (b as u64) << (8 * (i % 8));
108 }
109 }
110
111 fn absorb(&mut self, mut data: &[u8]) {
112 if self.pos > 0 {
113 let take = core::cmp::min(self.rate - self.pos, data.len());
114 Self::xor_into(&mut self.state, self.pos, &data[..take]);
115 self.pos += take;
116 data = &data[take..];
117 if self.pos == self.rate {
118 keccak_f1600(&mut self.state);
119 self.pos = 0;
120 }
121 }
122 while data.len() >= self.rate {
123 Self::xor_into(&mut self.state, 0, &data[..self.rate]);
124 keccak_f1600(&mut self.state);
125 data = &data[self.rate..];
126 }
127 if !data.is_empty() {
128 Self::xor_into(&mut self.state, 0, data);
129 self.pos = data.len();
130 }
131 }
132
133 fn pad(&mut self, dom: u8) {
136 debug_assert!(self.pos < self.rate);
137 Self::xor_into(&mut self.state, self.pos, &[dom]);
138 Self::xor_into(&mut self.state, self.rate - 1, &[0x80]);
139 keccak_f1600(&mut self.state);
140 self.pos = 0;
141 }
142
143 fn squeeze(&mut self, out: &mut [u8]) {
144 let mut out = out;
145 while !out.is_empty() {
146 let take = core::cmp::min(self.rate - self.pos, out.len());
147 for (j, b) in out[..take].iter_mut().enumerate() {
148 let i = self.pos + j;
149 *b = (self.state[i / 8] >> (8 * (i % 8))) as u8;
150 }
151 self.pos += take;
152 out = &mut out[take..];
153 if self.pos == self.rate {
154 keccak_f1600(&mut self.state);
155 self.pos = 0;
156 }
157 }
158 }
159}
160
161macro_rules! xof_type {
162 ($name:ident, $xof:ident, $rate:expr, $dom:expr, $doc:expr) => {
163 #[doc = $doc]
164 #[derive(Debug, Clone)]
165 pub struct $name {
166 k: Keccak,
167 }
168
169 impl $name {
170 pub fn new() -> Self {
172 $name {
173 k: Keccak::new($rate),
174 }
175 }
176
177 pub fn update(&mut self, data: &[u8]) {
179 self.k.absorb(data);
180 }
181
182 pub fn finalize_xof(self) -> $xof {
184 let mut k = self.k;
185 k.pad($dom);
186 $xof(k)
187 }
188 }
189
190 impl Default for $name {
191 fn default() -> Self {
192 Self::new()
193 }
194 }
195
196 #[doc = concat!("`", stringify!($name), "` 的挤出读取端(可重复调用 [`", stringify!($xof), "::fill`])。")]
197 #[derive(Debug, Clone)]
198 pub struct $xof(Keccak);
199
200 impl $xof {
201 pub fn fill(&mut self, out: &mut [u8]) {
203 self.0.squeeze(out);
204 }
205 }
206 };
207}
208
209xof_type!(
210 Shake128,
211 Shake128Xof,
212 168,
213 0x1f,
214 "SHAKE-128 可扩展输出函数(FIPS 202):rate = 168 字节(c = 256)。"
215);
216xof_type!(
217 Shake256,
218 Shake256Xof,
219 136,
220 0x1f,
221 "SHAKE-256 可扩展输出函数(FIPS 202):rate = 136 字节(c = 512)。"
222);
223
224pub fn sha3_256(data: &[u8]) -> [u8; 32] {
226 let mut k = Keccak::new(136);
227 k.absorb(data);
228 k.pad(0x06);
229 let mut out = [0u8; 32];
230 k.squeeze(&mut out);
231 out
232}
233
234pub fn sha3_512(data: &[u8]) -> [u8; 64] {
236 let mut k = Keccak::new(72);
237 k.absorb(data);
238 k.pad(0x06);
239 let mut out = [0u8; 64];
240 k.squeeze(&mut out);
241 out
242}
243
244#[cfg(test)]
245mod tests {
246 use super::*;
247
248 #[test]
250 fn streaming_matches_one_shot() {
251 let data: Vec<u8> = (0..700u32).map(|i| i as u8).collect();
252
253 for split in [0usize, 1, 63, 64, 65, 135, 136, 137, 699, 700] {
254 let (a, b) = data.split_at(split);
255 let mut s = Shake256::new();
256 s.update(a);
257 s.update(b);
258 let mut x = s.finalize_xof();
259 let mut chunked = [0u8; 100];
260 x.fill(&mut chunked[..37]);
261 x.fill(&mut chunked[37..]);
262 let mut once = Shake256::new();
263 once.update(&data);
264 let mut direct = once.finalize_xof();
265 let mut whole = [0u8; 100];
266 direct.fill(&mut whole);
267 assert_eq!(chunked, whole, "Shake256 split at {split}");
268 }
269
270 for split in [0usize, 1, 71, 72, 73, 135, 136, 137, 699] {
271 let (a, b) = data.split_at(split);
272 let mut s = Shake128::new();
273 s.update(a);
274 s.update(b);
275 let mut x = s.finalize_xof();
276 let mut chunked = [0u8; 500];
277 x.fill(&mut chunked[..300]);
278 x.fill(&mut chunked[300..]);
279 let mut once = Shake128::new();
280 once.update(&data);
281 let mut direct = once.finalize_xof();
282 let mut whole = [0u8; 500];
283 direct.fill(&mut whole);
284 assert_eq!(chunked, whole, "Shake128 split at {split}");
285 }
286 }
287
288 #[test]
291 fn fips203_appendix_a_anchors() {
292 let mut s = Shake128::new();
293 s.update(b"Input rho, to an XOF invocation!");
294 s.update(b"i");
295 s.update(b"j");
296 let mut x = s.finalize_xof();
297 let mut out = [0u8; 32];
298 x.fill(&mut out);
299 assert_eq!(
300 out.as_slice(),
301 hex32("0d2c3e65f754d074cb366cf1b099ae105cc40f018342509f15f1ba8a1a4144cb")
302 );
303
304 let mut s = Shake256::new();
305 s.update(b"Input s to an invocation of PRF2");
306 s.update(b"b");
307 let mut x = s.finalize_xof();
308 let mut prf = [0u8; 128];
309 x.fill(&mut prf);
310 assert_eq!(&prf[..16], &hex32("54c002415c2219b564d5c17b0df0c82f")[..]);
311
312 let mut s = Shake256::new();
313 s.update(b"Input to an invocation of J");
314 let mut x = s.finalize_xof();
315 let mut j = [0u8; 32];
316 x.fill(&mut j);
317 assert_eq!(
318 j.as_slice(),
319 hex32("a5292293d70c8eca049cbb475c48fabd625ed2b20785a18248504d3741196b52")
320 );
321 }
322
323 fn hex32(s: &str) -> Vec<u8> {
324 (0..s.len())
325 .step_by(2)
326 .map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("hex"))
327 .collect()
328 }
329}