uselesskey_core_hash/
lib.rs1#![forbid(unsafe_code)]
2#![cfg_attr(not(feature = "std"), no_std)]
3pub use blake3::{Hash, Hasher};
9
10pub fn hash32(bytes: &[u8]) -> Hash {
12 blake3::hash(bytes)
13}
14
15pub fn write_len_prefixed(hasher: &mut Hasher, bytes: &[u8]) {
19 let len = u32::try_from(bytes.len()).unwrap_or(u32::MAX);
20 hasher.update(&len.to_be_bytes());
21 hasher.update(bytes);
22}
23
24#[cfg(test)]
25mod tests {
26 use super::{hash32, write_len_prefixed};
27 use blake3::Hasher;
28 use proptest::prelude::*;
29
30 #[test]
31 fn hash32_matches_blake3_hash() {
32 let data = b"deterministic-fixture-hash";
33 assert_eq!(hash32(data), blake3::hash(data));
34 }
35
36 #[test]
37 fn write_len_prefixed_uses_big_endian_length() {
38 let data = b"abc";
39 let expected_len = 3u32.to_be_bytes();
40
41 let mut hasher = Hasher::new();
42 hasher.update(&expected_len);
43 hasher.update(data);
44 let expected = hasher.finalize();
45
46 let mut hasher2 = Hasher::new();
47 write_len_prefixed(&mut hasher2, data);
48 let actual = hasher2.finalize();
49
50 assert_eq!(actual, expected);
51 }
52
53 #[test]
54 fn len_prefix_changes_on_boundary_change() {
55 let mut a_left = Hasher::new();
56 write_len_prefixed(&mut a_left, b"a");
57 write_len_prefixed(&mut a_left, b"bc");
58
59 let mut b_left = Hasher::new();
60 write_len_prefixed(&mut b_left, b"ab");
61 write_len_prefixed(&mut b_left, b"c");
62
63 assert_ne!(a_left.finalize(), b_left.finalize());
64 }
65
66 #[test]
67 fn hash32_empty_input() {
68 let h = hash32(b"");
69 assert_eq!(h, blake3::hash(b""));
70 }
71
72 #[test]
73 fn write_len_prefixed_empty_data() {
74 let mut hasher = Hasher::new();
75 write_len_prefixed(&mut hasher, b"");
76 let actual = hasher.finalize();
77
78 let mut expected_hasher = Hasher::new();
79 expected_hasher.update(&0u32.to_be_bytes());
80 assert_eq!(actual, expected_hasher.finalize());
81 }
82
83 #[test]
84 fn hash32_different_inputs_differ() {
85 assert_ne!(hash32(b"alpha"), hash32(b"beta"));
86 }
87
88 proptest! {
89 #![proptest_config(ProptestConfig { cases: 64, ..ProptestConfig::default() })]
90
91 #[test]
92 fn hash32_is_deterministic_for_random_inputs(data in any::<Vec<u8>>()) {
93 let first = hash32(&data);
94 let second = hash32(&data);
95 assert_eq!(first, second);
96 }
97
98 #[test]
99 fn write_len_prefixed_matches_direct_length_encoding(data in any::<Vec<u8>>()) {
100 let expected_len = (u32::try_from(data.len()).unwrap_or(u32::MAX)).to_be_bytes();
101
102 let mut direct = Hasher::new();
103 direct.update(&expected_len);
104 direct.update(&data);
105 let expected = direct.finalize();
106
107 let mut prefixed = Hasher::new();
108 write_len_prefixed(&mut prefixed, &data);
109 let actual = prefixed.finalize();
110
111 assert_eq!(actual, expected);
112 }
113 }
114}