Skip to main content

audit_trail/hashers/
sha256.rs

1//! SHA-256 [`Hasher`] backed by the [`sha2`] crate. Requires the `sha2`
2//! feature.
3
4use sha2::Digest as _;
5
6use crate::hash::{Digest, HASH_LEN, Hasher};
7
8/// SHA-256 [`Hasher`].
9///
10/// The most common production hasher for audit-trail. SHA-256 is a FIPS
11/// 180-4 standard primitive, 32-byte output, widely accepted by HIPAA,
12/// SOC 2, PCI-DSS, and other compliance frameworks.
13///
14/// # Example
15///
16/// ```
17/// use audit_trail::{Digest, Hasher, Sha256Hasher};
18///
19/// let mut hasher = Sha256Hasher::new();
20/// hasher.update(b"audit-trail");
21/// let mut out = Digest::ZERO;
22/// hasher.finalize(&mut out);
23/// // SHA-256("audit-trail") = 4e9b…
24/// assert_ne!(out, Digest::ZERO);
25/// ```
26#[derive(Clone, Default)]
27pub struct Sha256Hasher(sha2::Sha256);
28
29impl Sha256Hasher {
30    /// Construct a fresh [`Sha256Hasher`].
31    #[inline]
32    pub fn new() -> Self {
33        Self(sha2::Sha256::new())
34    }
35}
36
37impl core::fmt::Debug for Sha256Hasher {
38    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
39        f.debug_struct("Sha256Hasher").finish_non_exhaustive()
40    }
41}
42
43impl Hasher for Sha256Hasher {
44    #[inline]
45    fn reset(&mut self) {
46        self.0 = sha2::Sha256::new();
47    }
48
49    #[inline]
50    fn update(&mut self, bytes: &[u8]) {
51        sha2::Digest::update(&mut self.0, bytes);
52    }
53
54    #[inline]
55    fn finalize(&mut self, out: &mut Digest) {
56        let result = self.0.finalize_reset();
57        let mut bytes = [0u8; HASH_LEN];
58        bytes.copy_from_slice(&result);
59        *out = Digest::from_bytes(bytes);
60    }
61}