1use sha2::{Sha224, Sha256, Sha384, Sha512, Digest};
2use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512, Keccak224, Keccak256, Keccak384, Keccak512};
3use blake2::{Blake2b512, Blake2s256};
4use blake3::Hasher as Blake3Hasher;
5use md5::Md5;
6use twox_hash::{XxHash32, XxHash64};
7use twox_hash::xxhash3_64::Hasher as Xxh3Hash64;
8use twox_hash::xxhash3_128::Hasher as Xxh3Hash128;
9use std::hash::Hasher;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum HashAlgorithm {
14 Md5,
15 Sha224,
16 Sha256,
17 Sha384,
18 Sha512,
19 Sha3_224,
20 Sha3_256,
21 Sha3_384,
22 Sha3_512,
23 Keccak224,
24 Keccak256,
25 Keccak384,
26 Keccak512,
27 Blake2b,
28 Blake2s,
29 Blake3,
30 Crc32,
32 Crc32c,
33 Crc16,
34 Crc64,
35 XxHash32,
37 XxHash64,
38 XxHash3_64,
39 XxHash3_128,
40}
41
42impl HashAlgorithm {
43 pub fn from_str(s: &str) -> Result<Self, String> {
45 match s.to_lowercase().as_str() {
46 "md5" => Ok(HashAlgorithm::Md5),
47 "sha224" | "sha-224" => Ok(HashAlgorithm::Sha224),
48 "sha256" | "sha-256" => Ok(HashAlgorithm::Sha256),
49 "sha384" | "sha-384" => Ok(HashAlgorithm::Sha384),
50 "sha512" | "sha-512" => Ok(HashAlgorithm::Sha512),
51 "sha3-224" | "sha3_224" => Ok(HashAlgorithm::Sha3_224),
52 "sha3-256" | "sha3_256" => Ok(HashAlgorithm::Sha3_256),
53 "sha3-384" | "sha3_384" => Ok(HashAlgorithm::Sha3_384),
54 "sha3-512" | "sha3_512" => Ok(HashAlgorithm::Sha3_512),
55 "keccak224" | "keccak-224" => Ok(HashAlgorithm::Keccak224),
56 "keccak256" | "keccak-256" => Ok(HashAlgorithm::Keccak256),
57 "keccak384" | "keccak-384" => Ok(HashAlgorithm::Keccak384),
58 "keccak512" | "keccak-512" => Ok(HashAlgorithm::Keccak512),
59 "blake2b" | "blake2b-512" => Ok(HashAlgorithm::Blake2b),
60 "blake2s" | "blake2s-256" => Ok(HashAlgorithm::Blake2s),
61 "blake3" => Ok(HashAlgorithm::Blake3),
62 "crc32" => Ok(HashAlgorithm::Crc32),
63 "crc32c" => Ok(HashAlgorithm::Crc32c),
64 "crc16" => Ok(HashAlgorithm::Crc16),
65 "crc64" => Ok(HashAlgorithm::Crc64),
66 "xxhash32" | "xxh32" => Ok(HashAlgorithm::XxHash32),
67 "xxhash64" | "xxh64" => Ok(HashAlgorithm::XxHash64),
68 "xxhash3" | "xxh3" | "xxhash3-64" | "xxh3-64" => Ok(HashAlgorithm::XxHash3_64),
69 "xxhash3-128" | "xxh3-128" => Ok(HashAlgorithm::XxHash3_128),
70 _ => Err(format!("Unknown hash algorithm: {}", s)),
71 }
72 }
73
74 pub fn as_str(&self) -> &str {
75 match self {
76 HashAlgorithm::Md5 => "md5",
77 HashAlgorithm::Sha224 => "sha224",
78 HashAlgorithm::Sha256 => "sha256",
79 HashAlgorithm::Sha384 => "sha384",
80 HashAlgorithm::Sha512 => "sha512",
81 HashAlgorithm::Sha3_224 => "sha3-224",
82 HashAlgorithm::Sha3_256 => "sha3-256",
83 HashAlgorithm::Sha3_384 => "sha3-384",
84 HashAlgorithm::Sha3_512 => "sha3-512",
85 HashAlgorithm::Keccak224 => "keccak224",
86 HashAlgorithm::Keccak256 => "keccak256",
87 HashAlgorithm::Keccak384 => "keccak384",
88 HashAlgorithm::Keccak512 => "keccak512",
89 HashAlgorithm::Blake2b => "blake2b",
90 HashAlgorithm::Blake2s => "blake2s",
91 HashAlgorithm::Blake3 => "blake3",
92 HashAlgorithm::Crc32 => "crc32",
93 HashAlgorithm::Crc32c => "crc32c",
94 HashAlgorithm::Crc16 => "crc16",
95 HashAlgorithm::Crc64 => "crc64",
96 HashAlgorithm::XxHash32 => "xxhash32",
97 HashAlgorithm::XxHash64 => "xxhash64",
98 HashAlgorithm::XxHash3_64 => "xxhash3-64",
99 HashAlgorithm::XxHash3_128 => "xxhash3-128",
100 }
101 }
102
103 pub fn output_size(&self) -> usize {
105 match self {
106 HashAlgorithm::Md5 => 16,
107 HashAlgorithm::Sha224 => 28,
108 HashAlgorithm::Sha256 => 32,
109 HashAlgorithm::Sha384 => 48,
110 HashAlgorithm::Sha512 => 64,
111 HashAlgorithm::Sha3_224 => 28,
112 HashAlgorithm::Sha3_256 => 32,
113 HashAlgorithm::Sha3_384 => 48,
114 HashAlgorithm::Sha3_512 => 64,
115 HashAlgorithm::Keccak224 => 28,
116 HashAlgorithm::Keccak256 => 32,
117 HashAlgorithm::Keccak384 => 48,
118 HashAlgorithm::Keccak512 => 64,
119 HashAlgorithm::Blake2b => 64,
120 HashAlgorithm::Blake2s => 32,
121 HashAlgorithm::Blake3 => 32,
122 HashAlgorithm::Crc16 => 2,
123 HashAlgorithm::Crc32 => 4,
124 HashAlgorithm::Crc32c => 4,
125 HashAlgorithm::Crc64 => 8,
126 HashAlgorithm::XxHash32 => 4,
127 HashAlgorithm::XxHash64 => 8,
128 HashAlgorithm::XxHash3_64 => 8,
129 HashAlgorithm::XxHash3_128 => 16,
130 }
131 }
132}
133
134pub fn hash(data: &[u8], algorithm: HashAlgorithm) -> Vec<u8> {
136 match algorithm {
137 HashAlgorithm::Md5 => {
138 let mut hasher = Md5::new();
139 hasher.update(data);
140 hasher.finalize().to_vec()
141 }
142 HashAlgorithm::Sha224 => {
143 let mut hasher = Sha224::new();
144 hasher.update(data);
145 hasher.finalize().to_vec()
146 }
147 HashAlgorithm::Sha256 => {
148 let mut hasher = Sha256::new();
149 hasher.update(data);
150 hasher.finalize().to_vec()
151 }
152 HashAlgorithm::Sha384 => {
153 let mut hasher = Sha384::new();
154 hasher.update(data);
155 hasher.finalize().to_vec()
156 }
157 HashAlgorithm::Sha512 => {
158 let mut hasher = Sha512::new();
159 hasher.update(data);
160 hasher.finalize().to_vec()
161 }
162 HashAlgorithm::Sha3_224 => {
163 let mut hasher = Sha3_224::new();
164 hasher.update(data);
165 hasher.finalize().to_vec()
166 }
167 HashAlgorithm::Sha3_256 => {
168 let mut hasher = Sha3_256::new();
169 hasher.update(data);
170 hasher.finalize().to_vec()
171 }
172 HashAlgorithm::Sha3_384 => {
173 let mut hasher = Sha3_384::new();
174 hasher.update(data);
175 hasher.finalize().to_vec()
176 }
177 HashAlgorithm::Sha3_512 => {
178 let mut hasher = Sha3_512::new();
179 hasher.update(data);
180 hasher.finalize().to_vec()
181 }
182 HashAlgorithm::Keccak224 => {
183 let mut hasher = Keccak224::new();
184 hasher.update(data);
185 hasher.finalize().to_vec()
186 }
187 HashAlgorithm::Keccak256 => {
188 let mut hasher = Keccak256::new();
189 hasher.update(data);
190 hasher.finalize().to_vec()
191 }
192 HashAlgorithm::Keccak384 => {
193 let mut hasher = Keccak384::new();
194 hasher.update(data);
195 hasher.finalize().to_vec()
196 }
197 HashAlgorithm::Keccak512 => {
198 let mut hasher = Keccak512::new();
199 hasher.update(data);
200 hasher.finalize().to_vec()
201 }
202 HashAlgorithm::Blake2b => {
203 let mut hasher = Blake2b512::new();
204 hasher.update(data);
205 hasher.finalize().to_vec()
206 }
207 HashAlgorithm::Blake2s => {
208 let mut hasher = Blake2s256::new();
209 hasher.update(data);
210 hasher.finalize().to_vec()
211 }
212 HashAlgorithm::Blake3 => {
213 let mut hasher = Blake3Hasher::new();
214 hasher.update(data);
215 hasher.finalize().as_bytes().to_vec()
216 }
217 HashAlgorithm::Crc16 => {
218 let crc = crc::Crc::<u16>::new(&crc::CRC_16_IBM_SDLC);
219 let result = crc.checksum(data);
220 result.to_be_bytes().to_vec()
221 }
222 HashAlgorithm::Crc32 => {
223 let crc = crc::Crc::<u32>::new(&crc::CRC_32_ISO_HDLC);
224 let result = crc.checksum(data);
225 result.to_be_bytes().to_vec()
226 }
227 HashAlgorithm::Crc32c => {
228 let crc = crc::Crc::<u32>::new(&crc::CRC_32_ISCSI);
229 let result = crc.checksum(data);
230 result.to_be_bytes().to_vec()
231 }
232 HashAlgorithm::Crc64 => {
233 let crc = crc::Crc::<u64>::new(&crc::CRC_64_ECMA_182);
234 let result = crc.checksum(data);
235 result.to_be_bytes().to_vec()
236 }
237 HashAlgorithm::XxHash32 => {
238 let mut hasher = XxHash32::with_seed(0);
239 hasher.write(data);
240 (hasher.finish() as u32).to_be_bytes().to_vec()
241 }
242 HashAlgorithm::XxHash64 => {
243 let mut hasher = XxHash64::with_seed(0);
244 hasher.write(data);
245 hasher.finish().to_be_bytes().to_vec()
246 }
247 HashAlgorithm::XxHash3_64 => {
248 let mut hasher = Xxh3Hash64::with_seed(0);
249 hasher.write(data);
250 hasher.finish().to_be_bytes().to_vec()
251 }
252 HashAlgorithm::XxHash3_128 => {
253 let mut hasher = Xxh3Hash128::with_seed(0);
254 hasher.write(data);
255 hasher.finish_128().to_be_bytes().to_vec()
256 }
257 }
258}
259
260#[cfg(test)]
261mod tests {
262 use super::*;
263
264 #[test]
265 fn test_md5() {
266 let data = b"hello world";
267 let hash = hash(data, HashAlgorithm::Md5);
268 assert_eq!(hash.len(), 16);
269 assert_eq!(hex::encode(&hash), "5eb63bbbe01eeed093cb22bb8f5acdc3");
271 }
272
273 #[test]
274 fn test_sha256() {
275 let data = b"hello world";
276 let hash = hash(data, HashAlgorithm::Sha256);
277 assert_eq!(hash.len(), 32);
278 assert_eq!(
280 hex::encode(&hash),
281 "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
282 );
283 }
284
285 #[test]
286 fn test_sha512() {
287 let data = b"hello world";
288 let hash = hash(data, HashAlgorithm::Sha512);
289 assert_eq!(hash.len(), 64);
290 }
291
292 #[test]
293 fn test_sha3_256() {
294 let data = b"hello world";
295 let hash = hash(data, HashAlgorithm::Sha3_256);
296 assert_eq!(hash.len(), 32);
297 }
298
299 #[test]
300 fn test_blake2b() {
301 let data = b"hello world";
302 let hash = hash(data, HashAlgorithm::Blake2b);
303 assert_eq!(hash.len(), 64);
304 }
305
306 #[test]
307 fn test_blake2s() {
308 let data = b"hello world";
309 let hash = hash(data, HashAlgorithm::Blake2s);
310 assert_eq!(hash.len(), 32);
311 }
312
313 #[test]
314 fn test_blake3() {
315 let data = b"hello world";
316 let hash = hash(data, HashAlgorithm::Blake3);
317 assert_eq!(hash.len(), 32);
318 }
319
320 #[test]
321 fn test_empty_input() {
322 let data = b"";
323 let hash = hash(data, HashAlgorithm::Sha256);
324 assert_eq!(hash.len(), 32);
325 assert_eq!(
327 hex::encode(&hash),
328 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
329 );
330 }
331
332 #[test]
333 fn test_output_sizes() {
334 assert_eq!(HashAlgorithm::Md5.output_size(), 16);
335 assert_eq!(HashAlgorithm::Sha256.output_size(), 32);
336 assert_eq!(HashAlgorithm::Sha512.output_size(), 64);
337 assert_eq!(HashAlgorithm::Blake3.output_size(), 32);
338 assert_eq!(HashAlgorithm::Crc16.output_size(), 2);
339 assert_eq!(HashAlgorithm::Crc32.output_size(), 4);
340 assert_eq!(HashAlgorithm::Crc64.output_size(), 8);
341 assert_eq!(HashAlgorithm::XxHash32.output_size(), 4);
342 assert_eq!(HashAlgorithm::XxHash64.output_size(), 8);
343 assert_eq!(HashAlgorithm::XxHash3_64.output_size(), 8);
344 assert_eq!(HashAlgorithm::XxHash3_128.output_size(), 16);
345 }
346
347 #[test]
348 fn test_crc32() {
349 let data = b"hello world";
350 let result = hash(data, HashAlgorithm::Crc32);
351 assert_eq!(result.len(), 4);
352 let result2 = hash(data, HashAlgorithm::Crc32);
354 assert_eq!(result, result2);
355 }
356
357 #[test]
358 fn test_crc32c() {
359 let data = b"hello world";
360 let result = hash(data, HashAlgorithm::Crc32c);
361 assert_eq!(result.len(), 4);
362 }
363
364 #[test]
365 fn test_crc16() {
366 let data = b"hello world";
367 let result = hash(data, HashAlgorithm::Crc16);
368 assert_eq!(result.len(), 2);
369 }
370
371 #[test]
372 fn test_crc64() {
373 let data = b"hello world";
374 let result = hash(data, HashAlgorithm::Crc64);
375 assert_eq!(result.len(), 8);
376 }
377
378 #[test]
379 fn test_xxhash32() {
380 let data = b"hello world";
381 let result = hash(data, HashAlgorithm::XxHash32);
382 assert_eq!(result.len(), 4);
383 let result2 = hash(data, HashAlgorithm::XxHash32);
385 assert_eq!(result, result2);
386 }
387
388 #[test]
389 fn test_xxhash64() {
390 let data = b"hello world";
391 let result = hash(data, HashAlgorithm::XxHash64);
392 assert_eq!(result.len(), 8);
393 }
394
395 #[test]
396 fn test_xxhash3_64() {
397 let data = b"hello world";
398 let result = hash(data, HashAlgorithm::XxHash3_64);
399 assert_eq!(result.len(), 8);
400 }
401
402 #[test]
403 fn test_xxhash3_128() {
404 let data = b"hello world";
405 let result = hash(data, HashAlgorithm::XxHash3_128);
406 assert_eq!(result.len(), 16);
407 }
408}