1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//! A default [`Hasher`] implementation backed by [`SipHasher24`].

use siphasher::sip128::{Hasher128, SipHasher24};

use super::{Digest, Hasher};

/// A fast, non-cryptographic hash outputting 128-bit digests.
///
/// This implementation is used as the default [`Hasher`] implementation, using
/// the standard library [`Hash`] trait, which may produce non-portable hashes
/// as described in the documentation of the [`Hash`] trait itself, and this
/// crate's [`Hasher`].
///
/// Users may choose to initialise the [`SipHasher`] with seed keys if untrusted
/// key/value user input is used in a tree in order to prevent chosen-hash
/// collision attacks.
#[derive(Debug, Default, Clone)]
#[allow(missing_copy_implementations)]
pub struct SipHasher {
    hasher: SipHasher24,
}

impl SipHasher {
    /// Initialise a [`SipHasher`] with the provided seed key.
    ///
    /// All peers comparing tree hashes MUST be initialised with the same seed
    /// key.
    pub fn new(key: &[u8; 16]) -> Self {
        let hasher = SipHasher24::new_with_key(key);
        Self { hasher }
    }
}

impl<T> Hasher<16, T> for SipHasher
where
    T: std::hash::Hash,
{
    fn hash(&self, value: &T) -> Digest<16> {
        let mut h = self.hasher;
        value.hash(&mut h);
        Digest::new(h.finish128().as_bytes())
    }
}