安全指南
使用 Web Crypto 和拒绝采样进行客户端密码生成
一份技术白皮书,解释 PwdGen 的浏览器端密码生成模型、熵边界、拒绝采样和隐私限制。
摘要
PwdGen 使用客户端参考生成方法:浏览器或运行时 Web Crypto 提供随机字节,拒绝采样将这些字节映射到无偏的有限索引,Fisher-Yates 洗牌将所需的字符类别分布到最终密码中。该方法刻意保持小巧、可审计,并且可在 Web 应用、API 适配器、CLI 以及准备好的 pwdgen-core 包中重现。
本文档描述了工程模型。它并非声称新的密码学原语、正式标准或独立的第三方审计。
随机性来源
生成器通过 crypto.getRandomValues() 请求密码学强度的随机值。Web Crypto 实现应使用由主机环境提供的高质量熵种子化的密码学安全伪随机数生成器。实际上,浏览器将此责任委托给操作系统设施和平台密码学提供者。
PwdGen 并不声称每次密码生成调用都直接采样硬件噪声源。更安全、更准确的说法是,浏览器通过 Web Crypto API 提供 CSPRNG 输出,并且 PwdGen 避免使用非密码学伪随机接口。
为什么不使用 Math.random()
Math.random() 不适用于安全敏感用途。它适用于模拟、视觉效果和普通的随机 UI 行为,但不提供密码、重置码、签名密钥或其他凭证所需的保证。
PwdGen 将不安全的伪随机回退视为失败状态。如果 Web Crypto 不可用,生成器应显示兼容性错误,而不是静默生成弱凭证。
拒绝采样
随机字节和整数通常从 2 的幂次范围中抽取。密码字母表的大小很少能整除该范围。直接取模运算可能使某些字符比其他字符略有可能。
PwdGen 使用拒绝采样:
- 抽取一个 32 位无符号整数。
- 计算适合 32 位范围内的最大字母表大小倍数。
- 拒绝超出该边界的值。
- 仅对剩余的完整范围应用取模。
这保持了有界字符选择的均匀性,而不会引入可测量的模偏差。
字符覆盖与熵
对于配置的密码策略,生成器首先从每个启用的类别中选择一个字符,从组合字母表中填充剩余部分,然后对结果进行洗牌。这有助于满足目标密码规则,而不会将可预测的类别放在可预测的位置。
理论熵估计为:
bits = length × log2(uniqueAlphabetSize)
该值是从配置字母表中均匀随机选择的上限。它不考虑密码重用、用户编辑的输出、受损设备、泄露的密码或目标服务的弱存储。
隐私边界
在浏览器工具中,生成的值保留在页面内存和可见的结果字段中,直到用户复制或导出它们。本地生成器不会将生成的密码发送到 PwdGen 服务器、放入 URL 或写入分析事件。
此边界不能防御恶意浏览器扩展、剪贴板管理器、操作系统受损、屏幕截图、钓鱼页面或用户将生成的密码粘贴到不安全的目标。
可重现的实现
公共的 pwdgen-cli 包和准备好的 pwdgen-core 包的存在是为了使生成模型在网页之外可检查。单元测试涵盖字符类别包含、排除字符、无效配置、熵公式以及缺少不安全的伪随机回退代码路径。
目标不是使 PwdGen 成为私有标准。目标是使实现足够小,以便开发人员可以在其环境需要不同信任边界时阅读、测试和替换它。