merkle_search_tree/digest/
siphash.rs

1//! A default [`Hasher`] implementation backed by [`SipHasher24`].
2
3use siphasher::sip128::{Hasher128, SipHasher24};
4
5use super::{Digest, Hasher};
6
7/// A fast, non-cryptographic hash outputting 128-bit digests.
8///
9/// This implementation is used as the default [`Hasher`] implementation, using
10/// the standard library [`Hash`] trait, which may produce non-portable hashes
11/// as described in the documentation of the [`Hash`] trait itself, and this
12/// crate's [`Hasher`].
13///
14/// Users may choose to initialise the [`SipHasher`] with seed keys if untrusted
15/// key/value user input is used in a tree in order to prevent chosen-hash
16/// collision attacks.
17#[derive(Debug, Default, Clone)]
18#[allow(missing_copy_implementations)]
19pub struct SipHasher {
20    hasher: SipHasher24,
21}
22
23impl SipHasher {
24    /// Initialise a [`SipHasher`] with the provided seed key.
25    ///
26    /// All peers comparing tree hashes MUST be initialised with the same seed
27    /// key.
28    pub fn new(key: &[u8; 16]) -> Self {
29        let hasher = SipHasher24::new_with_key(key);
30        Self { hasher }
31    }
32}
33
34impl<T> Hasher<16, T> for SipHasher
35where
36    T: std::hash::Hash,
37{
38    fn hash(&self, value: &T) -> Digest<16> {
39        let mut h = self.hasher;
40        value.hash(&mut h);
41        Digest::new(h.finish128().as_bytes())
42    }
43}