cardano_crypto/hash/
blake2b.rs1use alloc::vec::Vec;
9
10use super::HashAlgorithm;
11use blake2::digest::consts::{U28, U32};
12use blake2::{Blake2b, Digest};
13
14#[derive(Clone, Debug)]
29pub struct Blake2b224;
30
31impl HashAlgorithm for Blake2b224 {
32 const OUTPUT_SIZE: usize = 28;
33 const ALGORITHM_NAME: &'static str = "blake2b_224";
34
35 #[inline]
36 fn hash(data: &[u8]) -> Vec<u8> {
37 let mut hasher = Blake2b::<U28>::new();
38 hasher.update(data);
39 hasher.finalize().to_vec()
40 }
41}
42
43#[derive(Clone, Debug)]
59pub struct Blake2b256;
60
61impl HashAlgorithm for Blake2b256 {
62 const OUTPUT_SIZE: usize = 32;
63 const ALGORITHM_NAME: &'static str = "blake2b_256";
64
65 #[inline]
66 fn hash(data: &[u8]) -> Vec<u8> {
67 let mut hasher = Blake2b::<U32>::new();
68 hasher.update(data);
69 hasher.finalize().to_vec()
70 }
71}
72
73#[derive(Clone, Debug)]
88pub struct Blake2b512;
89
90impl HashAlgorithm for Blake2b512 {
91 const OUTPUT_SIZE: usize = 64;
92 const ALGORITHM_NAME: &'static str = "blake2b_512";
93
94 #[inline]
95 fn hash(data: &[u8]) -> Vec<u8> {
96 use blake2::Blake2b512 as Blake2b512Hasher;
97
98 let mut hasher = Blake2b512Hasher::new();
99 hasher.update(data);
100 hasher.finalize().to_vec()
101 }
102}
103
104#[must_use]
108#[allow(dead_code)]
109pub(crate) fn blake2b224(data: &[u8]) -> [u8; 28] {
110 let mut hasher = Blake2b::<U28>::new();
111 hasher.update(data);
112 hasher.finalize().into()
113}
114
115#[must_use]
119#[allow(dead_code)]
120pub(crate) fn blake2b256(data: &[u8]) -> [u8; 32] {
121 let mut hasher = Blake2b::<U32>::new();
122 hasher.update(data);
123 hasher.finalize().into()
124}
125
126#[must_use]
130#[allow(dead_code)]
131pub(crate) fn blake2b512(data: &[u8]) -> [u8; 64] {
132 use blake2::Blake2b512 as Blake2b512Hasher;
133
134 let mut hasher = Blake2b512Hasher::new();
135 hasher.update(data);
136 hasher.finalize().into()
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_blake2b224_empty() {
145 let expected = "836cc68931c2e4e3e838602eca1902591d216837bafddfe6f0c8cb07";
146 let out = Blake2b224::hash(b"");
147 assert_eq!(hex::encode(out), expected);
148 }
149
150 #[test]
151 fn test_blake2b224_hello_world() {
152 let expected = "42d1854b7d69e3b57c64fcc7b4f64171b47dff43fba6ac0499ff437f";
153 let out = Blake2b224::hash(b"hello world");
154 assert_eq!(hex::encode(out), expected);
155 }
156
157 #[test]
158 fn test_blake2b256_empty() {
159 let expected = "0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8";
160 let out = Blake2b256::hash(b"");
161 assert_eq!(hex::encode(out), expected);
162 }
163
164 #[test]
165 fn test_blake2b256_hello_world() {
166 let expected = "256c83b297114d201b30179f3f0ef0cace9783622da5974326b436178aeef610";
167 let out = Blake2b256::hash(b"hello world");
168 assert_eq!(hex::encode(out), expected);
169 }
170
171 #[test]
172 fn test_blake2b512_empty() {
173 let expected = "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce";
174 let out = Blake2b512::hash(b"");
175 assert_eq!(hex::encode(out), expected);
176 }
177
178 #[test]
179 fn test_blake2b512_hello_world() {
180 let expected = "021ced8799296ceca557832ab941a50b4a11f83478cf141f51f933f653ab9fbcc05a037cddbed06e309bf334942c4e58cdf1a46e237911ccd7fcf9787cbc7fd0";
181 let out = Blake2b512::hash(b"hello world");
182 assert_eq!(hex::encode(out), expected);
183 }
184
185 #[test]
186 fn test_hash_concat() {
187 let data1 = b"hello";
188 let data2 = b"world";
189 let hash1 = Blake2b256::hash_concat(data1, data2);
190 let hash2 = Blake2b256::hash(b"helloworld");
191 assert_eq!(hash1, hash2);
192 }
193
194 #[test]
195 fn test_expand_seed() {
196 let seed = b"test seed";
197 let (seed0, seed1) = Blake2b256::expand_seed(seed);
198 assert_eq!(seed0.len(), 32);
199 assert_eq!(seed1.len(), 32);
200 assert_ne!(seed0, seed1, "Expanded seeds should be different");
201 }
202
203 #[test]
204 fn test_blake2b256_not_simple_truncation() {
205 let cases = [
206 b"".as_ref(),
207 b"cardano".as_ref(),
208 b"longer-message".as_ref(),
209 ];
210
211 for input in cases {
212 let blake512 = Blake2b512::hash(input);
213 let blake256 = Blake2b256::hash(input);
214 assert_ne!(&blake512[..32], &blake256[..]);
215 }
216 }
217
218 #[test]
219 fn test_blake2b224_not_truncation() {
220 let cases = [
221 b"".as_ref(),
222 b"address-key".as_ref(),
223 b"longer-message".as_ref(),
224 ];
225
226 for input in cases {
227 let blake512 = Blake2b512::hash(input);
228 let blake224 = Blake2b224::hash(input);
229 assert_ne!(&blake512[..28], &blake224[..]);
230
231 let blake256 = Blake2b256::hash(input);
232 assert_ne!(&blake256[..28], &blake224[..]);
233 }
234 }
235}
236
237#[cfg(test)]
239mod hex {
240 pub(crate) fn encode(bytes: impl AsRef<[u8]>) -> String {
241 bytes
242 .as_ref()
243 .iter()
244 .map(|b| format!("{:02x}", b))
245 .collect()
246 }
247}