📚 第九章 网络安全
📄 一句话概括

对称密码快,但钥匙送不出去;公钥密码能送钥匙,但慢得离谱。 所以它们从来不是二选一——HTTPS 用的是两者接力。

📝 本节和前面几节的关系

前面三节讲的都是「怎么发现坏人」。这一节开始讲「怎么让坏人看见了也没用」。 Demo 算两张表:口令长度对应的爆破时间,和「RSA 一次只能加密多少字节」。

一、对称密码:一把钥匙开两把锁

对称的意思是加密和解密用同一把钥匙。 它的代表是 AES,工作方式是把数据切成固定长度的块,一块一块地变换。 它的优点是快:今天的 CPU 有专门的指令,AES 能跑到每秒几个 GB。 它的问题只有一个,但很致命:钥匙怎么送过去。 你要给对面一把钥匙,就得先有一条安全的通道,而这条通道本身又需要钥匙——这是一个死循环。 历史上所有对称密码的失败,几乎都失败在「钥匙管理」上,而不是算法被破解。 还有一个坑叫「工作模式」:同样的 AES,配不同的模式,安全性天差地别。 ECB 模式是把每个块独立加密, 于是同样的明文块会得到同样的密文块——一张纯色背景的图片加密之后,轮廓还看得见。 CBC 让每块先和前一块异或,GCM 还顺带给了完整性校验。 所以「用了 AES」这句话不完整,必须说「用了哪个模式」。

二、公钥密码:两把钥匙,一人一套

公钥密码把钥匙拆成一对:公钥公开,谁都能拿去加密;私钥自己留着,只有它能解开。 于是「送钥匙」这个死循环被解开了——公钥本来就不怕被人看见。 它的安全性建立在一个数学难题上:RSA 靠「大数分解」, 给你两个大素数相乘的结果,你很难反推出那两个素数。 椭圆曲线靠「离散对数」,同样的强度下密钥短得多,所以手机和物联网上更常用。 代价有两个,都很硬: 一是慢,同样强度的运算,公钥密码比对称密码慢三个数量级; 二是一次只能加密一小块,RSA-2048 一次最多 245 字节, 因为它的数学结构只对「比模数小的数」成立。 所以「用 RSA 加密一个文件」这个想法,从原理上就走不通——不是慢,是装不下。

三、混合加密:两者的接力

真实的做法是把两件事分开: 公钥只用来送一把临时的对称密钥,数据本身全部用对称密钥加密。 这个流程只有三步:客户端生成一把随机的对称密钥,用服务器的公钥把它加密后发过去, 之后双方就用那把对称密钥说话。 这就是 HTTPS 的全部秘密,也是 SSH、IPsec、VPN 的共同骨架。 所以「公钥密码比对称密码高级」这个印象是错的: 它们分工不同——公钥负责「把钥匙安全地送到对面」,对称密钥负责「把数据快速地搬过去」。 一个管信任,一个管吞吐。 最后记住这张表里的一个反直觉数字:RSA-2048 只相当于 112 位强度,而不是 2048 位。 因为公钥密码的密钥里有一大半是结构信息,它们不提供任何安全性,只是让运算能成立。 所以「位数」和「强度」不是一比一,跨算法比较位数是没有意义的。

四、动手 Demo:口令长度和密钥长度,到底差在哪儿

假设字符集 95 个、离线爆破每秒十亿次,算长度 6 到 12 位的破解时间; 再算 RSA-2048 加密 1 MB 要多少次。

rate = 1e9                      # 每秒尝试次数

for n in (6, 8, 10, 12):
    space = 95 ** n
    print(n, "%.3e" % space, round(space / rate / 86400 / 365, 1), "年")

blocks = (1 << 20) // 245 + 1   # RSA-2048 一次最多 245 字节
print(blocks, "次", blocks * 0.001, "秒")

实跑输出:

--------------------------------------------------------------------
口令长度和密钥长度,到底差在哪儿
--------------------------------------------------------------------
**「密码要长一点」这句话背后是一张指数表。**
**假设字符集有 95 个可选字符、离线爆破每秒十亿次,把长度从 6 加到 12 会发生什么。**

  口令长度      组合数        爆破耗时
  ------------------------------------------
  **6 位**      7.351e+11     **735 秒**
  **8 位**      6.634e+15     **76.8 天**
  **10 位**     5.987e+19     **1899 年**
  **12 位**     5.404e+23     **1713 万年**

**每多一位,时间乘 95。**
**从 6 位到 12 位是六次乘 95,大约是 7350 亿倍**——**这就是「长度比复杂度更重要」的全部数学。**
**换成一个符号(把字符集从 26 扩到 95)只是乘三倍多,而多一位就乘 95。**

**对称和公钥的密钥长度不能用同一把尺子量**:

  算法             密钥长度        等效强度          为什么
  ------------------------------------------------------------------------------
  **AES-128**      **128 位**      **128 位**        **对称,加解密同一把钥匙**
  **AES-256**      **256 位**      **256 位**        **对称,钥匙更长**
  **RSA-2048**     **2048 位**     **约 112 位**     **公钥,靠大数分解难**
  **RSA-3072**     **3072 位**     **约 128 位**     **等效 AES-128**

**第三列是这行表的意义**:**RSA 的 2048 位并不等于「比 AES-256 强八倍」,它只相当于 112 位。**
**公钥密码的密钥里有一半是结构信息,不提供安全性**,所以「位数」和「强度」不是一比一。

**公钥密码还有一个硬限制:一次只能加密一小块。**
**RSA-2048 的模数是 256 字节,去掉 11 字节填充,一次最多 245 字节。**

  项目                      结果
  ---------------------------------------
  一次能加密                **245 字节**
  1 MB 要加密几次           **4280 次**
  用时(按每次 1 毫秒)     **4.3 秒**

**所以现实中从来不用公钥加密数据本身**,
**而是「用公钥加密一把临时的对称密钥,再用它加密数据」**——**这叫混合加密,HTTPS 就是这么干的。**
**公钥负责「把钥匙安全地送到对面」,对称密钥负责「把数据快速地搬过去」。**
**两者各干自己擅长的事,这是全书最漂亮的一处分工。**

第一张表的斜率是这一节的重点:每多一位,时间乘 95。 从 6 位到 12 位是六次乘 95,大约七千多亿倍。 而把字符集从 26 个字母扩到 95 个可打印字符,只是乘三倍多。 所以「加长」比「加符号」划算得多——这就是为什么现在的建议是「长度优先」。 第二张表解释了一件常被误解的事: RSA-2048 的 2048 位,并不等于「比 AES-256 强八倍」,它只相当于 112 位。 跨算法比位数是没有意义的,要比就比「等效强度」。 最后那张小表是混合加密的存在理由:1 MB 就要加密四千多次、四秒多, 而 AES 干同样的事是毫秒级。 所以数据永远交给对称密码,公钥只负责送钥匙——这个分工不是设计者的偏好,是被数学逼出来的。

30 秒实验

  1. 算一下:12 位口令、每秒十亿次,要多少年?(约一千七百万年,量级已经超过宇宙年龄的百分之一)
  2. 想一下:为什么不能「用 RSA 直接加密一个文件」?
  3. 想一下:公钥密码安全的基础是什么数学难题?

常见误区

  1. 以为「公钥密码比对称密码高级」。 两者分工不同,一个管信任,一个管吞吐。
  2. 以为「用了 AES 就安全」。 还要看工作模式,ECB 会把明文图案泄露出去。
  3. 以为「密钥越长越安全,所以直接比位数」。 跨算法比位数没意义,RSA-2048 只相当于 112 位。
自测三问(点开对答案) 1. 对称密码的根本难题是什么? —— **钥匙怎么安全地送过去**,所有历史事故几乎都出在这儿。 2. 为什么 RSA 一次只能加密 245 字节? —— **它的数学只对「比模数小的数」成立**,2048 位模数减去填充就是 245 字节。 3. 混合加密的三步是什么? —— **生成对称密钥、用公钥送过去、之后全程用对称密钥**。

下一节换一个问题:加密解决了「看不见」,但「你是谁」还没解决。

相关笔记