### 你的建议 / Your suggestion 希望将个人主密码的密钥派生从一次 SHA-256 + 固定字符串升级为 Argon2id + 随机盐,并提供版本化、可恢复的旧数据迁移。此建议与 #459 的本地自动解锁存储保护互补,解决的是加密数据或验证数据泄露后的离线猜测风险。 ### 当前实现与影响 基于当前 main(6773a65)的静态阅读,crates/core/src/crypto.rs 的 derive_key 使用 SHA-256(master_key || 固定字符串) 直接生成 AES-256-GCM 密钥,没有迭代成本或内存成本。固定字符串不是每个用户/保险库独立的随机盐。 generate_key_verification 使用该密钥加密固定验证文本;个人云同步将 key_verification 写入 user_configs。拿到验证数据的人可在本机测试候选主密码,不经过登录接口,因此验证码和服务端限速不能阻止这种离线猜测。即使不保存独立验证文本,AES-GCM 密文本身的认证标签也可用于验证候选密钥,所以重点应是加强 KDF,而不只是移除验证文本。 这里不意味着 SHA-256 或 AES-256-GCM 被破解,也不意味着高熵随机主密码可以轻易被猜中;问题是普通用户口令的猜测成本过低。 ### 建议方案 1. 使用 Argon2id,从主密码和每个用户/保险库独立生成的随机盐派生密钥。盐无需保密,但应随加密格式保存;AES-GCM 的随机 nonce 与 KDF 的盐应分别生成和使用。 2. 将格式版本、KDF 算法、盐和成本参数显式持久化并支持跨设备同步。可参考现有 team_key_envelope.rs 的 Argon2id 方案(64 MiB、3 次迭代、并行度 1),结合目标设备性能实测确定参数;读取时对参数设置合理上限。 3. 可采用随机数据密钥 + 主密码派生密钥包装数据密钥的结构,使后续修改主密码或升级 KDF 更易维护;个人验证路径也应避免保留旧的快速 SHA-256 验证数据成为薄弱入口。 4. 兼容识别旧格式,在用户成功解锁后迁移:验证新数据可解密后再切换,覆盖本地连接、凭据、相关密钥缓存及个人同步记录/验证数据,保证中断后可恢复,并处理旧客户端兼容性。历史备份、Git 历史或云端旧快照仍可能保留旧格式,应明确告知保护边界。 5. 增加旧格式迁移、新格式跨设备解密、错误主密码、篡改数据及迁移中断恢复的测试,并继续提醒用户使用独立的强主密码。 ### 补充信息 / Additional context 源码依据(静态阅读,未对发布安装包进行抓包或破解实测): - 个人密钥派生与验证:https://github.com/feigeCode/navop/blob/6773a65b73e5c89e3f884d6c24b3f2d7059d2bac/crates/core/src/crypto.rs#L147 - 验证数据上传:https://github.com/feigeCode/navop/blob/6773a65b73e5c89e3f884d6c24b3f2d7059d2bac/crates/core/src/cloud_sync/supabase.rs#L1519 - 已有团队 Argon2id 实现:https://github.com/feigeCode/navop/blob/6773a65b73e5c89e3f884d6c24b3f2d7059d2bac/crates/core/src/cloud_sync/team_key_envelope.rs - OWASP 对抗离线猜测的密码哈希建议:https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
Activity
feat(core): 主密钥 KDF 升级为 Argon2id 并改用系统凭据库 (#459, #460)