p3_keccak/
lib.rs

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