lambdaworks_crypto/hash/sha3/
mod.rs1use alloc::{
2 string::{String, ToString},
3 vec::Vec,
4};
5use sha3::{Digest, Sha3_256};
6
7pub struct Sha3Hasher;
8
9impl Sha3Hasher {
12 pub const fn new() -> Self {
13 Self
14 }
15
16 pub fn expand_message(msg: &[u8], dst: &[u8], len_in_bytes: u64) -> Result<Vec<u8>, String> {
17 let b_in_bytes = Sha3_256::output_size() as u64;
18
19 let ell = len_in_bytes.div_ceil(b_in_bytes);
20 if ell > 255 {
21 return Err("Abort".to_string());
22 }
23
24 let dst_prime: Vec<u8> = [dst, &Self::i2osp(dst.len() as u64, 1)].concat();
25 let z_pad = Self::i2osp(0, 64);
26 let l_i_b_str = Self::i2osp(len_in_bytes, 2);
27 let msg_prime = [
28 z_pad,
29 msg.to_vec(),
30 l_i_b_str,
31 Self::i2osp(0, 1),
32 dst_prime.clone(),
33 ]
34 .concat();
35 let b_0: Vec<u8> = Sha3_256::digest(msg_prime).to_vec();
36 let a = [b_0.clone(), Self::i2osp(1, 1), dst_prime.clone()].concat();
37 let b_1 = Sha3_256::digest(a).to_vec();
38
39 let mut b_vals = Vec::<Vec<u8>>::with_capacity(ell as usize);
40 b_vals.push(b_1);
41 for idx in 1..ell {
42 let aux = Self::strxor(&b_0, &b_vals[idx as usize - 1]);
43 let b_i = [aux, Self::i2osp(idx, 1), dst_prime.clone()].concat();
44 b_vals.push(Sha3_256::digest(b_i).to_vec());
45 }
46
47 let mut b_vals = b_vals.concat();
48 b_vals.truncate(len_in_bytes as usize);
49
50 Ok(b_vals)
51 }
52
53 fn i2osp(x: u64, length: u64) -> Vec<u8> {
54 let mut x_aux = x;
55 let mut digits = Vec::new();
56 while x_aux != 0 {
57 digits.push((x_aux % 256) as u8);
58 x_aux /= 256;
59 }
60 digits.resize(length as usize, 0);
61 digits.reverse();
62 digits
63 }
64
65 fn strxor(a: &[u8], b: &[u8]) -> Vec<u8> {
66 a.iter().zip(b).map(|(a, b)| a ^ b).collect()
67 }
68}
69
70impl Default for Sha3Hasher {
71 fn default() -> Self {
72 Self::new()
73 }
74}