
什么使密码变强?
密码强度归结为一个指标:熵(entropy)——攻击者必须克服的随机性位数。熵越高,需要尝试的组合越多,破解所需时间越长。
公式:
熵(位)= log₂(字符集大小 ^ 密码长度)
= 密码长度 × log₂(字符集大小)
| 字符集 | 大小 | 12位熵 | 16位熵 |
|---|---|---|---|
| 仅数字 | 10 | 39.9 位 | 53.1 位 |
| 仅小写字母 | 26 | 56.4 位 | 75.2 位 |
| 小写+大写 | 52 | 68.4 位 | 91.2 位 |
| 小写+大写+数字 | 62 | 71.5 位 | 95.3 位 |
| 小写+大写+数字+符号 | 94 | 78.6 位 | 104.8 位 |
现代密码破解工具在消费级硬件上:简单哈希约每秒1000亿次尝试。按此速度:
- 56位熵:约7个月破解
- 72位熵:约72,000年破解
- 128位熵:宇宙热寂
实用建议: 对于使用强算法存储的密码,至少128位熵;对于使用MD5/SHA1(攻击者利用泄露数据库进行破解)的情况,目标至少80位熵。

攻击者如何破解密码
了解攻击方式有助于防御。
字典攻击
攻击者尝试常见单词、姓名、常见替换(a→@, e→3, s→5),并附加常见后缀(123, 2024!, !):
password → P@ssw0rd → P@ssw0rd123 → P@ssw0rd2024!
RockYou、Have I Been Pwned 等词表包含数十亿常见密码及其变体。
掩码攻击(基于模式)
如果攻击者知道密码策略(必须包含大写字母、数字、符号),他们会缩小搜索范围:
掩码: ?u?l?l?l?l?l?d?s → 1个大写 + 5个小写 + 1个数字 + 1个符号
这就是为什么 "Password1!" 很弱——它符合最常见的合规模式。
彩虹表
常见密码的预计算哈希表。通过密码加盐(所有好的密码哈希算法自动执行)来防御。

什么不起作用(常见误解)
替换(l33tspeak): 攻击者在其字典中包含常见替换。P@ssw0rd 出现在每个词表中。
在末尾添加数字/符号: 攻击者知道用户会这样做。correct1! 并不比 correct1 强多少。
键盘模式: qwerty、asdfgh、123qwe 都出现在每个词表中。
个人信息: 生日、宠物名、地址——这些是定向攻击中首先被针对的。
什么真正有效
随机字符
一个完全随机的16位密码,使用完整字符集,具有约105位熵,基本上不可破解:
Kp7!mNqX3#rL9sYv
问题:无法记忆。
Diceware 密码短语
一串随机常见单词既高熵又易记:
correct horse battery staple
从7776个单词的词表中选5个单词:log₂(7776^5) = 64.6位。无法通过暴力破解。
6个单词:77.5位。8个单词:103.4位。
在同等熵值下,单词比随机字符更易记。

密码管理器
实用解决方案:为每个服务生成一个唯一、完全随机的20+字符密码,全部存储在密码管理器中。只需记住一个强主密码。
在代码中生成密码
// 浏览器 / Node.js — 加密安全
function generatePassword(length = 20, options = {}) {
const {
uppercase = true,
lowercase = true,
digits = true,
symbols = true,
} = options;
let charset = '';
if (lowercase) charset += 'abcdefghijklmnopqrstuvwxyz';
if (uppercase) charset += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (digits) charset += '0123456789';
if (symbols) charset += '!@#$%^&*()-_=+[]{}|;:,.<>?';
if (!charset) throw new Error('At least one character type required');
const array = new Uint32Array(length);
crypto.getRandomValues(array);
return Array.from(array)
.map(n => charset[n % charset.length])
.join('');
}
// 使用
const password = generatePassword(24, { symbols: true });
// => "Kp7!mNqX3#rL9sYv2@Hf8qR"
import secrets
import string
def generate_password(length=20, use_symbols=True):
chars = string.ascii_letters + string.digits
if use_symbols:
chars += '!@#$%^&*()-_=+[]{}|;:,.<>?'
# secrets.choice 使用 os.urandom — 加密安全
return ''.join(secrets.choice(chars) for _ in range(length))
# Diceware 风格密码短语
import random
WORDLIST = ['apple', 'bridge', 'cloud', ...] # 加载你的词表
def generate_passphrase(num_words=6):
return ' '.join(secrets.choice(WORDLIST) for _ in range(num_words))
不同使用场景的密码规则
| 使用场景 | 最低要求 | 推荐 | 备注 |
|---|---|---|---|
| 网络账户(bcrypt) | 12字符 | 20+字符 | bcrypt 处理工作因子 |
| 管理员/特权账户 | 16字符 | 30+字符 | 使用密码短语或密码管理器 |
| Wi-Fi 密码 | 12字符 | 20字符 | WPA2 无速率限制 |
| PIN(4位数字) | — | 使用6位数字 | 仅用于低风险、锁定设备 |
| 加密密钥密码短语 | 20字符 | Diceware 8个单词 | 保护加密卷 |
评估密码强度
一个基于熵的简单评估器:
function estimateEntropy(password) {
let charset = 0;
if (/[a-z]/.test(password)) charset += 26;
if (/[A-Z]/.test(password)) charset += 26;
if (/[0-9]/.test(password)) charset += 10;
if (/[^a-zA-Z0-9]/.test(password)) charset += 32;
const entropy = password.length * Math.log2(charset || 1);
if (entropy < 40) return { score: 0, label: '非常弱' };
if (entropy < 56) return { score: 1, label: '弱' };
if (entropy < 72) return { score: 2, label: '一般' };
if (entropy < 88) return { score: 3, label: '强' };
return { score: 4, label: '非常强' };
}
如需更复杂的分析(模式检测、字典检查),请使用 zxcvbn 库,它模拟了真实的攻击模式。
→ 使用 密码强度分析器 测试和分析你的密码强度。