Skip to main content

pulith_verify/
hasher.rs

1use digest::Digest;
2
3/// Minimal hasher interface for streaming verification.
4/// Implementations must be Send for cross-thread safety.
5pub trait Hasher: Send {
6    /// Update the hash with new data.
7    fn update(&mut self, data: &[u8]);
8
9    /// Finalize and return the hash digest.
10    /// Consumes self to prevent reuse.
11    fn finalize(self) -> Vec<u8>;
12}
13
14/// Generic hasher wrapper for any `digest::Digest` implementation.
15/// Provides the primary way to use standard hashing algorithms.
16/// Enables composability with external crates like `sha2`, `sha3`, `blake3`.
17pub struct DigestHasher<D: digest::Digest + Send>(D);
18
19impl<D: digest::Digest + Send> DigestHasher<D> {
20    /// Create from a digest instance.
21    pub fn from_digest(digest: D) -> Self {
22        Self(digest)
23    }
24}
25
26impl<D: digest::Digest + Send> Hasher for DigestHasher<D> {
27    fn update(&mut self, data: &[u8]) {
28        self.0.update(data);
29    }
30
31    fn finalize(self) -> Vec<u8> {
32        self.0.finalize().to_vec()
33    }
34}
35
36/// Built-in hashers as type aliases and constructors for convenience.
37#[cfg(feature = "sha256")]
38pub type Sha256Hasher = DigestHasher<sha2::Sha256>;
39
40#[cfg(feature = "sha256")]
41impl Default for Sha256Hasher {
42    fn default() -> Self {
43        Self::new()
44    }
45}
46
47impl Sha256Hasher {
48    /// Create a new SHA-256 hasher instance.
49    pub fn new() -> Self {
50        DigestHasher::from_digest(sha2::Sha256::new())
51    }
52}
53
54#[cfg(feature = "blake3")]
55pub struct Blake3Hasher(blake3::Hasher);
56
57#[cfg(feature = "blake3")]
58impl Default for Blake3Hasher {
59    fn default() -> Self {
60        Self::new()
61    }
62}
63
64#[cfg(feature = "blake3")]
65impl Blake3Hasher {
66    /// Create a new Blake3 hasher instance.
67    pub fn new() -> Self {
68        Self(blake3::Hasher::new())
69    }
70}
71
72#[cfg(feature = "blake3")]
73impl Hasher for Blake3Hasher {
74    fn update(&mut self, data: &[u8]) {
75        self.0.update(data);
76    }
77
78    fn finalize(self) -> Vec<u8> {
79        self.0.finalize().as_bytes().to_vec()
80    }
81}
82
83#[cfg(feature = "sha3")]
84pub type Sha3_256Hasher = DigestHasher<sha3::Sha3_256>;
85
86#[cfg(feature = "sha3")]
87impl Sha3_256Hasher {
88    /// Create a new SHA3-256 hasher instance.
89    pub fn new() -> Self {
90        DigestHasher::from_digest(sha3::Sha3_256::new())
91    }
92}