密码安全完全指南:如何生成与管理真正可靠的强密码
你的密码,可能比你想的更脆弱
几乎每个月都有大网站泄露用户数据的消息。泄露之后,最危险的不是「我的密码被看到了」,而是大多数人一套密码走天下——A 站泄露的账号密码,攻击者拿去撞 B 站、C 站,十有八九能直接登进去。
还有一类人走另一个极端:把 P@ssw0rd1! 当成「够复杂了」。这其实是自欺欺人。我们在做工具库的密码工具这几年反复强调一件事:密码的强度不是你「觉得」多复杂,而是它实际有多难被算出来。
根据 Have I Been Pwned 等泄露库统计,常年出现在撞库字典里的弱密码就那么几百个变体。password、123456、qwerty、P@ssw0rd 这些,占了真实泄露量的惊人比例。你以为的「创意」,在攻击者眼里早就是公开剧本。
攻击者是怎么破你密码的
- 撞库(Credential Stuffing):从别处买来/拖库的账号密码,自动批量去各网站试登录。这是「一套密码通用」最致命的原因——你一个账户泄露,所有账户跟着裸奔。
- 暴力破解 / 字典攻击:短密码、常见单词组合,在普通显卡上几秒到几分钟就能穷举完。一张消费级显卡每秒能试几十亿次哈希。
- 社会工程与个人信息:生日、名字、宠物、车牌。攻击者只要稍微了解你(或你的社交账号),就能把这些塞进字典优先试。
- 彩虹表(Rainbow Table):提前算好「常见密码 → 哈希」的对照表,拿到泄露的哈希库直接反查。加盐(salt)能废掉它。
注意这几类的共同前提:你的密码要么太常见,要么太短,要么和你的信息有关。只要避开这三点,破解成本就会高到没人愿意碰你。
什么才是真正的「强」
三个标准,按重要性排序:
- 够长:12–16 个字符起步。长度对破解成本的提升是指数级的,比任何「加个符号」都管用。一个 12 位随机密码,比 8 位复杂密码难破几个数量级。
- 真随机:字符来自密码学随机数生成器,不是你脑子里编的。人编的密码有明显的模式(比如首字母大写、结尾加数字、用常见单词),熵很低。
- 唯一:每个站点不同。这一条单独就能挡住撞库。
不同密码被破解的时间量级(基于离线暴力,仅作直觉参考;实际取决于攻击者算力):
| 密码 | 大约破解成本 |
|---|---|
password123 |
瞬间 |
P@ssw0rd1! |
字典攻击下几秒 |
| 8 位随机字母数字 | 数小时到数天 |
| 12 位随机字母数字符号 | 数千年以上 |
| 4 个随机词组成的口令短语 | 也上千年 |
熵:给「强度」一个可量化的标准
密码学里用「熵(entropy,单位 bit)」衡量随机性。粗略公式:熵 ≈ 字符集大小的对数 × 长度。
- 小写字母(26 种):每个字符约贡献 log₂26 ≈ 4.7 bit
- 加数字(36 种):约 5.17 bit
- 大小写+数字+符号(约 95 种):约 6.57 bit
所以:
| 密码 | 估算熵 |
|---|---|
| 8 位复杂字符 | ~52 bit |
| 12 位复杂字符 | ~79 bit |
| 4 个随机常用词(每词~11bit) | ~44–55 bit |
| 5 个随机常用词 | ~55–65 bit |
经验阈值:熵 ≥ 60 bit 算「强」,≥ 80 bit 算「很强」。这就是为什么口令短语只要词够多、真随机,就能和乱码一样扛揍。
怎么生成:交给工具,别靠脑子
自己想密码,再「随机」也带着习惯。让工具用密码学随机数生成才靠谱:
- 随机密码 / Token 生成器:可配置长度和字符集(大小写、数字、符号),底层用
crypto随机,不是伪随机。 - 生成完顺手用密码强度分析扫一眼,确认没有被常见规则误判为弱。
长度建议直接拉到 16 位以上。多一位,破解成本翻几十倍。下面是正确和错误的生成方式对比:
// ❌ 错误:Math.random 是伪随机,可被预测,别用于密码
const weak = Math.random().toString(36).slice(2, 10);
// ✅ 正确:用 Web Crypto 的密码学随机数
function genPassword(len = 16) {
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789';
const arr = new Uint32Array(len);
crypto.getRandomValues(arr);
return Array.from(arr, n => chars[n % chars.length]).join('');
}
口令短语:又好记,又扛揍
如果嫌乱码难记,试试口令短语(Passphrase)——Diceware 思路:挑 4–5 个互不相关的随机词,用分隔符连起来,比如 correct-horse-battery-staple(经典示例)。
它比同等长度的乱码更好记,熵却一点不低:每个常用词约贡献 10–13 bit 熵,5 个词就是 50–65 bit,远超大多数随机短密码。对手写脑记型用户,这是最实用的方案。
别用名言、歌词、或者「把一句话首字连起来」——那依然是可预测的模式。词必须真的是随机选的(用工具的随机词功能,别自己挑)。
进阶:在词之间加随机数字和符号,比如 correct-7-horse-battery-3-staple,熵再上一个台阶,也不难记。
管理:管理器 + 唯一 + 双因素
生成强密码只是第一步,记不住就白搭。
- 用密码管理器(Bitwarden、1Password、KeePass 等):每个站点存一个唯一强密码,你只守住一个主密码。主密码建议用上面的口令短语思路。好的管理器是零知识架构——你的库在本地加密,服务商也看不到明文。
- 开双因素(2FA):就算密码泄露,多一道动态码也登不进。TOTP 工具可以生成步步验证码,比短信可靠。
- 重要账户别只靠短信验证:SIM 互换攻击能劫持短信,能上 TOTP 或硬件密钥(如通行密钥/Passkey)的优先上。
双因素方式的可靠度排序:
| 方式 | 安全度 | 备注 |
|---|---|---|
| 硬件密钥 / Passkey(WebAuthn) | 最高 | 防钓鱼,无密可偷 |
| TOTP 验证器 App | 高 | 不依赖短信,推荐 |
| 短信 SMS | 低 | 可被 SIM 互换劫持 |
| 邮箱验证码 | 中低 | 邮箱若泄露则连带失效 |
开发者视角:秘密怎么存
如果你是写后端的,一条铁律:永远不要明文存密码。
哈希,而不是加密
密码应该只存哈希——用 bcrypt / Argon2 / PBKDF2,并且加盐。注意:「哈希」和「加密」不同:加密可逆,哈希不可逆。你不需要(也不应该)能还原用户密码。
工具库提供了哈希工具(MD5/SHA 等摘要)和bcrypt 工具(专门做密码哈希)。重要:MD5/SHA 是通用摘要算法,算得太快,不适合直接存密码——它们挡不住暴力破解。正式存储请用 bcrypt / Argon2 / scrypt 这类「慢哈希」。
// Node.js:用 bcrypt 存密码(正确姿势)
import bcrypt from 'bcrypt';
const saltRounds = 12; // 越大越慢越安全,12 是常见值
const hash = await bcrypt.hash(password, saltRounds);
// 存 hash 进数据库,别存 password
// 登录时校验
const ok = await bcrypt.compare(inputPassword, hashFromDb);
// Node.js:用 Argon2(更现代,推荐新项目)
import argon2 from 'argon2';
const hash = await argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 65536, // 64 MB
timeCost: 3,
parallelism: 1,
});
盐(salt)、胡椒(pepper)与防爆破
- 盐:每个用户随机一串,混进哈希,存进数据库。作用是让相同密码产生不同哈希,废掉彩虹表和撞库。bcrypt/Argon2 会自动加盐,直接用即可。
- 胡椒(pepper):全局一个密钥,不进数据库(放环境变量/密钥管理),在哈希前先拼到密码上。即使数据库泄露,没有 pepper 也难破解。
- 限速与锁死:登录接口必须限流、失败次数锁定、加验证码,挡住在线暴力。
- 时序攻击:用「恒定时间比较」校验哈希(bcrypt.compare 内部已做),别用
==直接比。
需要可逆时再用加密
比如要回推的密钥、用户授权的第三方 token,用AES-256-GCM 工具,口令经 PBKDF2 派生密钥,全程本地。但「用户登录密码」永远不该可逆——那是设计错误。
永远别把用户密码写进日志、别存明文数据库、别在前端做「密码强度」之外的任何处理。前端强度提示只是 UX,真正的安全在后端哈希。
合规参考:NIST 的新思路
美国 NIST 800-63B 早就推翻了「每 30 天强制换密码」「必须包含大小写+数字+符号」的老套路。新建议:
- 长度优先(至少 8,建议更长),而非强制复杂组合;
- 不要强制定期更换(没泄露就别换,强制定期换反而催生弱密码);
- 检查密码是否在已知泄露库中(用 k-anonymity 接口查前缀,不泄露完整密码);
- 允许粘贴密码(方便用管理器);
- 限制最大长度即可,别限制特殊字符。
密码强度分析工具的实现思路就参考了这些原则——不只看「有没有符号」,更看长度和是否落入常见模式。
常见错误
| 错误 | 后果 | 正确做法 |
|---|---|---|
| 一套密码通用 | 一处泄露全崩 | 每站唯一 |
P@ssw0rd 式替换 |
字典秒破 | 真随机 / 口令短语 |
| 写在手机备忘录 | 手机丢就完 | 密码管理器 |
| 只开短信 2FA | SIM 互换可劫持 | TOTP / 硬件密钥 |
| 用短 PIN 当密码 | 暴力秒破 | 12–16+ 字符 |
| 后端明文存密码 | 一泄露全曝光 | bcrypt / Argon2 哈希 |
| 用 MD5/SHA 直接存密码 | 快哈希挡不住爆破 | 用慢哈希算法 |
常见问题
密码要定期换吗? 没有泄露迹象就不用(遵循 NIST 新指南)。强制每 30 天换一次,反而让人写下弱密码或只改末尾数字。等出现泄露再换。
口令短语和乱码密码哪个好? 都行,关键是长度和随机性。口令短语胜在好记,适合主密码和手写记录;随机乱码适合管理器自动填的站点密码。
发现某站泄露了怎么办? 立刻改掉那个站(以及所有复用同一密码的站)的密码 → 开 2FA → 去 Have I Been Pwned 查自己哪些邮箱中招。
密码管理器的主密码忘了会怎样? 主密码通常无找回机制(这是它安全的代价)。所以主密码一定要用你真正记得住、又够长的口令短语,并留一份离线备份(手写锁进抽屉)。
开发者:用哪个哈希算法? 新项目优先 Argon2id;要兼容老系统用 bcrypt(cost≥12)。避免直接用 MD5/SHA 系列存密码。
账号安全自检清单
1. 有没有重复使用的密码? → 用 /encode/password 生成唯一强密码逐个替换
2. 长度够吗(≥12,建议 16+)? 不够就加长
3. 开了双因素吗? → 优先 TOTP(/utils/totp)或 Passkey,别只靠短信
4. 开发者:密码是哈希存储吗? → /encode/bcrypt,别明文,别用 MD5/SHA
5. 主密码好记又够强吗? → 用口令短语思路,留离线备份
6. 有没有在泄露库里? → 定期查 Have I Been Pwned
把这六条过一遍,你的账号安全等级会比绝大多数人高出一个身位。密码这件事,早一天认真,少一天提心吊胆。相关的图片/文件隐私处理,可以参考数据隐私指南。
本站提供浏览器本地工具,免注册即可试用 →