密码是数字世界的第一道防线。据统计,超过 80% 的数据泄露事件与弱密码或密码复用有关。但"使用强密码"这条建议过于笼统——什么才是"强"?为什么强?本文从密码学的熵(Entropy)概念出发,剖析常见攻击方式,教你用科学方法生成真正安全的密码。
密码强度的数学基础:熵
在密码学中,密码的强度用信息熵(Shannon Entropy)来衡量,单位是比特(bits)。熵值越高,密码被猜测或破解的难度就越大。计算公式为:
H = L × log₂(N)
其中:
H= 熵值(bits)L= 密码长度(字符数)N= 字符集大小(可用字符种类数)
例如,仅使用小写字母(N=26)的 8 位密码:
H = 8 × log₂(26) ≈ 8 × 4.7 = 37.6 bits
而使用大小写字母、数字和符号(N≈94)的 16 位密码:
H = 16 × log₂(94) ≈ 16 × 6.55 = 104.8 bits
熵值每增加 1 bit,破解难度翻倍。从 37.6 bits 到 104.8 bits,难度增加了约 2^67 倍——这是一个天文数字。
密码熵值等级评估
- < 40 bits:极弱。现代 GPU 可在毫秒级暴力破解
- 40–60 bits:弱。家用计算机可在数小时至数天内破解
- 60–80 bits:中等。需要专用硬件和较长时间
- 80–128 bits:强。当前计算能力下不可暴力破解
- > 128 bits:极强。理论上即使动用全球算力也需要亿万年
NIST(美国国家标准与技术研究院)最新指南建议:最低 8 位,推荐 15 位以上。OWASP 则明确建议至少 12 位。
常见密码攻击方式
了解攻击方式,才能理解为什么需要高熵密码:
1. 暴力破解(Brute Force)
攻击者遍历所有可能的字符组合,逐一尝试。攻击效率取决于两个因素:密码熵值和攻击者算力。一张 NVIDIA RTX 4090 每秒可尝试数十亿次 SHA-256 哈希。8 位纯数字密码在几秒内就会被破解。
2. 字典攻击(Dictionary Attack)
不遍历所有组合,而是使用预先准备好的"密码字典"——包含常见密码、单词、短语、变体(如 Password1、P@ssw0rd)。据统计,Top 1000 常用密码覆盖了约 90% 的用户账户。
3. 撞库攻击(Credential Stuffing)
从 A 网站泄露的用户名-密码组合,批量尝试登录 B、C、D 网站。如果你在不同网站使用相同密码,一个平台的泄露就意味着所有平台的沦陷。据 Verizon 报告,近 50% 的数据泄露与凭证窃取有关。
4. 彩虹表攻击(Rainbow Table)
针对未加盐(salt)的哈希密码。攻击者预先计算大量常见密码的哈希值,建立"哈希→明文"映射表。使用 MD5/SHA1 且无盐哈希的系统极易遭受此类攻击。
5. 社会工程学
最高效的攻击往往不需要技术。通过钓鱼邮件、假冒客服、社交工程获取密码。再强的密码也防不住主动泄露。
如何正确使用密码生成器
密码生成器是创建高熵密码的最佳工具,但需要正确使用才能发挥其价值。
原则一:使用密码学安全的随机数源
普通的 Math.random() 是伪随机数,基于种子值可预测。优秀的密码生成器应采用 crypto.getRandomValues(),它使用操作系统级的熵源(硬件噪声、中断时间等),生成密码学安全的随机数:
// ❌ 不安全的伪随机数
function weakRandom(length) {
const chars = 'abcdefghijklmnopqrstuvwxyz';
let result = '';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
// ✅ 密码学安全的随机数
function secureRandom(length) {
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';
const array = new Uint32Array(length);
crypto.getRandomValues(array);
return Array.from(array, x => chars[x % chars.length]).join('');
}
原则二:长度优先于复杂度
一个 20 位的纯小写字母密码(熵 ≈ 94 bits)比一个 10 位的混合密码(熵 ≈ 65 bits)更安全。长度是提升熵值的最有效方式。
推荐配置:
- 普通账户:16 位,包含大小写+数字+符号
- 金融/邮箱账户:20 位以上
- API Key / 根密钥:32 位以上
原则三:排除易混淆字符
如果需要手动输入(如 WiFi 密码、银行 U 盾),建议排除易混淆字符:0 与 O、l 与 1 与 I。好的密码生成器提供一键排除选项。
原则四:每个账户独立密码
这是防止撞库攻击的唯一方法。人脑无法记忆几十个复杂密码,必须使用密码管理器(Bitwarden、1Password、KeePass 等)安全存储。
密码存储的安全实践(开发者视角)
如果你是开发者,处理用户密码时必须遵守以下原则:
- 绝不存储明文密码。永远存储哈希值
- 使用专用密码哈希算法。如 bcrypt、scrypt、Argon2,而非 MD5/SHA-256
- 添加随机盐值(Salt)。每个用户独立随机盐,防御彩虹表攻击
- 设置工作因子(Work Factor)。bcrypt 成本因子至少 10-12,使哈希计算耗时 >100ms
- 实施登录速率限制。防止在线暴力破解
// Node.js bcrypt 示例
const bcrypt = require('bcrypt');
const saltRounds = 12;
// 注册时哈希密码
const hash = await bcrypt.hash(plaintextPassword, saltRounds);
// 登录时验证
const match = await bcrypt.compare(inputPassword, storedHash);
双重验证:密码的终极补强
即使密码足够强,启用双重验证(2FA/MFA)仍至关重要。推荐优先级:
- 硬件安全密钥:YubiKey、Titan Security Key(防钓鱼最强)
- TOTP 应用:Google Authenticator、Aegis、Microsoft Authenticator
- 短信验证:最后选择,易受 SIM swapping 攻击
总结
密码安全不是玄学,而是可量化的科学。通过熵值公式,我们可以精确计算密码强度;了解攻击方式,可以针对性地提升防御能力。密码生成器结合密码管理器和双重验证,构成了现代数字身份的三层防护体系。记住:安全是一种习惯,而非一次性的任务。