签入版本
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
# 密码工具
|
||||
|
||||
:::tip 说明
|
||||
项目采用 bcrypt 双重加盐方案存储密码,源码位于 `src/core/password.py`。工作因子 12(约 250ms),在安全性和性能之间取得平衡。
|
||||
:::
|
||||
|
||||
## 加密方案
|
||||
|
||||
密码存储采用「外部随机盐 + bcrypt 内部盐」双重加盐方案:
|
||||
|
||||
```
|
||||
用户密码 + 外部盐 → bcrypt.hashpw → 存储哈希值
|
||||
```
|
||||
|
||||
### 生成盐值
|
||||
|
||||
```python
|
||||
import secrets
|
||||
|
||||
BCRYPT_ROUNDS = 12 # 工作因子,约250ms
|
||||
|
||||
def generate_salt(length: int = 10) -> str:
|
||||
"""生成随机盐值"""
|
||||
return secrets.token_urlsafe(length)[:length]
|
||||
```
|
||||
|
||||
### 加密密码
|
||||
|
||||
```python
|
||||
import bcrypt
|
||||
|
||||
def encrypt_password(password: str, salt: str) -> str:
|
||||
"""使用 bcrypt 加密密码(外部 salt 双重加盐)"""
|
||||
combined = (password + salt).encode('utf-8')
|
||||
hashed = bcrypt.hashpw(combined, bcrypt.gensalt(rounds=BCRYPT_ROUNDS))
|
||||
return hashed.decode('utf-8')
|
||||
```
|
||||
|
||||
### 验证密码
|
||||
|
||||
```python
|
||||
def verify_password(password: str, salt: str, hashed: str) -> bool:
|
||||
"""验证密码是否正确"""
|
||||
combined = (password + salt).encode('utf-8')
|
||||
return bcrypt.checkpw(combined, hashed.encode('utf-8'))
|
||||
```
|
||||
|
||||
## 工作因子
|
||||
|
||||
`BCRYPT_ROUNDS = 12` 表示 bcrypt 的工作因子为 12,即需要 2^12 = 4096 次迭代。值越大计算越慢越安全,12 是当前推荐值(约 250ms)。
|
||||
|
||||
:::tip 温馨提示
|
||||
bcrypt 的工作因子决定了加密速度。增加 1 会使计算时间翻倍。建议保持默认值 12,在安全性和性能之间取得平衡。
|
||||
:::
|
||||
|
||||
## 存储结构
|
||||
|
||||
用户表中密码相关字段:
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `password` | bcrypt 哈希后的密码 |
|
||||
| `salt` | 外部随机盐值 |
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 注册/创建用户
|
||||
|
||||
```python
|
||||
from src.core.password import generate_salt, encrypt_password
|
||||
|
||||
salt = generate_salt()
|
||||
hashed = encrypt_password("mypassword", salt)
|
||||
# 将 hashed 和 salt 存入数据库
|
||||
```
|
||||
|
||||
### 登录验证
|
||||
|
||||
登录验证位于 `src/modules/auth/service.py`:
|
||||
|
||||
```python
|
||||
from src.core.password import verify_password
|
||||
|
||||
# 从数据库获取用户记录
|
||||
user = get_user_by_username(username)
|
||||
|
||||
# 验证密码
|
||||
password_ok = verify_password(data['password'], user.salt or '', user.password or '')
|
||||
if password_ok:
|
||||
# 密码正确
|
||||
...
|
||||
```
|
||||
|
||||
### 修改密码
|
||||
|
||||
```python
|
||||
# 验证旧密码
|
||||
if not verify_password(old_password, user.salt, user.password):
|
||||
return R.failed("原密码错误")
|
||||
|
||||
# 生成新盐值并加密
|
||||
new_salt = generate_salt()
|
||||
new_hashed = encrypt_password(new_password, new_salt)
|
||||
# 更新数据库
|
||||
```
|
||||
|
||||
## 安全特性
|
||||
|
||||
```
|
||||
1. 双重加盐:外部随机盐 + bcrypt 内部盐,即使两个用户使用相同密码,存储的哈希值也不同
|
||||
2. 抗彩虹表:bcrypt 自带盐值,无法预计算彩虹表
|
||||
3. 抗暴力破解:工作因子 12 使每次验证约 250ms,大幅增加暴力破解成本
|
||||
4. 自适应性:工作因子可随硬件提升而增加
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
密码工具采用 bcrypt 双重加盐方案,外部盐值由 `secrets.token_urlsafe()` 生成,bcrypt 内部盐自动处理。工作因子 12 在安全性和性能之间取得平衡,有效抵御彩虹表和暴力破解攻击。
|
||||
Reference in New Issue
Block a user