正确的生成器,
正确的语言。
并非所有密码生成器都一样。你的保险库由哪种语言编写,也绝不是工程师才需要关心的细节。本文解析熵、生成模式,以及为什么 Rust 正在成为底层安全的关键选择。
当密码管理器声称“生成强密码”时,有两个问题必须回答:它真的不可预测吗(随机性的质量),以及显示之后它在内存中会发生什么?前者取决于生成模式,后者取决于运行应用程序的语言。本文会同时解释这两点。
01 / 基础熵:唯一真正重要的指标
密码强度不应按主观感受中的“复杂度”衡量,而应按熵衡量:也就是攻击者面对的不确定性位数。可能组合越多,暴力破解成本就越呈爆炸式增长。一个从完整 ASCII 字符集中随机抽取的 16 字符密码约有 100 bits 熵,属于“非常强”的范畴。
一个经常被忽视的关键点是:只有当随机源是 CSPRNG(加密安全伪随机数生成器)时,熵才有意义。普通的 Math.random() 是可预测的,会让其余设计全部失效。优秀实现会从操作系统读取熵:Unix 下的 /dev/urandom 或 getrandom(2),Windows 下的 CNG。
02 / 模式四类生成器
优秀的管理器不应只提供“一个”生成器,而应提供多种适配不同用途的模式。规则很简单:可记忆性要用长度来换。下面是四类方式,从最高密度到最贴近人类记忆依次排列。
纯随机
j7$kQ!mP2#xR9vL@口令短语(Diceware / EFF)
Granite-Bicycle-Phantom-Violet-9可记忆 / 可发音
Crimson7!Falcon$Reef数字 PIN
8392 4471正确习惯:让熵匹配用途
对于受登录页面限速保护的 Web 账户,攻击者通常被限制在每秒几百次尝试以内:即使 50 bits 也足以支撑极其漫长的破解时间。超高熵只对离线机密有意义,例如加密密钥或加密钱包 seed,因为这类攻击可以被大规模并行化。 对于这些极高价值的机密,使用真实物理骰子(严格意义上的 Diceware)仍然是终极选择:它消除了对 CSPRNG 质量或受攻陷浏览器的任何依赖。
03 / 底层机制为什么 Rust 改变了局面
生成一个好密码只是工作的一半。另一半是:不要让它在内存中游荡。密码一旦显示或解密,就会存在于 RAM 中,而这正是应用程序所用语言变得决定性的地方。
Microsoft 报告称,其遇到的安全漏洞中有 70% 是内存 bug(buffer overflow、use-after-free 等)。Google 在 Chrome 和 Android 上也观察到相同比例。Rust 通过所有权模型(ownership)和借用模型(borrowing),在编译期消除了这些漏洞类别,而且不需要垃圾回收器。
Google 的数据很有说服力:Android 的内存漏洞从 2019 年的 223 个降至 2024 年的不到 50 个,首次跌破总漏洞数的 20%。新的 Rust 代码相较历史 C/C++ 代码,内存漏洞密度最高可降低 1000 倍,同时 rollback 减少 4 倍,代码审查时间减少 25%。
1. 没有垃圾回收器的内存安全。 Java 或 Python 等语言同样具备内存安全性,但它们的 garbage collector 会以非确定性的方式释放内存:秘密可能无限期残留其中,暴露在 memory dump 或 cold-boot 攻击之下。Rust 会在数据不再使用时确定性地释放内存。
2. 使用 zeroize 显式擦除。 Rust 并不保证已释放内存会被覆盖。zeroize crate 补上了这个缺口:把秘密包装在 Zeroizing 中,就能保证它在离开作用域的确切时刻被零覆盖,这通过编译器无法优化掉的 volatile 写入实现。
3. 强制正确使用密码学的类型系统。 Rust 严格的类型系统可以限定敏感数据如何被使用,以及能被使用多少次。例如,可以建模一把只能使用一次的密钥,编译器会拒绝任何重复使用。
自动内存擦除use zeroize::Zeroizing;
fn unlock_vault(master: &str) {
let dek = Zeroizing::new(derive_key(master));
// ... 解密保险库 ...
} // `dek` 会在此处自动被零覆盖内存漏洞 — ANDROID(占总数百分比)
采用 RUST
技术上要诚实:Rust 不是魔法棒
unsafe 代码和第三方依赖仍然是攻击面。Google 就曾在投产前修复过 Rust 解析器中一个 unsafe 代码块里的漏洞(CVE-2025-48530)。内存安全是一层防护,而不是终点:它必须与纵深防御结合,例如 Argon2id 等强健 KDF、zero-knowledge 架构、自动锁定和 MFA。
垃圾回收语言
- 内存释放时间不确定
- 秘密会在内存中残留未知时长
- 显式擦除困难或不可行
- 暴露于 dump 与 cold-boot 攻击
Rust
- 确定性释放(ownership)
- 通过 zeroize 立即擦除
- 没有 buffer overflow 或 use-after-free
- 密码学使用错误在编译期被捕获
04 / 要点你应向密码管理器提出的要求
在选择或评估密码管理器时,可以直接问四个具体问题:
检查清单
- 1. 生成器是否基于系统 CSPRNG,并以 bits 显示熵?
- 2. 是否为主密码提供 Diceware/EFF 口令短语模式?
- 3. 生成过程是否本地执行(client-side),不会经过服务器?
- 4. 敏感核心是否用内存安全语言编写,并显式擦除秘密?