1use hmac::Mac;
4use sha2::{Digest, Sha256};
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct ContentHash([u8; 32]);
9
10impl ContentHash {
11 pub fn from_bytes(bytes: [u8; 32]) -> Self {
13 Self(bytes)
14 }
15 pub fn as_bytes(&self) -> &[u8; 32] {
17 &self.0
18 }
19}
20
21pub struct ContentHasher(Sha256);
23
24impl ContentHasher {
25 pub fn new() -> Self {
27 Self(Sha256::new())
28 }
29 pub fn update(&mut self, bytes: &[u8]) {
31 self.0.update(bytes);
32 }
33 pub fn finish(self) -> ContentHash {
35 ContentHash(self.0.finalize().into())
36 }
37}
38
39impl std::fmt::Debug for ContentHasher {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 f.write_str("ContentHasher(..)")
42 }
43}
44
45#[cfg(test)]
46#[path = "hashing_tests.rs"]
47mod tests;
48
49#[derive(Clone)]
55pub struct AuthorshipHasher(zeroize::Zeroizing<[u8; 32]>);
56
57impl AuthorshipHasher {
58 pub(crate) fn new(key: &[u8; 32]) -> Self {
59 Self(zeroize::Zeroizing::new(*key))
60 }
61
62 pub fn leaf(&self, leaf: &[u8]) -> [u8; 32] {
64 let mut mac = crate::derivation::mac(&self.0);
65 mac.update(&[0]);
66 mac.update(leaf);
67 mac.finalize().into_bytes().into()
68 }
69}
70
71pub fn authorship_node(left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
73 let mut hash = Sha256::new();
74 hash.update([1]);
75 hash.update(left);
76 hash.update(right);
77 hash.finalize().into()
78}
79
80pub fn authorship_empty() -> [u8; 32] {
82 Sha256::digest([2]).into()
83}
84
85pub fn kept_value_digest(encoded: &[u8]) -> [u8; 32] {
91 Sha256::digest(crate::cipher::context(&[crate::derivation::KEPT_VALUE, encoded])).into()
92}
93
94impl std::fmt::Debug for AuthorshipHasher {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 f.write_str("AuthorshipHasher([REDACTED])")
97 }
98}