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}