🛡️ 第五章 什么是密码、数字签名、数字证书
📄 一句话概括

公开密钥加密用一个不对称的设计把死结解开了:锁(公钥)可以随便公开,钥匙(私钥)只有自己拿着——于是"怎么把密钥安全地送过去"这个问题本身消失了,不需要再送任何秘密。

📝 本节和前面几节的关系

5-2 把对称加密的两个麻烦摆在了桌上:密钥怎么送、人多时密钥太多。这一节就是来解第一个麻烦的,而且是用一种"根本不需要送密钥"的方式解的。

注意它解的是"送钥匙",不是"全都用它":公开密钥加密慢得多,所以真实系统里的做法是"用它来送对称密钥,然后数据全走对称加密"——那正是 5-7 的内容。

一、先把死结看清楚:密钥分发问题

对称加密要求双方事先拥有同一把密钥。于是:

参与人数 需要的密钥把数 现实里的麻烦
2 人 1 把 各持一把就够
10 人 45 把 每人还要和其余 9 人各持一把
100 人 4950 把 已经不可能靠人工维护
1000 人 499500 把 近 50 万把,还随时要换
100000 人 4999950000 把 5 亿把级别,纯属灾难

这还不算最糟的。最糟的是"这些密钥本身怎么送":你要把一把密钥安全地交给对方,就必须先有一条安全的通道——可这条通道要么不存在,要么本身又需要密钥。这就是密钥分发问题(key distribution problem),密码学上最经典的一个鸡生蛋。

二、换一个思路:把钥匙分成两把,其中一把完全公开

公开密钥加密(非对称加密)的做法是:

关键在于这两把钥匙做的事不一样:

第二个用途今天和第一个一样重要:它让"证明这条消息来自谁、有没有被改过"第一次变成一件数学上可验证的事。这就是 5-6 的整节内容。

再回头看人数问题:100 万人也只需要 100 万个公钥,而且这些公钥本来就该到处公开,不需要任何安全通道。"分发"这个动作彻底消失了。

三、动手 Demo:RSA 的最小可运行例子

下面用一个"小到能心算"的 RSA 走完整流程(教科书级,只为看清结构,实际用的 n 是 2048 位):

p, q = 61, 53
n = p * q                    # 公开
phi = (p - 1) * (q - 1)      # 保密
e = 17                       # 公钥 = (e, n)
d = pow(e, -1, phi)          # 私钥 = (d, n),只有知道 p、q 才算得出

m = 65
c = pow(m, e, n)             # 公钥加密
print(pow(c, d, n))          # 私钥解密 → 65
print(pow(m, d, n))          # 私钥"签名"
print(pow(pow(m, d, n), e, n))   # 公钥验证 → 65

实跑输出:

一、共享密钥加密的死结(密钥分发问题)
  参与人数    需要的密钥把数      现实里的麻烦
  2 人        1 把                各持一把就够
  10 人       45 把               每人还要和其余 9 人各持一把
  100 人      4950 把             已经不可能靠人工维护
  1000 人     499500 把           近 50 万把,还随时要换
  100000 人   4999950000 把       5 亿把级别,纯属灾难
  → 人数翻一倍,密钥数翻约四倍。而且这些密钥本身还得靠
     一个【双方都信任的通道】去送——鸡生蛋的问题。

二、公开密钥加密:每人一对钥匙,问题直接消失
  公钥 = 随便公开(像信箱投递口,谁都能把信塞进去)
  私钥 = 只有自己有(像信箱钥匙,只有本人能打开)
  参与人数    需要的公钥数        要走保密通道吗
  1000 人     1000 个             不用(对比上一张表:同样 1000 人要 49.9 万把)
  1000000 人  1000000 个          不用,全部公钥都可以直接公开

三、RSA 的最小可运行例子(教科书级,只为看清流程)
  取两个质数 p=61、q=53
  算出 n = p*q = 3233        (公开)
  算出 φ(n) = (p-1)(q-1) = 3120   (保密)
  挑一个与 φ(n) 互质的 e = 17          → 公钥 = (e, n) = (17, 3233)
  求 e 的模反元素 d = 2753            → 私钥 = (d, n) = (2753, 3233)
  → d 只有知道 p、q 的人才算得出来;
     而从 n 反推出 p、q,就是难住全世界的那件事:大数分解。

  用两个方向实际跑一遍:
  要发的内容 m      65
  公钥加密          c = m^e mod n = 65^17 mod 3233 = 2790
  私钥解密          m = c^d mod n = 2790^2753 mod 3233 = 65
  结果              65 == 65 → 还原成功

四、同一对钥匙,把使用方向反过来就是【签名】
  私钥签名          s = m^d mod n = 65^2753 mod 3233 = 588
  公钥验证          m = s^e mod n = 588^17 mod 3233 = 65
  → 加密与签名是同一个运算,区别只在【谁拿哪把钥匙】:
     公钥加密 / 私钥解密 = 保密(保证只有收件人能看)
     私钥签名 / 公钥验证 = 认证(保证只有私钥持有者发得出)

五、真实世界里的 n 不是 4 位数,是 2048 位
  2048 位二进制 ≈ 617 位十进制。用目前最好的分解算法,
  运算量在 10^34 次这个量级——这才是 RSA 靠得住的地方。
  代价是慢:RSA 的速度大约是同级对称密码的千分之一,
  这正是后面要讲【混合加密】的原因。

读这个输出:

四、代价:慢,而且慢得没法忽视

公开密钥加密的代价很实在:它比对称加密慢三个数量级左右(Demo 第五段已经埋了这句)。原因在于它做的是大数模幂运算,而不是简单的位运算。

这个速度差直接决定了真实系统的架构:没有人会用 RSA 去加密一个几 GB 的文件。真实做法是用公开密钥加密送一把临时对称密钥,然后数据全部走对称加密——这就是混合加密,5-7 整节都在讲它。

五、⚠️ 2026 现状

30 秒实验

今天做两个动作,各 15 秒:

  1. 在浏览器地址栏点一下挂锁图标,看那串证书信息:你会看到"颁发给"和"颁发者"两栏——那里面装着的就是一个公钥和一份签名。这个动作把本节抽象的三级证书链变成你屏幕上能点开看的东西。
  2. 打开一个你常用的网站,问自己一句:如果这台服务器的私钥今天被人偷走,会发生什么?——答案分两层:① 后果严重,因为对方可以伪装成这个网站(这正是中间人攻击的可行路径,5-14);② 但影响可以被压住,因为证书可以吊销、而且有效期越来越短(5-10 讲这件事)。

这一节要带走的一句是:公开密钥加密真正解决的,不是"怎么把钥匙送得更安全",而是"干脆不需要送任何秘密"——它把保密的那一半留在自己手里,把不需要保密的那一半公开出去。

常见误区

  1. 错误:公钥和私钥是一对"加密钥匙和解密钥匙",用哪把加密就用另一把解。——纠正:这个说法不准确,容易在关键时刻搞反。准确的描述是"两把钥匙都能加密、也能解密,但只有配对的那把才能反向操作"。工程上要分清的是"目的"而不是"方向":目的如果是保密,就用收件人的公钥加密(只有他解得开);目的如果是认证,就用自己的私钥签名(谁都能验、但只有我签得出来)。一个常见的严重错误是把这两个目的搞混:用"自己的公钥"加密以为只有自己能解——实际上任何人都能用你公开的私钥解不开,但都能用你的公钥加密,等于谁都能给你发信、但你自己也解不开(因为你自己拿的是私钥,而加密用的是公钥)。记住一句话:公钥是给别人用的,私钥是给自己用的。

  2. 错误:既然公钥可以随便公开,那我在网站上贴一个公钥就等于完成加密改造了。——纠正:贴公钥这个动作本身没有风险,但它解决不了"我怎么知道你贴的就是你的"这个问题。攻击者可以在你和网站之间把公钥换掉——你拿到的是一把攻击者的公钥,于是你用他的公钥加密、他用私钥解开,你全程毫无察觉。这正是"公开密钥加密"必须再叠一层"数字证书"的原因(5-4 整节都在讲这一层)。一句话:公钥加密解决了"怎么送密钥",但没有解决"怎么确认这把钥匙是谁的"——后者要靠第三方背书。

  3. 错误:RSA 是最经典的公开密钥算法,那就一直用 RSA 就好。——纠正:2026 年的默认选择已经不是 RSA 了。同等安全等级下,椭圆曲线(ECC)的密钥短 12 倍左右:128 位安全等级需要 RSA 3072 位,而 ECC 只要 256 位。更短意味着更少的握手数据、更快的运算、更小的存储开销。所以今天的实践是:新生成的 SSH 密钥用 Ed25519,TLS 里的签名优先用 ECDSA 或 Ed25519,RSA 主要留给"必须兼容老设备"的场景(5-12 会给完整的选型表)。唯一要注意的是 ECC 自己也有个实现层面的坑(ECDSA 的随机数重用会泄露私钥),而 Ed25519 从设计上避开了它。

  4. 错误:等量子计算机真造出来了再考虑换算法也来得及。——纠正:来不及时,因为攻击有一个"先存后解"的形态。攻击者可以现在就把加密流量录下来存着,等量子计算机可用时再解开(harvest now, decrypt later)——这意味着"长期需要保密的数据"今天就已经处在风险里了。所以迁移的时间表不是"等量子计算机出现",而是"按数据的保密年限倒推":需要保密 10 年以上的数据,现在就该规划后量子迁移;NIST 给出的禁用在 2035 年,而实际的落地压力比这个日期早得多(5-9 会给出从 2024 到 2035 的完整节点)。

自测三问(点开对答案) 1. 公开密钥加密到底解决了什么问题?它没有解决什么问题? —— **解决了"密钥分发"和"密钥数量爆炸"这两个问题**:**公钥可以公开发布、不需要安全通道,人数增长时密钥数量从平方级降到线性级**(1000 人从 49.9 万把降到 1000 个)。**它没有解决"怎么确认这把公钥属于谁"**——**因为公开的东西可以被替换**,攻击者可以把自己伪造的公钥塞给你。**这个缺口要靠第三方背书来补,也就是数字证书与 CA(5-4)**。**另外它也没有解决"速度"问题**——**它慢了三个数量级,所以真实系统必须与对称加密组合使用(5-7)**。 2. 为什么"加密"和"签名"能用同一对钥匙完成?这件事有什么实际好处? - **因为它们是同一个数学运算(模幂)的两个方向**:**公钥加密的数据只有私钥能还原,私钥"加密"的数据只有公钥能还原**——**前者用于保密,后者用于认证**。**实际好处是"一套数学基础能同时支撑三件不同的事"**:**保密**(HTTPS 里的密钥传输)、**认证**(数字签名、代码签名)、**身份绑定**(SSH 登录、客户端证书)。**这意味着工程上不需要为每个用途维护不同的密码体系**——**证书、签名、握手、登录密钥全部可以统一到同一套库、同一套硬件模块、同一套轮换流程上**。**代价也要记住:一旦这套数学基础本身被攻破(比如大数分解被量子计算机解决),上面这三件事会同时失效**——**这正是后量子迁移被当成一件系统性工程的原因。** 3. 为什么说 RSA-2048 今天还能用,但不是新系统的首选? —— **因为它对应的安全等级是 112 位,而不是 128 位**。**今天的推荐基线是 128 位安全等级,对应 RSA 3072 位或 ECC 256 位**。**RSA-2048 属于"仍然可接受、但已是过渡状态"**。**更值得注意的是选型逻辑**:**同样要达到 128 位安全,ECC 只需要 256 位密钥(RSA 要 3072 位)——差 12 倍**,**这直接决定了握手大小、运算耗时和硬件开销**。**再叠加后量子时间表**(**RSA/ECDSA 2030 年弃用、2035 年禁用**),**新系统的合理选择就很清楚了:能上 ECC 就上 ECC,需要长期保密或面向法规的场景尽早规划后量子算法。**

相关笔记