p3_symmetric/
compression.rsuse crate::hasher::CryptographicHasher;
use crate::permutation::CryptographicPermutation;
pub trait PseudoCompressionFunction<T, const N: usize>: Clone {
fn compress(&self, input: [T; N]) -> T;
}
pub trait CompressionFunction<T, const N: usize>: PseudoCompressionFunction<T, N> {}
#[derive(Clone, Debug)]
pub struct TruncatedPermutation<InnerP, const N: usize, const CHUNK: usize, const WIDTH: usize> {
inner_permutation: InnerP,
}
impl<InnerP, const N: usize, const CHUNK: usize, const WIDTH: usize>
TruncatedPermutation<InnerP, N, CHUNK, WIDTH>
{
pub const fn new(inner_permutation: InnerP) -> Self {
Self { inner_permutation }
}
}
impl<T, InnerP, const N: usize, const CHUNK: usize, const WIDTH: usize>
PseudoCompressionFunction<[T; CHUNK], N> for TruncatedPermutation<InnerP, N, CHUNK, WIDTH>
where
T: Copy + Default,
InnerP: CryptographicPermutation<[T; WIDTH]>,
{
fn compress(&self, input: [[T; CHUNK]; N]) -> [T; CHUNK] {
debug_assert!(CHUNK * N <= WIDTH);
let mut pre = [T::default(); WIDTH];
for i in 0..N {
pre[i * CHUNK..(i + 1) * CHUNK].copy_from_slice(&input[i]);
}
let post = self.inner_permutation.permute(pre);
post[..CHUNK].try_into().unwrap()
}
}
#[derive(Clone, Debug)]
pub struct CompressionFunctionFromHasher<H, const N: usize, const CHUNK: usize> {
hasher: H,
}
impl<H, const N: usize, const CHUNK: usize> CompressionFunctionFromHasher<H, N, CHUNK> {
pub const fn new(hasher: H) -> Self {
Self { hasher }
}
}
impl<T, H, const N: usize, const CHUNK: usize> PseudoCompressionFunction<[T; CHUNK], N>
for CompressionFunctionFromHasher<H, N, CHUNK>
where
T: Clone,
H: CryptographicHasher<T, [T; CHUNK]>,
{
fn compress(&self, input: [[T; CHUNK]; N]) -> [T; CHUNK] {
self.hasher.hash_iter(input.into_iter().flatten())
}
}
impl<T, H, const N: usize, const CHUNK: usize> CompressionFunction<[T; CHUNK], N>
for CompressionFunctionFromHasher<H, N, CHUNK>
where
T: Clone,
H: CryptographicHasher<T, [T; CHUNK]>,
{
}