Skip to main content

wae_crypto/
password.rs

1//! 密码哈希和验证模块
2
3use crate::error::{CryptoError, CryptoResult};
4use argon2::{
5    Argon2, PasswordHash, PasswordHasher as Argon2PasswordHasher, PasswordVerifier, Version, password_hash::SaltString,
6};
7use zeroize::Zeroize;
8
9/// 密码哈希算法
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum PasswordAlgorithm {
12    /// bcrypt 算法
13    Bcrypt,
14    /// argon2 算法
15    Argon2,
16}
17
18/// 密码哈希器配置
19#[derive(Debug, Clone)]
20pub struct PasswordHasherConfig {
21    /// 密码哈希算法
22    pub algorithm: PasswordAlgorithm,
23    /// bcrypt 成本因子
24    pub bcrypt_cost: u32,
25    /// argon2 内存成本(KB)
26    pub argon2_memory_cost: u32,
27    /// argon2 时间成本
28    pub argon2_time_cost: u32,
29    /// argon2 并行度
30    pub argon2_parallelism: u32,
31}
32
33impl Default for PasswordHasherConfig {
34    fn default() -> Self {
35        Self {
36            algorithm: PasswordAlgorithm::Bcrypt,
37            bcrypt_cost: 12,
38            argon2_memory_cost: 19456,
39            argon2_time_cost: 2,
40            argon2_parallelism: 1,
41        }
42    }
43}
44
45/// 密码哈希器
46#[derive(Debug, Clone)]
47pub struct PasswordHasher {
48    config: PasswordHasherConfig,
49}
50
51impl PasswordHasher {
52    /// 创建新的密码哈希器
53    pub fn new(config: PasswordHasherConfig) -> Self {
54        Self { config }
55    }
56
57    /// 使用默认配置创建密码哈希器
58    pub fn default() -> Self {
59        Self::new(PasswordHasherConfig::default())
60    }
61
62    /// 哈希密码
63    pub fn hash_password(&self, password: &str) -> CryptoResult<String> {
64        let mut password_bytes = password.as_bytes().to_vec();
65        let result = match self.config.algorithm {
66            PasswordAlgorithm::Bcrypt => self.hash_bcrypt(&password_bytes),
67            PasswordAlgorithm::Argon2 => self.hash_argon2(&password_bytes),
68        };
69        password_bytes.zeroize();
70        result
71    }
72
73    /// 验证密码
74    pub fn verify_password(&self, password: &str, hash: &str) -> CryptoResult<bool> {
75        let mut password_bytes = password.as_bytes().to_vec();
76        let result = match self.config.algorithm {
77            PasswordAlgorithm::Bcrypt => self.verify_bcrypt(&password_bytes, hash),
78            PasswordAlgorithm::Argon2 => self.verify_argon2(&password_bytes, hash),
79        };
80        password_bytes.zeroize();
81        result
82    }
83
84    /// 使用 bcrypt 哈希密码
85    fn hash_bcrypt(&self, password: &[u8]) -> CryptoResult<String> {
86        bcrypt::hash(password, self.config.bcrypt_cost).map_err(|_| CryptoError::PasswordHashError)
87    }
88
89    /// 使用 bcrypt 验证密码
90    fn verify_bcrypt(&self, password: &[u8], hash: &str) -> CryptoResult<bool> {
91        bcrypt::verify(password, hash).map_err(|_| CryptoError::PasswordVerifyError)
92    }
93
94    /// 使用 argon2 哈希密码
95    fn hash_argon2(&self, password: &[u8]) -> CryptoResult<String> {
96        use argon2::password_hash::rand_core::OsRng;
97        let mut rng = OsRng;
98        let salt = SaltString::generate(&mut rng);
99        let argon2 = Argon2::new(
100            argon2::Algorithm::Argon2id,
101            Version::V0x13,
102            argon2::Params::new(
103                self.config.argon2_memory_cost,
104                self.config.argon2_time_cost,
105                self.config.argon2_parallelism,
106                None,
107            )
108            .map_err(|_| CryptoError::PasswordHashError)?,
109        );
110        let password_hash = argon2.hash_password(password, &salt).map_err(|_| CryptoError::PasswordHashError)?;
111        Ok(password_hash.to_string())
112    }
113
114    /// 使用 argon2 验证密码
115    fn verify_argon2(&self, password: &[u8], hash: &str) -> CryptoResult<bool> {
116        let parsed_hash = PasswordHash::new(hash).map_err(|_| CryptoError::PasswordVerifyError)?;
117        let argon2 = Argon2::default();
118        Ok(argon2.verify_password(password, &parsed_hash).is_ok())
119    }
120}
121
122impl Default for PasswordHasher {
123    fn default() -> Self {
124        Self::new(PasswordHasherConfig::default())
125    }
126}