Skip to main content

flare_core/common/encryption/
algorithms.rs

1//! 内置加密算法实现
2//!
3//! 提供常用的加密算法实现
4
5use super::traits::Encryptor;
6use crate::common::error::{FlareError, Result};
7
8/// 加密算法类型枚举
9///
10/// 支持内置算法和自定义算法扩展
11#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
12pub enum EncryptionAlgorithm {
13    /// 不使用加密
14    None,
15    /// AES-256-GCM 加密
16    Aes256Gcm,
17    /// 自定义加密算法(通过字符串标识符)
18    ///
19    /// 使用此变体可以注册和使用自定义加密算法
20    /// 自定义算法必须通过 `EncryptionUtil::register_custom` 注册
21    ///
22    /// # 示例
23    /// ```rust
24    /// use flare_core::common::encryption::{EncryptionAlgorithm, EncryptionUtil, Encryptor};
25    /// use std::sync::Arc;
26    ///
27    /// // 注册自定义加密器
28    /// struct MyCustomEncryptor;
29    /// impl Encryptor for MyCustomEncryptor { /* ... */ }
30    ///
31    /// EncryptionUtil::register_custom(Arc::new(MyCustomEncryptor));
32    ///
33    /// // 使用自定义算法
34    /// let algo = EncryptionAlgorithm::Custom("my_custom".to_string());
35    /// ```
36    Custom(String),
37}
38
39impl EncryptionAlgorithm {
40    /// 从字符串转换为加密算法
41    ///
42    /// 如果字符串匹配内置算法,返回对应的枚举值
43    /// 否则返回 `Custom(String)` 变体
44    ///
45    /// # 示例
46    /// ```rust
47    /// use flare_core::common::encryption::EncryptionAlgorithm;
48    ///
49    /// assert_eq!(EncryptionAlgorithm::from_str("none"), Some(EncryptionAlgorithm::None));
50    /// assert_eq!(EncryptionAlgorithm::from_str("aes256gcm"), Some(EncryptionAlgorithm::Aes256Gcm));
51    /// assert_eq!(
52    ///     EncryptionAlgorithm::from_str("my_custom"),
53    ///     Some(EncryptionAlgorithm::Custom("my_custom".to_string()))
54    /// );
55    /// ```
56    #[allow(clippy::should_implement_trait)]
57    pub fn from_str(s: &str) -> Option<Self> {
58        match s.to_lowercase().as_str() {
59            "none" | "" => Some(EncryptionAlgorithm::None),
60            "aes256gcm" | "aes-256-gcm" => Some(EncryptionAlgorithm::Aes256Gcm),
61            custom => Some(EncryptionAlgorithm::Custom(custom.to_string())),
62        }
63    }
64
65    /// 转换为字符串标识符
66    ///
67    /// 返回算法的字符串表示,可用于注册表查找
68    ///
69    /// # 示例
70    /// ```rust
71    /// use flare_core::common::encryption::EncryptionAlgorithm;
72    ///
73    /// assert_eq!(EncryptionAlgorithm::None.as_str(), "none");
74    /// assert_eq!(EncryptionAlgorithm::Aes256Gcm.as_str(), "aes256gcm");
75    /// assert_eq!(EncryptionAlgorithm::Custom("my_custom".to_string()).as_str(), "my_custom");
76    /// ```
77    pub fn as_str(&self) -> String {
78        match self {
79            EncryptionAlgorithm::None => "none".to_string(),
80            EncryptionAlgorithm::Aes256Gcm => "aes256gcm".to_string(),
81            EncryptionAlgorithm::Custom(name) => name.clone(),
82        }
83    }
84
85    /// 检查是否是自定义算法
86    pub fn is_custom(&self) -> bool {
87        matches!(self, EncryptionAlgorithm::Custom(_))
88    }
89
90    /// 获取自定义算法名称(如果是自定义算法)
91    pub fn custom_name(&self) -> Option<&str> {
92        match self {
93            EncryptionAlgorithm::Custom(name) => Some(name),
94            _ => None,
95        }
96    }
97}
98
99/// 无加密器(直通)
100pub struct NoEncryptor;
101
102impl Encryptor for NoEncryptor {
103    fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
104        Ok(data.to_vec())
105    }
106
107    fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
108        Ok(data.to_vec())
109    }
110
111    fn algorithm(&self) -> EncryptionAlgorithm {
112        EncryptionAlgorithm::None
113    }
114
115    fn name(&self) -> &'static str {
116        "none"
117    }
118}
119
120/// AES-256-GCM 加密器
121///
122/// 使用 AES-256-GCM 算法进行加密,每次加密使用随机生成的 12 字节 nonce
123/// 加密后的数据格式: \[nonce (12 bytes)\]\[ciphertext\]
124///
125/// # 安全说明
126/// - 每次加密都会生成新的随机 nonce,确保相同明文产生不同密文
127/// - 密钥必须严格保密,建议使用安全的密钥派生函数(如 PBKDF2)从密码生成
128/// - nonce 会随密文一起存储,解密时需要提取
129pub struct Aes256GcmEncryptor {
130    #[cfg(feature = "encryption-aes-gcm")]
131    key: [u8; 32], // AES-256 需要 32 字节密钥
132}
133
134impl Aes256GcmEncryptor {
135    /// 创建新的 AES-256-GCM 加密器
136    ///
137    /// # 参数
138    /// - `key`: 32 字节的密钥
139    ///
140    /// # 错误
141    /// 如果密钥长度不是 32 字节,返回错误
142    pub fn new(key: &[u8]) -> Result<Self> {
143        #[cfg(not(feature = "encryption-aes-gcm"))]
144        {
145            let _ = key;
146            return Err(FlareError::operation_not_supported(
147                "aes-256-gcm encryption feature is disabled",
148            ));
149        }
150
151        #[cfg(feature = "encryption-aes-gcm")]
152        {
153            if key.len() != 32 {
154                return Err(FlareError::protocol_error(format!(
155                    "AES-256-GCM requires a 32-byte key, got {} bytes",
156                    key.len()
157                )));
158            }
159
160            let mut key_array = [0u8; 32];
161            key_array.copy_from_slice(key);
162
163            Ok(Self { key: key_array })
164        }
165    }
166
167    /// 从密码派生密钥(使用 PBKDF2)
168    ///
169    /// # 参数
170    /// - `password`: 密码
171    /// - `salt`: 盐值(可选,如果不提供则使用默认盐值)
172    ///
173    /// # 返回
174    /// 加密器实例
175    pub fn from_password(password: &[u8], salt: Option<&[u8]>) -> Result<Self> {
176        #[cfg(not(feature = "encryption-aes-gcm"))]
177        {
178            let _ = (password, salt);
179            return Err(FlareError::operation_not_supported(
180                "aes-256-gcm encryption feature is disabled",
181            ));
182        }
183
184        #[cfg(feature = "encryption-aes-gcm")]
185        {
186            use sha2::{Digest, Sha256};
187
188            let mut hasher = Sha256::new();
189            hasher.update(password);
190            if let Some(s) = salt {
191                hasher.update(s);
192            }
193            let key = hasher.finalize();
194
195            Self::new(&key)
196        }
197    }
198}
199
200impl Encryptor for Aes256GcmEncryptor {
201    fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
202        #[cfg(not(feature = "encryption-aes-gcm"))]
203        {
204            let _ = data;
205            return Err(FlareError::operation_not_supported(
206                "aes-256-gcm encryption feature is disabled",
207            ));
208        }
209
210        #[cfg(feature = "encryption-aes-gcm")]
211        {
212            use aes_gcm::{
213                Aes256Gcm as AesGcm,
214                aead::{Aead, AeadCore, KeyInit, OsRng},
215            };
216            tracing::debug!("Encrypting data: {:?}", data);
217            // 创建加密器
218            let cipher = AesGcm::new_from_slice(&self.key).map_err(|e| {
219                FlareError::encoding_error(format!("Failed to create AES-GCM cipher: {}", e))
220            })?;
221
222            // 生成随机 nonce(12 字节)
223            let nonce = AesGcm::generate_nonce(&mut OsRng);
224
225            // 加密数据
226            let ciphertext = cipher.encrypt(&nonce, data).map_err(|e| {
227                FlareError::encoding_error(format!("AES-GCM encryption failed: {}", e))
228            })?;
229
230            // 组合 nonce 和 ciphertext: [nonce (12 bytes)][ciphertext]
231            // nonce 是 GenericArray<u8, U12>,转换为数组
232            // 使用 into() 将 GenericArray 转换为数组
233            let nonce_bytes: [u8; 12] = nonce.into();
234            let mut result = Vec::with_capacity(12 + ciphertext.len());
235            result.extend_from_slice(&nonce_bytes);
236            result.extend_from_slice(&ciphertext);
237
238            Ok(result)
239        }
240    }
241
242    fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
243        #[cfg(not(feature = "encryption-aes-gcm"))]
244        {
245            let _ = data;
246            return Err(FlareError::operation_not_supported(
247                "aes-256-gcm encryption feature is disabled",
248            ));
249        }
250
251        #[cfg(feature = "encryption-aes-gcm")]
252        {
253            use aes_gcm::{
254                Aes256Gcm as AesGcm, Nonce,
255                aead::{Aead, KeyInit},
256            };
257
258            tracing::debug!("Decrypting data: {:?}", data);
259            // 检查数据长度(至少需要 12 字节 nonce)
260            if data.len() < 12 {
261                return Err(FlareError::deserialization_error(format!(
262                    "Encrypted data too short: expected at least 12 bytes, got {}",
263                    data.len()
264                )));
265            }
266
267            // 提取 nonce 和 ciphertext
268            let (nonce_bytes, ciphertext) = data.split_at(12);
269
270            // 将 nonce_bytes 转换为固定大小数组
271            let nonce_array: [u8; 12] = nonce_bytes.try_into().map_err(|_| {
272                FlareError::deserialization_error(
273                    "Failed to convert nonce bytes to array".to_string(),
274                )
275            })?;
276
277            // 创建 Nonce(使用 From trait)
278            let nonce = Nonce::from(nonce_array);
279
280            // 创建解密器
281            let cipher = AesGcm::new_from_slice(&self.key).map_err(|e| {
282                FlareError::encoding_error(format!("Failed to create AES-GCM cipher: {}", e))
283            })?;
284
285            // 解密数据
286            let plaintext = cipher.decrypt(&nonce, ciphertext).map_err(|e| {
287                FlareError::deserialization_error(format!("AES-GCM decryption failed: {}", e))
288            })?;
289
290            Ok(plaintext)
291        }
292    }
293
294    fn algorithm(&self) -> EncryptionAlgorithm {
295        EncryptionAlgorithm::Aes256Gcm
296    }
297
298    fn name(&self) -> &'static str {
299        "aes256gcm"
300    }
301}