merkleforge_hash/
keccak256.rs1use merkle_core::traits::HashFunction;
22use tiny_keccak::{Hasher, Keccak};
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub struct Keccak256;
30
31impl Keccak256 {
32 #[inline]
34 fn new_hasher() -> Keccak {
35 Keccak::v256()
36 }
37}
38
39impl HashFunction for Keccak256 {
40 type Digest = [u8; 32];
41
42 #[inline]
44 fn hash(data: &[u8]) -> [u8; 32] {
45 let mut out = [0u8; 32];
46 let mut h = Self::new_hasher();
47 h.update(&[0x00]); h.update(data);
49 h.finalize(&mut out);
50 out
51 }
52
53 #[inline]
55 fn hash_nodes(left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
56 let mut out = [0u8; 32];
57 let mut h = Self::new_hasher();
58 h.update(&[0x01]); h.update(left);
60 h.update(right);
61 h.finalize(&mut out);
62 out
63 }
64
65 fn algorithm_name() -> &'static str {
66 "Keccak-256"
67 }
68
69 fn digest_size() -> usize {
70 32
71 }
72}
73
74#[cfg(test)]
77mod tests {
78 use super::*;
79 use merkle_core::traits::HashFunction;
80
81 #[test]
84 fn known_vector_empty_string() {
85 let mut out = [0u8; 32];
87 let mut h = Keccak::v256();
88 h.update(b"");
89 h.finalize(&mut out);
90 let expected = [
91 0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7,
92 0x03, 0xc0, 0xe5, 0x00, 0xb6, 0x53, 0xca, 0x82, 0x27, 0x3b, 0x7b, 0xfa, 0xd8, 0x04,
93 0x5d, 0x85, 0xa4, 0x70,
94 ];
95 assert_eq!(out, expected);
96 }
97
98 #[test]
99 fn digest_size_is_32() {
100 assert_eq!(Keccak256::digest_size(), 32);
101 }
102
103 #[test]
104 fn algorithm_name() {
105 assert_eq!(Keccak256::algorithm_name(), "Keccak-256");
106 }
107
108 #[test]
109 fn hash_deterministic() {
110 assert_eq!(Keccak256::hash(b"test"), Keccak256::hash(b"test"));
111 }
112
113 #[test]
114 fn hash_nodes_non_commutative() {
115 let a = [0xAAu8; 32];
116 let b = [0xBBu8; 32];
117 assert_ne!(Keccak256::hash_nodes(&a, &b), Keccak256::hash_nodes(&b, &a));
118 }
119
120 #[test]
121 fn hash_and_hash_nodes_differ() {
122 let data = [0x42u8; 32];
124 let leaf = Keccak256::hash(&data);
125 let node = Keccak256::hash_nodes(&data, &data);
126 assert_ne!(leaf, node);
127 }
128}