Skip to main content

driven/binary/
checksum.rs

1//! Blake3 Integrity Verification
2//!
3//! Cryptographic checksums for rule integrity.
4
5/// Blake3 checksum (first 16 bytes for compact storage)
6pub type Blake3Checksum = [u8; 16];
7
8/// Compute Blake3 hash of data
9pub fn compute_blake3(data: &[u8]) -> Blake3Checksum {
10    let hash = blake3::hash(data);
11    let mut checksum = [0u8; 16];
12    checksum.copy_from_slice(&hash.as_bytes()[..16]);
13    checksum
14}
15
16/// Verify Blake3 checksum
17pub fn verify_blake3(data: &[u8], expected: &Blake3Checksum) -> bool {
18    let computed = compute_blake3(data);
19    computed == *expected
20}
21
22/// Full Blake3 hash (32 bytes)
23pub fn full_blake3(data: &[u8]) -> [u8; 32] {
24    *blake3::hash(data).as_bytes()
25}
26
27/// Keyed Blake3 MAC
28pub fn keyed_blake3(key: &[u8; 32], data: &[u8]) -> [u8; 32] {
29    *blake3::keyed_hash(key, data).as_bytes()
30}
31
32/// Incremental hasher for streaming
33#[derive(Debug)]
34pub struct Blake3Hasher {
35    hasher: blake3::Hasher,
36}
37
38impl Blake3Hasher {
39    /// Create a new hasher
40    pub fn new() -> Self {
41        Self {
42            hasher: blake3::Hasher::new(),
43        }
44    }
45
46    /// Create a keyed hasher
47    pub fn new_keyed(key: &[u8; 32]) -> Self {
48        Self {
49            hasher: blake3::Hasher::new_keyed(key),
50        }
51    }
52
53    /// Update with more data
54    pub fn update(&mut self, data: &[u8]) {
55        self.hasher.update(data);
56    }
57
58    /// Finalize and get checksum
59    pub fn finalize(self) -> Blake3Checksum {
60        let hash = self.hasher.finalize();
61        let mut checksum = [0u8; 16];
62        checksum.copy_from_slice(&hash.as_bytes()[..16]);
63        checksum
64    }
65
66    /// Finalize and get full hash
67    pub fn finalize_full(self) -> [u8; 32] {
68        *self.hasher.finalize().as_bytes()
69    }
70}
71
72impl Default for Blake3Hasher {
73    fn default() -> Self {
74        Self::new()
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn test_compute_verify() {
84        let data = b"Hello, World!";
85        let checksum = compute_blake3(data);
86
87        assert!(verify_blake3(data, &checksum));
88        assert!(!verify_blake3(b"Different data", &checksum));
89    }
90
91    #[test]
92    fn test_incremental() {
93        let data = b"Hello, World!";
94
95        let direct = compute_blake3(data);
96
97        let mut hasher = Blake3Hasher::new();
98        hasher.update(b"Hello, ");
99        hasher.update(b"World!");
100        let incremental = hasher.finalize();
101
102        assert_eq!(direct, incremental);
103    }
104
105    #[test]
106    fn test_full_hash() {
107        let data = b"test";
108        let hash = full_blake3(data);
109        assert_eq!(hash.len(), 32);
110    }
111
112    #[test]
113    fn test_keyed_hash() {
114        let key = [0u8; 32];
115        let data = b"test";
116
117        let hash1 = keyed_blake3(&key, data);
118        let hash2 = keyed_blake3(&key, data);
119
120        assert_eq!(hash1, hash2);
121    }
122}