🛡️ 第一章 信息安全的基本概念
📄 一句话概括

打口令只有三种打法——蛮力攻击、字典攻击、密码列表攻击;三者的成本差着好几个量级,所以"不复用"比"设得复杂"更重要,"够长"比"够怪"更值钱。

📝 本节和前面几节的关系

上一节(权限只交给合适的人)把认证和授权分开了。这一节专门钻进"认证"里最常被打的那一环——口令。

这也是本篇第一次出现可以真算的数字(破解时间)。之所以要算,是因为口令这件事上直觉特别不可靠:大多数人以为"P@ssw0rd! 比 applebananaorange 强",一算就知道反了。

一、先分清两件事:偷和猜

打口令的攻击分两大类,混在一起谈是很多讨论失焦的原因:

第一类:偷。 攻击者通过钓鱼、撞库、恶意软件、买数据等方式直接拿到口令明文。这类攻击跟你的口令有多强毫无关系——它是"P@ssw0rd!"还是 30 位随机串都一样。

第二类:猜。 攻击者拿到的是口令的哈希值(从数据库泄露里拿到),或者只有一个登录界面,需要想办法算出/试出那个口令。只有这一类,"口令强度"才起作用。

所以本节讲的三种攻击都属于第二类。而第一类的防御在别的地方——不复用、开多因子、防钓鱼。

二、蛮力攻击:最笨也最诚实

蛮力攻击的做法是:把所有可能的组合一个一个试过来。

它的成本公式很朴素:

要试的次数 = 字符集大小 ^ 口令长度
所需时间 = 要试的次数 ÷ 每秒能试多少次

这道公式里藏着两个关键变量:

这就是当前主流指南(NIST SP 800-63B)态度转变的原因:长度比复杂度更值得要求。

三、字典攻击:不猜字母,猜"人会怎么想"

字典攻击不试随机组合,而是拿词表去试:常见词、人名、品牌名、影视名、地名,再加上变形规则(首字母大写、末尾加数字、字符替换如 o→0、a→@)。

它的杀伤力在于:人的口令几乎都来自有限的那批词加有限的那几种变形。

所以 P@ssw0rd! 这种口令在"数学上"看着不弱(有大小写、有符号、有数字),在字典攻击面前几乎等于裸奔——因为 password 是词表里的第一个词,@ 和 0 是变形规则里最常用的两条。

一句话:蛮力攻击考验长度,字典攻击考验"你的口令是不是能被人想到"。

四、密码列表攻击:连算都不用算

第三种最常见、也最快:拿一份泄露口令清单直接试。

它的原理是"复用":A 网站泄露了一亿条"账号+口令",攻击者就拿这批口令去 B 网站、C 网站挨个试——因为在 B、C 网站里,总有相当比例的人用的是同一个口令。

这就叫撞库。它的特点是:

所以本节最该记住的一句话是:

在"泄露口令清单"面前,口令的复杂度毫无意义——你唯一能做的是别让它出现在那份清单里(也就是不复用),以及开多因子。

五、在线和离线,是两个世界

同样的口令,在两种场景下的破解难度差着天文数字:

场景 攻击者的速度 防守方的武器
在线(对着登录框试) 受限于网络和限速,每秒几次 失败锁定、限速、验证码、风险识别
离线(拿到哈希在自己机器上算) 一块现代显卡每秒可试上百亿次 只靠口令本身的强度

这个区别非常重要,因为它决定了防守的着力点:

所以正确的做法是两边都做:限速与锁定(挡在线)、长度与多因子(挡离线)。

六、动手 Demo:三类攻击的破解时间估算

下面这个 Demo 用同一批口令把三种打法跑一遍,看它们的差距有多大。

GPU = 1e10          # 离线:一块现代显卡每秒可试 100 亿次快速哈希
ONLINE = 5 / 60.0   # 在线:限速 5 次/分钟,且通常几次就锁号

def brute(sec, size, n):
    return (size ** n) / sec        # 字符集^长度 ÷ 每秒尝试次数

实跑输出:

============================================================================================
一、同一个口令,三种打法
============================================================================================
  口令                            长度  蛮力(离线)    字典+变形     泄露列表
  ----------------------------------------------------------------------------------------
  123456                          6     瞬间          瞬间          ★ 命中
  password                        8     21 秒         瞬间          ★ 命中
  P@ssw0rd!                       9     2 年          瞬间          ★ 命中
  company2026                     11    152 天        10 秒         —
  zhang1985                       9     2.8 小时      10 秒         —
  Tr0ub4dor&3                     11    1.8 万年      10 秒         —
  applebananaorange               17    359.5 万年    —(不在表里) —
  correct-horse-battery-staple    28    4e+22 年(天文数字)—(不在表里) —

============================================================================================
二、再看在线攻击(隔着一道限速的门)
============================================================================================
  口令                            在线(5次/分钟)    说明
  ----------------------------------------------------------------------------------------
  123456                          2.0 分钟          列表前几位就是它,试十几次就中
  password                        2.0 分钟          列表前几位就是它,试十几次就中
  P@ssw0rd!                       2.0 分钟          列表前几位就是它,试十几次就中
  company2026                     14 天             限速之后在线猜变慢了,但远没到安全
  zhang1985                       14 天             限速之后在线猜变慢了,但远没到安全
  Tr0ub4dor&3                     14 天             限速之后在线猜变慢了,但远没到安全
  applebananaorange               4e+17 年(天文数字)在线打它没意义
  correct-horse-battery-staple    5e+33 年(天文数字)在线打它没意义

  ④ 读这张表要读出两件事:
     第一,凡是在【泄露密码列表】里的口令,破解时间都是瞬间——
     攻击者根本不用算,直接查表。所以【不复用】比【设得复杂】重要得多。
     第二,最后两条长口令,离线硬算要几万年以上,
     可它们连大小写都没混——长度赢过了复杂度。

  ⑤ 这就是当前主流指南(NIST SP 800-63B):
     单靠口令登录的场景,最短 15 个字符;不强制大小写和符号混排;
     系统要拿泄露口令库筛一遍,命中就拒收;
     并且不再要求定期换口令——定期换只会把人逼成 2026春季 变 2026夏季。

读这个输出:最有信息量的两行是 P@ssw0rd! 和 applebananaorange 的对比。

这就是本节最想让人亲眼看到的一件事:"看着复杂"和"实际难破"是两回事;真正起作用的是长度和不可预测性。

再看第二张表的 123456:蛮力只要瞬间,但因为限速,在线攻击要 2 分钟——还是一次就试中的。而 company2026 在线要 14 天。同一个登录框,限速一开,攻击成本从"秒"抬到了"两周"——这就是"在线"和"离线"的分水岭。

七、⚠️ 2026 现状

30 秒实验

把你现在正在用的两个网站的口令,在心里做一个判断(不用真的写出来):

  1. 这两个口令是不是同一个,或者只是换了几个字符?
  2. 它们是不是由一个常见词加变形拼出来的?
  3. 如果明天第一个网站泄露了,第二个网站还守得住吗?

只要 3 答"守不住",那就是最该处理的一种情况——它属于"密码列表攻击"的目标,跟你口令有多复杂无关。处理办法只有两个:换成不重复的口令(交给口令管理工具生成),或者开多因子。

常见误区

  1. 错误:口令里混了大小写和符号就更安全。——纠正:复杂度带来的提升远小于长度,而且人满足复杂度规则的方式高度可预测(首字母大写、末尾加 1!)。字典攻击就是专门打这个习惯的。Demo 里 P@ssw0rd! 和 applebananaorange 的对比就是最好的说明。

  2. 错误:定期换口令更安全。——纠正:当前主流指南明确不要求定期更换。定期换会把人逼向"可预测的变化"(年份、月份、数字加一),反而更容易被猜中;同时带来大量现实成本的投入。正确的做法是在有泄露证据时强制更换。

  3. 错误:我的口令很复杂,所以不怕泄露。——纠正:如果它在别的站点用过,就"已经"在攻击者的清单里了。这时复杂度不起作用。不复用是唯一有效的对策。

  4. 错误:把口令设得很长但很好猜(比如一整句话的拼音)就安全。——纠正:长度确实有效,但"可预测"会让长度打折——流行的句子、歌词、名言都在词表里。随机的多个不相关词才是又长又难猜的做法(Demo 里的 correct-horse-battery-staple 就是这种思路)。

自测三问(点开对答案) 1. 为什么说"密码列表攻击"跟前两种攻击不是一回事? —— 因为前两种是**"猜"**(要计算或尝试),而密码列表攻击是**"试"**——攻击者直接用从别处泄露的真实口令去撞库,**不需要任何计算,命中率却很高**。它打的不是口令强度,是**复用习惯**。 2. 同样一个 8 位口令,为什么"在线"要几个月、"离线"只要几十秒? —— 因为**两者的速度差着好几个量级**:在线受网络和限速约束(每秒几次),离线是在自己机器上算(每秒上百亿次)。所以防守要**两边都做**:限速与锁定挡在线,长度与多因子挡离线。 3. 为什么 NIST 建议"允许粘贴口令、支持口令管理工具"? —— 因为**禁止粘贴会把人推向短口令**(手打不方便,就写短一点)。允许工具生成和自动填充,人才可能真的用上"每个站点一个的、长的、随机的"口令。**这又是一次"便利性和安全性同向"的例子**——顺人性的规定才落地得下去。

相关笔记