dapol/
hasher.rs

1use primitive_types::H256;
2
3const DELIMITER: &[u8] = ";".as_bytes();
4
5/// Abstraction of a hash function, allows easy switching of hash function.
6///
7/// The main purpose of the hash function is usage in the binary tree merge
8/// function. The reason it has it's own file is so that we can create a
9/// wrapper around the underlying hash function, allowing it to be easily
10/// changed.
11///
12/// The current hash function used is blake3.
13///
14/// Example:
15/// ```
16/// use dapol::Hasher;
17/// let mut hasher = Hasher::new();
18/// hasher.update("leaf".as_bytes());
19/// let hash = hasher.finalize();
20/// ```
21///
22/// Note that a delimiter is used to add extra security:
23/// ```
24/// use dapol::Hasher;
25/// let mut dapol_hasher = Hasher::new();
26/// dapol_hasher.update("leaf".as_bytes());
27/// dapol_hasher.update("node".as_bytes());
28/// let dapol_hash = dapol_hasher.finalize();
29///
30/// let mut blake_hasher = blake3::Hasher::new();
31/// blake_hasher.update("leaf".as_bytes());
32/// blake_hasher.update(";".as_bytes());
33/// blake_hasher.update("node".as_bytes());
34/// blake_hasher.update(";".as_bytes());
35/// let blake_hash = blake_hasher.finalize();
36///
37/// assert_eq!(dapol_hash.as_bytes(), blake_hash.as_bytes());
38/// ```
39pub struct Hasher(blake3::Hasher);
40
41impl Hasher {
42    pub fn new() -> Self {
43        Hasher(blake3::Hasher::new())
44    }
45
46    pub fn update(&mut self, input: &[u8]) -> &mut Self {
47        self.0.update(input);
48        self.0.update(DELIMITER);
49        self
50    }
51
52    pub fn finalize(&self) -> H256 {
53        let bytes: [u8; 32] = self.0.finalize().into();
54        H256(bytes)
55    }
56}
57
58impl Default for Hasher {
59    fn default() -> Self {
60        Hasher(blake3::Hasher::default())
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    // Ensures Blake 3 library produces correct hashed output.
69    // Comparison hash derived through the following urls:
70    // https://asecuritysite.com/hash/blake3
71    // https://emn178.github.io/online-tools/blake3.html
72    //
73    // For https://connor4312.github.io/blake3/index.html do the following:
74    // -> select utf-8 input option
75    // -> paste in "dapol;PoR;"
76    // -> see resulting hash is equal to b0424ae23fcce672aaff99e9f433286e27119939a280743539783ba7aade8294
77    //
78    // For https://toolkitbay.com/tkb/tool/BLAKE3 do the following:
79    // -> select "text input" option
80    // -> paste in "dapol;PoR;"
81    // -> click "process from text"
82    // -> see resulting hash is equal to b0424ae23fcce672aaff99e9f433286e27119939a280743539783ba7aade8294
83    #[test]
84    fn verify_hasher() {
85        use std::str::FromStr;
86
87        let mut hasher = Hasher::new();
88        hasher.update("dapol".as_bytes());
89        hasher.update("PoR".as_bytes());
90        let hash = hasher.finalize();
91        assert_eq!(
92            hash,
93            H256::from_str("b0424ae23fcce672aaff99e9f433286e27119939a280743539783ba7aade8294")
94                .unwrap()
95        );
96    }
97}