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