binius_hash/
compress.rs

1// Copyright 2024-2025 Irreducible Inc.
2// Copyright (c) 2024 The Plonky3 Authors
3
4//! These interfaces are taken from
5//! [p3_symmetric](https://github.com/Plonky3/Plonky3/blob/main/symmetric/src/compression.rs) in
6//! [Plonky3].
7//!
8//! Plonky3 is dual-licensed under MIT OR Apache 2.0. We use it under Apache 2.0.
9//!
10//! [Plonky3]: <https://github.com/plonky3/plonky3>
11
12/// An `N`-to-1 compression function, collision-resistant in a hash tree setting.
13///
14/// Unlike `CompressionFunction`, it may not be collision-resistant in general.
15/// Instead it is only collision-resistant in hash-tree like settings where
16/// the preimage of a non-leaf node must consist of compression outputs.
17pub trait PseudoCompressionFunction<T, const N: usize>: Clone {
18	fn compress(&self, input: [T; N]) -> T;
19}
20
21/// An `N`-to-1 compression function.
22pub trait CompressionFunction<T, const N: usize>: PseudoCompressionFunction<T, N> {}
23
24pub mod sha256 {
25	use bytemuck::{bytes_of_mut, must_cast};
26	use digest::{Digest, core_api::Block};
27	use sha2::{Sha256, compress256, digest::Output};
28
29	use super::*;
30
31	/// A two-to-one compression function for SHA-256 digests.
32	#[derive(Debug, Clone)]
33	pub struct Sha256Compression {
34		initial_state: [u32; 8],
35	}
36
37	impl Default for Sha256Compression {
38		fn default() -> Self {
39			let initial_state_bytes = Sha256::digest(b"BINIUS SHA-256 COMPRESS");
40			let mut initial_state = [0u32; 8];
41			bytes_of_mut(&mut initial_state).copy_from_slice(&initial_state_bytes);
42			Self { initial_state }
43		}
44	}
45
46	impl PseudoCompressionFunction<Output<Sha256>, 2> for Sha256Compression {
47		fn compress(&self, input: [Output<Sha256>; 2]) -> Output<Sha256> {
48			let mut ret = self.initial_state;
49			let mut block = <Block<Sha256>>::default();
50			block.as_mut_slice()[..32].copy_from_slice(input[0].as_slice());
51			block.as_mut_slice()[32..].copy_from_slice(input[1].as_slice());
52			compress256(&mut ret, &[block]);
53			must_cast::<[u32; 8], [u8; 32]>(ret).into()
54		}
55	}
56
57	impl CompressionFunction<Output<Sha256>, 2> for Sha256Compression {}
58}