next_web_utils/
digester.rs

1use std::io::Read;
2use std::path::Path;
3use std::fs::File;
4use std::string::String;
5use std::vec::Vec;
6use md2::Md2;
7use md5;
8use sha1::Sha1;
9use sha2::{Sha256, Sha384, Sha512, Digest};
10
11/// 哈希算法枚举
12///  
13/// Hash Algorithm Enum
14#[derive(Debug, Clone, Copy)]
15pub enum HashAlgorithm {
16    /// MD2 哈希算法 
17    /// 
18    ///  MD2 Hash Algorithm
19    Md2,
20    /// MD5 哈希算法 
21    /// 
22    ///  MD5 Hash Algorithm
23    Md5,
24    /// SHA-1 哈希算法 
25    /// 
26    ///  SHA-1 Hash Algorithm
27    Sha1,
28    /// SHA-256 哈希算法 
29    /// 
30    ///  SHA-256 Hash Algorithm
31    Sha256,
32    /// SHA-384 哈希算法 
33    /// 
34    ///  SHA-384 Hash Algorithm
35    Sha384,
36    /// SHA-512 哈希算法 
37    /// 
38    ///  SHA-512 Hash Algorithm
39    Sha512,
40}
41
42/// 哈希计算器 trait
43/// 
44/// Hash Calculator Trait
45pub trait Digester {
46    /// 计算哈希值
47    /// 
48    /// Calculate hash value
49    /// 
50    /// # Arguments
51    /// * `algorithm` - 使用的哈希算法
52    /// 
53    /// # Returns
54    /// * `String` - 十六进制格式的哈希值
55    fn hash(&self, algorithm: HashAlgorithm) -> String;
56}
57
58impl Digester for String {
59    fn hash(&self, algorithm: HashAlgorithm) -> String {
60        self.as_bytes().hash(algorithm)
61    }
62}
63
64impl Digester for &[u8] {
65    fn hash(&self, algorithm: HashAlgorithm) -> String {
66        match algorithm {
67            HashAlgorithm::Md2 => {
68                let mut hasher = Md2::new();
69                hasher.update(self);
70                format!("{:x}", hasher.finalize())
71            }
72            HashAlgorithm::Md5 => {
73                let digest = md5::compute(self);
74                format!("{:x}", digest)
75            }
76            HashAlgorithm::Sha1 => {
77                let mut hasher = Sha1::new();
78                hasher.update(self);
79                format!("{:x}", hasher.finalize())
80            }
81            HashAlgorithm::Sha256 => {
82                let mut hasher = Sha256::new();
83                hasher.update(self);
84                format!("{:x}", hasher.finalize())
85            }
86            HashAlgorithm::Sha384 => {
87                let mut hasher = Sha384::new();
88                hasher.update(self);
89                format!("{:x}", hasher.finalize())
90            }
91            HashAlgorithm::Sha512 => {
92                let mut hasher = Sha512::new();
93                hasher.update(self);
94                format!("{:x}", hasher.finalize())
95            }
96        }
97    }
98}
99
100impl Digester for Vec<u8> {
101    fn hash(&self, algorithm: HashAlgorithm) -> String {
102        self.as_slice().hash(algorithm)
103    }
104}
105
106impl Digester for File {
107    fn hash(&self, algorithm: HashAlgorithm) -> String {
108        let mut buffer = Vec::new();
109        let mut file = self.try_clone().unwrap();
110        file.read_to_end(&mut buffer).unwrap();
111        buffer.hash(algorithm)
112    }
113}
114
115/// 计算文件的哈希值 
116/// 
117///  Calculate file hash
118/// 
119/// # Arguments / 参数
120/// * `path` - 文件路径 
121/// 
122///  File path
123///
124/// * `algorithm` - 使用的哈希算法 
125/// 
126///  Hash algorithm to use
127/// 
128/// # Returns 
129///  返回值
130/// * `std::io::Result<String>` - 十六进制格式的哈希值 
131///  Hash value in hexadecimal format
132/// 
133/// # Errors 
134///  错误
135/// * 如果文件无法打开或读取 / If the file cannot be opened or read
136pub fn hash_file<P: AsRef<Path>>(path: P, algorithm: HashAlgorithm) -> std::io::Result<String> {
137    let file = File::open(path)?;
138    Ok(file.hash(algorithm))
139}
140
141#[cfg(test)]
142mod tests {
143    use super::*;
144
145    /// 测试字符串哈希 
146    /// 
147    /// Test string hashing
148    #[test]
149    fn test_string_hash() {
150        let text = "Hello, World!".to_string();
151        let md5_hash = text.hash(HashAlgorithm::Md5);
152        assert_eq!(md5_hash, "65a8e27d8879283831b664bd8b7f0ad4");
153        
154        let sha256_hash = text.hash(HashAlgorithm::Sha256);
155        assert_eq!(sha256_hash, "dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f");
156    }
157
158    /// 测试字节数组哈希 
159    /// 
160    /// Test byte array hashing
161    #[test]
162    fn test_bytes_hash() {
163        let bytes = vec![1, 2, 3, 4, 5];
164        let md5_hash = bytes.hash(HashAlgorithm::Md5);
165        assert_eq!(md5_hash, "7cfdd07889b3295d6a550914ab35e068");
166        
167        let sha1_hash = bytes.hash(HashAlgorithm::Sha1);
168        assert_eq!(sha1_hash, "8f9baf15c0c6aa4887d832e415735772a5a05a5c");
169    }
170}