dcrypt_algorithms/hash/shake/
mod.rs1#[cfg(not(feature = "std"))]
9use alloc::vec::Vec;
10use zeroize::{Zeroize, ZeroizeOnDrop};
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, Zeroize, ZeroizeOnDrop)]
89pub struct Shake128 {
90 state: [u64; KECCAK_STATE_SIZE],
91 buffer: [u8; SHAKE128_RATE],
92 buffer_idx: usize,
93}
94
95#[derive(Clone, Zeroize, ZeroizeOnDrop)]
97pub struct Shake256 {
98 state: [u64; KECCAK_STATE_SIZE],
99 buffer: [u8; SHAKE256_RATE],
100 buffer_idx: usize,
101}
102
103fn keccak_f1600(state: &mut [u64; KECCAK_STATE_SIZE]) {
105 for &rc in RC.iter().take(KECCAK_ROUNDS) {
106 let mut c = [0u64; 5];
108 for x in 0..5 {
109 c[x] = state[x] ^ state[x + 5] ^ state[x + 10] ^ state[x + 15] ^ state[x + 20];
110 }
111 let mut d = [0u64; 5];
112 for x in 0..5 {
113 d[x] = c[(x + 4) % 5] ^ c[(x + 1) % 5].rotate_left(1);
114 }
115 for y in 0..5 {
116 for x in 0..5 {
117 state[x + 5 * y] ^= d[x];
118 }
119 }
120
121 let mut b = [0u64; KECCAK_STATE_SIZE];
123 let mut x = 1;
124 let mut y = 0;
125 b[0] = state[0];
126 for i in 0..24 {
127 let idx = x + 5 * y;
128 b[PI[i]] = state[idx].rotate_left(RHO[i]);
129 let temp = y;
130 y = (2 * x + 3 * y) % 5;
131 x = temp;
132 }
133
134 for y in 0..5 {
136 for x in 0..5 {
137 let idx = x + 5 * y;
138 state[idx] = b[idx] ^ ((!b[(x + 1) % 5 + 5 * y]) & b[(x + 2) % 5 + 5 * y]);
139 }
140 }
141
142 state[0] ^= rc;
144 }
145}
146
147impl Shake128 {
148 fn init() -> Self {
149 Shake128 {
150 state: [0u64; KECCAK_STATE_SIZE],
151 buffer: [0u8; SHAKE128_RATE],
152 buffer_idx: 0,
153 }
154 }
155
156 fn update_internal(&mut self, data: &[u8]) -> Result<()> {
157 let mut idx = 0;
158
159 if self.buffer_idx > 0 {
161 let to_copy = (SHAKE128_RATE - self.buffer_idx).min(data.len());
162 self.buffer[self.buffer_idx..self.buffer_idx + to_copy]
163 .copy_from_slice(&data[..to_copy]);
164 self.buffer_idx += to_copy;
165 idx += to_copy;
166
167 if self.buffer_idx == SHAKE128_RATE {
168 for (i, chunk) in self.buffer.chunks_exact(8).enumerate() {
170 let mut lane = 0u64;
171 for (j, &b) in chunk.iter().enumerate() {
172 lane |= (b as u64) << (8 * j);
173 }
174 self.state[i] ^= lane;
175 }
176 keccak_f1600(&mut self.state);
177 self.buffer_idx = 0;
178 }
179 }
180
181 while idx + SHAKE128_RATE <= data.len() {
183 let block = &data[idx..idx + SHAKE128_RATE];
184 for (i, chunk) in block.chunks_exact(8).enumerate() {
185 let mut lane = 0u64;
186 for (j, &b) in chunk.iter().enumerate() {
187 lane |= (b as u64) << (8 * j);
188 }
189 self.state[i] ^= lane;
190 }
191 keccak_f1600(&mut self.state);
192 idx += SHAKE128_RATE;
193 }
194
195 if idx < data.len() {
197 let rem = data.len() - idx;
198 self.buffer[..rem].copy_from_slice(&data[idx..]);
199 self.buffer_idx = rem;
200 }
201
202 Ok(())
203 }
204
205 fn finalize_internal(&mut self) -> Result<Vec<u8>> {
206 let mut pad_block = [0u8; SHAKE128_RATE];
208 pad_block[..self.buffer_idx].copy_from_slice(&self.buffer[..self.buffer_idx]);
209 pad_block[self.buffer_idx] = 0x1F;
210 pad_block[SHAKE128_RATE - 1] |= 0x80;
211
212 for (i, chunk) in pad_block.chunks_exact(8).enumerate() {
214 let mut lane = 0u64;
215 for (j, &b) in chunk.iter().enumerate() {
216 lane |= (b as u64) << (8 * j);
217 }
218 self.state[i] ^= lane;
219 }
220 keccak_f1600(&mut self.state);
221
222 let mut result = vec![0u8; SHAKE128_OUTPUT_SIZE];
224 let mut offset = 0;
225
226 while offset < SHAKE128_OUTPUT_SIZE {
227 let to_copy = (SHAKE128_OUTPUT_SIZE - offset).min(SHAKE128_RATE);
228
229 for i in 0..to_copy {
231 let lane_idx = i / 8;
232 let byte_idx = i % 8;
233 result[offset + i] = ((self.state[lane_idx] >> (8 * byte_idx)) & 0xFF) as u8;
234 }
235
236 offset += to_copy;
237
238 if offset < SHAKE128_OUTPUT_SIZE {
240 keccak_f1600(&mut self.state);
241 }
242 }
243
244 Ok(result)
245 }
246}
247
248impl Shake256 {
249 fn init() -> Self {
250 Shake256 {
251 state: [0u64; KECCAK_STATE_SIZE],
252 buffer: [0u8; SHAKE256_RATE],
253 buffer_idx: 0,
254 }
255 }
256
257 fn update_internal(&mut self, data: &[u8]) -> Result<()> {
258 let mut idx = 0;
259
260 if self.buffer_idx > 0 {
262 let to_copy = (SHAKE256_RATE - self.buffer_idx).min(data.len());
263 self.buffer[self.buffer_idx..self.buffer_idx + to_copy]
264 .copy_from_slice(&data[..to_copy]);
265 self.buffer_idx += to_copy;
266 idx += to_copy;
267
268 if self.buffer_idx == SHAKE256_RATE {
269 for (i, chunk) in self.buffer.chunks_exact(8).enumerate() {
271 let mut lane = 0u64;
272 for (j, &b) in chunk.iter().enumerate() {
273 lane |= (b as u64) << (8 * j);
274 }
275 self.state[i] ^= lane;
276 }
277 keccak_f1600(&mut self.state);
278 self.buffer_idx = 0;
279 }
280 }
281
282 while idx + SHAKE256_RATE <= data.len() {
284 let block = &data[idx..idx + SHAKE256_RATE];
285 for (i, chunk) in block.chunks_exact(8).enumerate() {
286 let mut lane = 0u64;
287 for (j, &b) in chunk.iter().enumerate() {
288 lane |= (b as u64) << (8 * j);
289 }
290 self.state[i] ^= lane;
291 }
292 keccak_f1600(&mut self.state);
293 idx += SHAKE256_RATE;
294 }
295
296 if idx < data.len() {
298 let rem = data.len() - idx;
299 self.buffer[..rem].copy_from_slice(&data[idx..]);
300 self.buffer_idx = rem;
301 }
302
303 Ok(())
304 }
305
306 fn finalize_internal(&mut self) -> Result<Vec<u8>> {
307 let mut pad_block = [0u8; SHAKE256_RATE];
309 pad_block[..self.buffer_idx].copy_from_slice(&self.buffer[..self.buffer_idx]);
310 pad_block[self.buffer_idx] = 0x1F;
311 pad_block[SHAKE256_RATE - 1] |= 0x80;
312
313 for (i, chunk) in pad_block.chunks_exact(8).enumerate() {
315 let mut lane = 0u64;
316 for (j, &b) in chunk.iter().enumerate() {
317 lane |= (b as u64) << (8 * j);
318 }
319 self.state[i] ^= lane;
320 }
321 keccak_f1600(&mut self.state);
322
323 let mut result = vec![0u8; SHAKE256_OUTPUT_SIZE];
325 let mut offset = 0;
326
327 while offset < SHAKE256_OUTPUT_SIZE {
328 let to_copy = (SHAKE256_OUTPUT_SIZE - offset).min(SHAKE256_RATE);
329
330 for i in 0..to_copy {
332 let lane_idx = i / 8;
333 let byte_idx = i % 8;
334 result[offset + i] = ((self.state[lane_idx] >> (8 * byte_idx)) & 0xFF) as u8;
335 }
336
337 offset += to_copy;
338
339 if offset < SHAKE256_OUTPUT_SIZE {
341 keccak_f1600(&mut self.state);
342 }
343 }
344
345 Ok(result)
346 }
347}
348
349impl HashFunction for Shake128 {
351 type Algorithm = Shake128Algorithm;
352 type Output = Digest<SHAKE128_OUTPUT_SIZE>;
353
354 fn new() -> Self {
355 Self::init()
356 }
357
358 fn update(&mut self, data: &[u8]) -> Result<&mut Self> {
359 self.update_internal(data)?;
360 Ok(self)
361 }
362
363 fn finalize(&mut self) -> Result<Self::Output> {
364 let hash = self.finalize_internal()?;
365 let mut digest = [0u8; SHAKE128_OUTPUT_SIZE];
366 digest.copy_from_slice(&hash);
367 Ok(Digest::new(digest))
368 }
369
370 fn output_size() -> usize {
371 Self::Algorithm::OUTPUT_SIZE
372 }
373
374 fn block_size() -> usize {
375 Self::Algorithm::BLOCK_SIZE
376 }
377
378 fn name() -> String {
379 Self::Algorithm::ALGORITHM_ID.to_string()
380 }
381}
382
383impl HashFunction for Shake256 {
385 type Algorithm = Shake256Algorithm;
386 type Output = Digest<SHAKE256_OUTPUT_SIZE>;
387
388 fn new() -> Self {
389 Self::init()
390 }
391
392 fn update(&mut self, data: &[u8]) -> Result<&mut Self> {
393 self.update_internal(data)?;
394 Ok(self)
395 }
396
397 fn finalize(&mut self) -> Result<Self::Output> {
398 let hash = self.finalize_internal()?;
399 let mut digest = [0u8; SHAKE256_OUTPUT_SIZE];
400 digest.copy_from_slice(&hash);
401 Ok(Digest::new(digest))
402 }
403
404 fn output_size() -> usize {
405 Self::Algorithm::OUTPUT_SIZE
406 }
407
408 fn block_size() -> usize {
409 Self::Algorithm::BLOCK_SIZE
410 }
411
412 fn name() -> String {
413 Self::Algorithm::ALGORITHM_ID.to_string()
414 }
415}
416
417#[cfg(test)]
418mod tests;