binius_hash/
hasher.rs

1// Copyright 2023-2025 Irreducible Inc.
2
3use std::{marker::PhantomData, mem::MaybeUninit};
4
5/// Trait representing the simplest and most straight forward use case of a hash function
6///
7/// This is a highly simplified trait that just treats the entire interface of a hash as a
8/// simple function that takes in a slice of inputs and gives you back an output.
9pub trait HashDigest<T> {
10	/// The hash function output type.
11	type Digest;
12	fn hash(data: impl AsRef<[T]>) -> Self::Digest;
13}
14
15/// Wrapper over structs that implement [`Hasher`] to provide default implementation for [`HashDigest`]
16pub struct HasherDigest<T, H: Hasher<T>> {
17	_t_marker: PhantomData<T>,
18	_h_marker: PhantomData<H>,
19}
20
21impl<T, H: Hasher<T>> HashDigest<T> for HasherDigest<T, H> {
22	type Digest = <H as Hasher<T>>::Digest;
23
24	fn hash(data: impl AsRef<[T]>) -> Self::Digest {
25		hasher_hash::<T, H>(data)
26	}
27}
28
29/// Wrapper over structs that implement [`FixedLenHasher`] to provide default implementation for [`HashDigest`]
30pub struct FixedLenHasherDigest<T, H: FixedLenHasher<T>> {
31	_t_marker: PhantomData<T>,
32	_h_marker: PhantomData<H>,
33}
34
35impl<T, H: FixedLenHasher<T>> HashDigest<T> for FixedLenHasherDigest<T, H> {
36	type Digest = <H as FixedLenHasher<T>>::Digest;
37
38	fn hash(data: impl AsRef<[T]>) -> Self::Digest {
39		fixed_len_hash::<T, H>(data)
40	}
41}
42
43/// Trait representing cryptographic hash functions which is generic over the input type.
44///
45/// This interface is largely based on RustCrypto's Digest trait, except that instead of
46/// requiring byte strings as input and byte arrays as output, this is generic over the input
47/// values and has a less constrained output digest type.
48pub trait Hasher<T>: Sync + Send {
49	/// The hash function output type.
50	type Digest;
51
52	fn new() -> Self;
53	fn update(&mut self, data: impl AsRef<[T]>);
54	fn chain_update(self, data: impl AsRef<[T]>) -> Self;
55	fn finalize(self) -> Self::Digest;
56	fn finalize_into(self, out: &mut MaybeUninit<Self::Digest>);
57
58	fn finalize_reset(&mut self) -> Self::Digest;
59	fn finalize_into_reset(&mut self, out: &mut MaybeUninit<Self::Digest>);
60	fn reset(&mut self);
61}
62
63#[derive(Debug, thiserror::Error)]
64pub enum HashError {
65	#[error("Not enough data to finalize hash (expected {committed} elements, hashed {hashed} elements)")]
66	NotEnoughData { committed: u64, hashed: u64 },
67	#[error("Too much data to hash (expected {committed} elements, received {received} elements)")]
68	TooMuchData { committed: u64, received: u64 },
69}
70
71/// Trait representing a family of fixed-length cryptographic hash functions which is generic over
72/// the input type.
73///
74/// A fixed-length hash has the property that the amount of data in the preimage is fixed, and so
75/// must be specified up front when constructing the hasher. The `[FixedLenHasher::finalize]` will
76/// fail if the amount of data the hasher is updated with does not match the specified length. A
77/// family of fixed-length hash functions retains the property that is it impossible to find
78/// collisions between any two inputs, even those differing in length.
79///
80/// This interface is otherwise similar to the [`Hasher`] trait.
81pub trait FixedLenHasher<T>
82where
83	Self: Sized,
84{
85	/// The hash function output type.
86	type Digest;
87
88	/// Constructor.
89	///
90	/// `msg_len` is the total number of `T` elements to be hashed
91	fn new(msg_len: u64) -> Self;
92	fn update(&mut self, data: impl AsRef<[T]>);
93	fn chain_update(self, data: impl AsRef<[T]>) -> Self;
94	fn finalize(self) -> Result<Self::Digest, HashError>;
95
96	/// Resets with length initialized to the current context
97	fn reset(&mut self);
98}
99
100pub fn hasher_hash<T, H: Hasher<T>>(data: impl AsRef<[T]>) -> H::Digest {
101	H::new().chain_update(data).finalize()
102}
103
104pub fn fixed_len_hash<T, H: FixedLenHasher<T>>(data: impl AsRef<[T]>) -> H::Digest {
105	H::new(data.as_ref().len() as u64)
106		.chain_update(data)
107		.finalize()
108		.unwrap()
109}