p3_keccak/
lib.rs

1//! The Keccak-f permutation, and hash functions built from it.
2
3#![no_std]
4#![cfg_attr(
5    all(
6        feature = "nightly-features",
7        target_arch = "x86_64",
8        target_feature = "avx512f"
9    ),
10    feature(stdarch_x86_avx512)
11)]
12
13use p3_symmetric::{CryptographicHasher, CryptographicPermutation, Permutation};
14use tiny_keccak::{keccakf, Hasher, Keccak};
15
16#[cfg(all(
17    feature = "nightly-features",
18    target_arch = "x86_64",
19    target_feature = "avx512f"
20))]
21pub mod avx512;
22#[cfg(all(
23    feature = "nightly-features",
24    target_arch = "x86_64",
25    target_feature = "avx512f"
26))]
27pub use avx512::*;
28
29#[cfg(all(
30    target_arch = "x86_64",
31    target_feature = "avx2",
32    not(all(feature = "nightly-features", target_feature = "avx512f"))
33))]
34pub mod avx2;
35#[cfg(all(
36    target_arch = "x86_64",
37    target_feature = "avx2",
38    not(all(feature = "nightly-features", target_feature = "avx512f"))
39))]
40pub use avx2::*;
41
42#[cfg(all(target_arch = "x86_64", not(target_feature = "avx2")))]
43pub mod sse2;
44#[cfg(all(target_arch = "x86_64", not(target_feature = "avx2")))]
45pub use sse2::*;
46
47#[cfg(all(
48    target_arch = "aarch64",
49    target_feature = "neon",
50    target_feature = "sha3"
51))]
52pub mod neon;
53#[cfg(all(
54    target_arch = "aarch64",
55    target_feature = "neon",
56    target_feature = "sha3"
57))]
58pub use neon::*;
59
60#[cfg(not(any(
61    all(
62        target_arch = "aarch64",
63        target_feature = "neon",
64        target_feature = "sha3",
65    ),
66    target_arch = "x86_64",
67)))]
68mod fallback;
69#[cfg(not(any(
70    all(
71        target_arch = "aarch64",
72        target_feature = "neon",
73        target_feature = "sha3",
74    ),
75    target_arch = "x86_64",
76)))]
77pub use fallback::*;
78
79/// The Keccak-f permutation.
80#[derive(Copy, Clone, Debug)]
81pub struct KeccakF;
82
83impl Permutation<[u64; 25]> for KeccakF {
84    fn permute_mut(&self, input: &mut [u64; 25]) {
85        keccakf(input);
86    }
87}
88
89impl CryptographicPermutation<[u64; 25]> for KeccakF {}
90
91impl Permutation<[u8; 200]> for KeccakF {
92    fn permute(&self, input_u8s: [u8; 200]) -> [u8; 200] {
93        let mut state_u64s: [u64; 25] = core::array::from_fn(|i| {
94            u64::from_le_bytes(input_u8s[i * 8..][..8].try_into().unwrap())
95        });
96
97        keccakf(&mut state_u64s);
98
99        core::array::from_fn(|i| {
100            let u64_limb = state_u64s[i / 8];
101            u64_limb.to_le_bytes()[i % 8]
102        })
103    }
104
105    fn permute_mut(&self, input: &mut [u8; 200]) {
106        *input = self.permute(*input);
107    }
108}
109
110impl CryptographicPermutation<[u8; 200]> for KeccakF {}
111
112/// The `Keccak` hash functions defined in
113/// [Keccak SHA3 submission](https://keccak.team/files/Keccak-submission-3.pdf).
114#[derive(Copy, Clone, Debug)]
115pub struct Keccak256Hash;
116
117impl CryptographicHasher<u8, [u8; 32]> for Keccak256Hash {
118    fn hash_iter<I>(&self, input: I) -> [u8; 32]
119    where
120        I: IntoIterator<Item = u8>,
121    {
122        const BUFLEN: usize = 512; // Tweakable parameter; determined by experiment
123        let mut hasher = Keccak::v256();
124        p3_util::apply_to_chunks::<BUFLEN, _, _>(input, |buf| hasher.update(buf));
125
126        let mut output = [0u8; 32];
127        hasher.finalize(&mut output);
128        output
129    }
130
131    fn hash_iter_slices<'a, I>(&self, input: I) -> [u8; 32]
132    where
133        I: IntoIterator<Item = &'a [u8]>,
134    {
135        let mut hasher = Keccak::v256();
136        for chunk in input.into_iter() {
137            hasher.update(chunk);
138        }
139
140        let mut output = [0u8; 32];
141        hasher.finalize(&mut output);
142        output
143    }
144}