dcrypt_algorithms/hash/shake/
mod.rs1#[cfg(feature = "alloc")]
9use crate::alloc_prelude::*;
10use dcrypt_internal::zeroing::{Zeroize, ZeroizeOnDrop, Zeroizing};
11
12use crate::error::Result;
13use crate::hash::{HashAlgorithm, HashFunction};
14use crate::types::Digest;
15
16pub const SHAKE128_OUTPUT_SIZE: usize = 32; pub const SHAKE256_OUTPUT_SIZE: usize = 64; const SHAKE128_RATE: usize = 168; const SHAKE256_RATE: usize = 136; const KECCAK_ROUNDS: usize = 24;
28const KECCAK_STATE_SIZE: usize = 25; const RC: [u64; KECCAK_ROUNDS] = [
32 0x0000000000000001,
33 0x0000000000008082,
34 0x800000000000808A,
35 0x8000000080008000,
36 0x000000000000808B,
37 0x0000000080000001,
38 0x8000000080008081,
39 0x8000000000008009,
40 0x000000000000008A,
41 0x0000000000000088,
42 0x0000000080008009,
43 0x000000008000000A,
44 0x000000008000808B,
45 0x800000000000008B,
46 0x8000000000008089,
47 0x8000000000008003,
48 0x8000000000008002,
49 0x8000000000000080,
50 0x000000000000800A,
51 0x800000008000000A,
52 0x8000000080008081,
53 0x8000000000008080,
54 0x0000000080000001,
55 0x8000000080008008,
56];
57
58const RHO: [u32; 24] = [
60 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
61];
62
63const PI: [usize; 24] = [
65 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
66];
67
68pub enum Shake128Algorithm {}
70
71pub enum Shake256Algorithm {}
73
74impl HashAlgorithm for Shake128Algorithm {
76 const OUTPUT_SIZE: usize = SHAKE128_OUTPUT_SIZE;
77 const BLOCK_SIZE: usize = SHAKE128_RATE;
78 const ALGORITHM_ID: &'static str = "SHAKE-128";
79}
80
81impl HashAlgorithm for Shake256Algorithm {
82 const OUTPUT_SIZE: usize = SHAKE256_OUTPUT_SIZE;
83 const BLOCK_SIZE: usize = SHAKE256_RATE;
84 const ALGORITHM_ID: &'static str = "SHAKE-256";
85}
86
87#[derive(Clone)]
89pub struct Shake128 {
90 state: [u64; KECCAK_STATE_SIZE],
91 buffer: [u8; SHAKE128_RATE],
92 buffer_idx: usize,
93}
94
95#[derive(Clone)]
97pub struct Shake256 {
98 state: [u64; KECCAK_STATE_SIZE],
99 buffer: [u8; SHAKE256_RATE],
100 buffer_idx: usize,
101}
102
103macro_rules! impl_shake_zeroize {
104 ($name:ident) => {
105 impl Zeroize for $name {
106 fn zeroize(&mut self) {
107 self.state.zeroize();
108 self.buffer.zeroize();
109 self.buffer_idx.zeroize();
110 }
111 }
112
113 impl Drop for $name {
114 fn drop(&mut self) {
115 self.zeroize();
116 }
117 }
118
119 impl ZeroizeOnDrop for $name {}
120 };
121}
122
123impl_shake_zeroize!(Shake128);
124impl_shake_zeroize!(Shake256);
125
126fn keccak_f1600(state: &mut [u64; KECCAK_STATE_SIZE]) {
128 for &rc in RC.iter().take(KECCAK_ROUNDS) {
129 let mut c = Zeroizing::new([0u64; 5]);
131 for x in 0..5 {
132 c[x] = state[x] ^ state[x + 5] ^ state[x + 10] ^ state[x + 15] ^ state[x + 20];
133 }
134 let mut d = Zeroizing::new([0u64; 5]);
135 for x in 0..5 {
136 d[x] = c[(x + 4) % 5] ^ c[(x + 1) % 5].rotate_left(1);
137 }
138 for y in 0..5 {
139 for x in 0..5 {
140 state[x + 5 * y] ^= d[x];
141 }
142 }
143
144 let mut b = Zeroizing::new([0u64; KECCAK_STATE_SIZE]);
146 let mut x = 1;
147 let mut y = 0;
148 b[0] = state[0];
149 for i in 0..24 {
150 let idx = x + 5 * y;
151 b[PI[i]] = state[idx].rotate_left(RHO[i]);
152 let temp = y;
153 y = (2 * x + 3 * y) % 5;
154 x = temp;
155 }
156
157 for y in 0..5 {
159 for x in 0..5 {
160 let idx = x + 5 * y;
161 state[idx] = b[idx] ^ ((!b[(x + 1) % 5 + 5 * y]) & b[(x + 2) % 5 + 5 * y]);
162 }
163 }
164
165 state[0] ^= rc;
167 }
168}
169
170impl Shake128 {
171 fn init() -> Self {
172 Shake128 {
173 state: [0u64; KECCAK_STATE_SIZE],
174 buffer: [0u8; SHAKE128_RATE],
175 buffer_idx: 0,
176 }
177 }
178
179 fn update_internal(&mut self, data: &[u8]) -> Result<()> {
180 let mut idx = 0;
181
182 if self.buffer_idx > 0 {
184 let to_copy = (SHAKE128_RATE - self.buffer_idx).min(data.len());
185 self.buffer[self.buffer_idx..self.buffer_idx + to_copy]
186 .copy_from_slice(&data[..to_copy]);
187 self.buffer_idx += to_copy;
188 idx += to_copy;
189
190 if self.buffer_idx == SHAKE128_RATE {
191 for (i, chunk) in self.buffer.chunks_exact(8).enumerate() {
193 let mut lane = 0u64;
194 for (j, &b) in chunk.iter().enumerate() {
195 lane |= (b as u64) << (8 * j);
196 }
197 self.state[i] ^= lane;
198 lane.zeroize();
199 }
200 keccak_f1600(&mut self.state);
201 self.buffer.zeroize();
202 self.buffer_idx = 0;
203 }
204 }
205
206 while idx + SHAKE128_RATE <= data.len() {
208 let block = &data[idx..idx + SHAKE128_RATE];
209 for (i, chunk) in block.chunks_exact(8).enumerate() {
210 let mut lane = 0u64;
211 for (j, &b) in chunk.iter().enumerate() {
212 lane |= (b as u64) << (8 * j);
213 }
214 self.state[i] ^= lane;
215 lane.zeroize();
216 }
217 keccak_f1600(&mut self.state);
218 idx += SHAKE128_RATE;
219 }
220
221 if idx < data.len() {
223 let rem = data.len() - idx;
224 self.buffer[..rem].copy_from_slice(&data[idx..]);
225 self.buffer_idx = rem;
226 }
227
228 Ok(())
229 }
230
231 fn finalize_internal(&mut self) -> Result<Zeroizing<[u8; SHAKE128_OUTPUT_SIZE]>> {
232 let mut pad_block = Zeroizing::new([0u8; SHAKE128_RATE]);
234 pad_block[..self.buffer_idx].copy_from_slice(&self.buffer[..self.buffer_idx]);
235 pad_block[self.buffer_idx] = 0x1F;
236 pad_block[SHAKE128_RATE - 1] |= 0x80;
237
238 for (i, chunk) in pad_block.chunks_exact(8).enumerate() {
240 let mut lane = 0u64;
241 for (j, &b) in chunk.iter().enumerate() {
242 lane |= (b as u64) << (8 * j);
243 }
244 self.state[i] ^= lane;
245 lane.zeroize();
246 }
247 keccak_f1600(&mut self.state);
248
249 let mut result = Zeroizing::new([0u8; SHAKE128_OUTPUT_SIZE]);
251 let mut offset = 0;
252
253 while offset < SHAKE128_OUTPUT_SIZE {
254 let to_copy = (SHAKE128_OUTPUT_SIZE - offset).min(SHAKE128_RATE);
255
256 for i in 0..to_copy {
258 let lane_idx = i / 8;
259 let byte_idx = i % 8;
260 result[offset + i] = ((self.state[lane_idx] >> (8 * byte_idx)) & 0xFF) as u8;
261 }
262
263 offset += to_copy;
264
265 if offset < SHAKE128_OUTPUT_SIZE {
267 keccak_f1600(&mut self.state);
268 }
269 }
270
271 self.zeroize();
272 Ok(result)
273 }
274}
275
276impl Shake256 {
277 fn init() -> Self {
278 Shake256 {
279 state: [0u64; KECCAK_STATE_SIZE],
280 buffer: [0u8; SHAKE256_RATE],
281 buffer_idx: 0,
282 }
283 }
284
285 fn update_internal(&mut self, data: &[u8]) -> Result<()> {
286 let mut idx = 0;
287
288 if self.buffer_idx > 0 {
290 let to_copy = (SHAKE256_RATE - self.buffer_idx).min(data.len());
291 self.buffer[self.buffer_idx..self.buffer_idx + to_copy]
292 .copy_from_slice(&data[..to_copy]);
293 self.buffer_idx += to_copy;
294 idx += to_copy;
295
296 if self.buffer_idx == SHAKE256_RATE {
297 for (i, chunk) in self.buffer.chunks_exact(8).enumerate() {
299 let mut lane = 0u64;
300 for (j, &b) in chunk.iter().enumerate() {
301 lane |= (b as u64) << (8 * j);
302 }
303 self.state[i] ^= lane;
304 lane.zeroize();
305 }
306 keccak_f1600(&mut self.state);
307 self.buffer.zeroize();
308 self.buffer_idx = 0;
309 }
310 }
311
312 while idx + SHAKE256_RATE <= data.len() {
314 let block = &data[idx..idx + SHAKE256_RATE];
315 for (i, chunk) in block.chunks_exact(8).enumerate() {
316 let mut lane = 0u64;
317 for (j, &b) in chunk.iter().enumerate() {
318 lane |= (b as u64) << (8 * j);
319 }
320 self.state[i] ^= lane;
321 lane.zeroize();
322 }
323 keccak_f1600(&mut self.state);
324 idx += SHAKE256_RATE;
325 }
326
327 if idx < data.len() {
329 let rem = data.len() - idx;
330 self.buffer[..rem].copy_from_slice(&data[idx..]);
331 self.buffer_idx = rem;
332 }
333
334 Ok(())
335 }
336
337 fn finalize_internal(&mut self) -> Result<Zeroizing<[u8; SHAKE256_OUTPUT_SIZE]>> {
338 let mut pad_block = Zeroizing::new([0u8; SHAKE256_RATE]);
340 pad_block[..self.buffer_idx].copy_from_slice(&self.buffer[..self.buffer_idx]);
341 pad_block[self.buffer_idx] = 0x1F;
342 pad_block[SHAKE256_RATE - 1] |= 0x80;
343
344 for (i, chunk) in pad_block.chunks_exact(8).enumerate() {
346 let mut lane = 0u64;
347 for (j, &b) in chunk.iter().enumerate() {
348 lane |= (b as u64) << (8 * j);
349 }
350 self.state[i] ^= lane;
351 lane.zeroize();
352 }
353 keccak_f1600(&mut self.state);
354
355 let mut result = Zeroizing::new([0u8; SHAKE256_OUTPUT_SIZE]);
357 let mut offset = 0;
358
359 while offset < SHAKE256_OUTPUT_SIZE {
360 let to_copy = (SHAKE256_OUTPUT_SIZE - offset).min(SHAKE256_RATE);
361
362 for i in 0..to_copy {
364 let lane_idx = i / 8;
365 let byte_idx = i % 8;
366 result[offset + i] = ((self.state[lane_idx] >> (8 * byte_idx)) & 0xFF) as u8;
367 }
368
369 offset += to_copy;
370
371 if offset < SHAKE256_OUTPUT_SIZE {
373 keccak_f1600(&mut self.state);
374 }
375 }
376
377 self.zeroize();
378 Ok(result)
379 }
380}
381
382impl HashFunction for Shake128 {
384 type Algorithm = Shake128Algorithm;
385 type Output = Digest<SHAKE128_OUTPUT_SIZE>;
386
387 fn new() -> Self {
388 Self::init()
389 }
390
391 fn update(&mut self, data: &[u8]) -> Result<&mut Self> {
392 self.update_internal(data)?;
393 Ok(self)
394 }
395
396 fn finalize(&mut self) -> Result<Self::Output> {
397 let hash = self.finalize_internal()?;
398 let mut digest = Digest::<SHAKE128_OUTPUT_SIZE>::zeroed();
399 digest.as_mut().copy_from_slice(&hash[..]);
400 Ok(digest)
401 }
402
403 fn output_size() -> usize {
404 Self::Algorithm::OUTPUT_SIZE
405 }
406
407 fn block_size() -> usize {
408 Self::Algorithm::BLOCK_SIZE
409 }
410
411 fn name() -> String {
412 Self::Algorithm::ALGORITHM_ID.to_string()
413 }
414}
415
416impl HashFunction for Shake256 {
418 type Algorithm = Shake256Algorithm;
419 type Output = Digest<SHAKE256_OUTPUT_SIZE>;
420
421 fn new() -> Self {
422 Self::init()
423 }
424
425 fn update(&mut self, data: &[u8]) -> Result<&mut Self> {
426 self.update_internal(data)?;
427 Ok(self)
428 }
429
430 fn finalize(&mut self) -> Result<Self::Output> {
431 let hash = self.finalize_internal()?;
432 let mut digest = Digest::<SHAKE256_OUTPUT_SIZE>::zeroed();
433 digest.as_mut().copy_from_slice(&hash[..]);
434 Ok(digest)
435 }
436
437 fn output_size() -> usize {
438 Self::Algorithm::OUTPUT_SIZE
439 }
440
441 fn block_size() -> usize {
442 Self::Algorithm::BLOCK_SIZE
443 }
444
445 fn name() -> String {
446 Self::Algorithm::ALGORITHM_ID.to_string()
447 }
448}
449
450#[cfg(test)]
451mod tests;