对于不同性能的性能的硬件环境的密码hash的设计
本方案适合从32Mb极端的边缘设计到高性能服务器的密码安全hash的设计。 在安全性和性能之间寻找平衡并支持平衡迁移无感自动升级。
主要是解决随着GPU性能暴涨,传统的密码hash已经无法满足目前的安全需求。
#灵活可演进的密码哈希方案 (适用)
本方案通过算法版本化 (Versioning) 适配从 低性能设备到高性能服务器的跨度,兼顾性能、并发与安全。
#1. 数据库存储结构
password_hash: 完整的哈希字符串(含参数和有可能存在的盐)password_type(uint8/int): 算法类型标识。 方便在代码里写switch-case分发给不同的加密库1: SHA2562: Bcrypt (标准模式,建议 Cost 10-12)。3: Argon2id (高安全模式,建议内存 64MB)。
#2. 系统运行逻辑
- 全局配置: 管理员根据当前硬件算力(如 0.125 Core 或 32MB RAM)设置系统当前默认算法。
- 新用户/改密: 强制采用“当前默认算法”进行加密并记录
password_type。 - 登录校验: 不参考全局配置,直接读取该用户的
password_type调用对应算法库进行验证。
#3. 平滑迁移与自动升级
向下兼容: 允许数据库中同时存在三种算法的哈希数据,确保从高性能迁移到低性能设备时,老用户仍能登录。
无感升级 (静默重哈希):- 当用户登录成功后,程序对比
user.password_type与 `system.default_password_type。
- 若用户算法版本不是系统配置,趁内存中持有明文密码,立即用新算法重算并覆盖数据库,实现数据随硬件升级而自动加固。
- 当用户登录成功后,程序对比
#4. 性能与安全平衡建议
- 32MB 设备: 默认选
1。PBKDF2 内存占用近乎零,且比单次 SHA256 更能抵抗暴力破解。 - 普通服务器: 默认选
2。Bcrypt 仅需 4KB 内存,能承受极高并发而不会导致 OOM。 - 安全型服务器: 默认选
3。Argon2id 提供最强的抗 GPU 破解能力。
第一性原则:在低性能硬件可以降低密码安全性换取高性能,在高性能硬件可以牺牲算力和内存换取密码安全。
开发过程注意点
- 数据库结构需要同时兼容sqlite和pgsql
- 把密码相关的单独封装到一个crate ,yh-password-hash
- 需要完善系统设置的可视化的性能配置模板,对其默认密码算法。
- 新增配置项目
- user_center.passwd_type # 当前默认算法:1-SHA256(PBKDF2), 2-Bcrypt, 3-Argon2
- user_center.passwd_auto_upgrade #默认true 登录成功后是否自动升级到当前默认算法
- user_center.passwd_Argon2_mem #默认32M 32768
- user_center.passwd_Argon2_t #默认3
- user_center.passwd_Argon2_p #默认1
- user_center.passwd_bcrypt_cost #默认10
- user_center.passwd_sha256_iterations #默认待定 - 默认迭代次数:建议
user_center.passwd_sha256_iterations默认值为 310,000 (OWASP 最新推荐标准)。对于 64MB 的极低功耗路由,可以允许用户下调至 50,000 以换取秒开体验。
- 因为 每种加密算法 需要记录的信息不同 ,Bcrypt 和 Argon2 有标准的 MCF/PHC 格式,但 PBKDF2 比较乱。为了兼容性,你需要规定一个存储标准:- 建议格式:
$pbkdf2-sha256$i=310000$salt$hash(仿照 Argon2 格式)。 - password_hash 长度:在 PG 中用
TEXT,在 SQLite 中也用TEXT。不要设定过短的VARCHAR(255),Argon2 的完整字符串可能很长。 - 原子更新:在执行“无感升级(静默重哈希)”时,代码必须在一个事务内完成,或者确保即使更新失败也不影响当前的登录会话(Session)
- 性能保护 实现一个简单的 并发校验限制。例如:同时进行的 Argon2 校验任务不得超过
N个,或者在校验失败后强制sleep几百毫秒。这在低功耗设备上是保命的 - rust
// 登录校验伪代码逻辑 伪代码 只是这个意思 let user = db.get_user(username); let is_valid = match user.password_type { 1 => pbkdf2::verify(input_password, user.password_hash), 2 => bcrypt::verify(input_password, user.password_hash), 3 => argon2::verify(input_password, user.password_hash), _ => return Error("Unknown algorithm"), }; if is_valid && config.passwd_auto_upgrade && user.password_type != config.passwd_type { // 异步或同步执行:用新算法重算并 Update 数据库 let new_hash = hash_with_config(input_password, config); db.update_password(user.id, new_hash, config.passwd_type); }
#最终补充 Checklist:
- 错误处理:如果配置文件中的算法参数(如 Argon2 内存)超过了物理机剩余内存,系统应报明确的错误,尽量避免直接panic
- 依赖库选型:建议使用 Rust 的
RustCrypto组织下的仓库(如argon2,bcrypt,pbkdf2),它们是纯 Rust 实现,跨平台支持(交叉编译到嵌入式设备)最好。 - 常量定义:将算法 ID (1, 2, 3) 定义为 Enum,增强代码可读性。
- 日志脱敏:在执行
passwd_auto_upgrade时,记录一条INFO日志,但绝对禁止打印哈希值或明文。