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

公钥加密解决了"怎么送钥匙",但没解决"怎么确认这把钥匙是它自称的那个人"——数字证书、证书颁发机构、PKI、根证书这几样东西,全都是为了补上这一个缺口。

📝 本节和前面几节的关系

5-3 把公钥公开出去了,但"公开"这件事本身留了一个洞:攻击者同样可以公开一把假公钥。

这一节就是来堵这个洞的,而且它用的手段你已经见过——还是签名,只是这次签的不是数据,而是"某把公钥属于某个人"这句话。它也是 冒充特定的人物 那类攻击在密码学层面的正面回应。

一、光有公钥不够:交换过程中的那个空档

假设 A 想把公钥发给 B。如果这个过程没有人干扰,一切正常。但如果有人站在中间:

  1. A 发出自己的公钥;
  2. 攻击者截下来,换成自己的公钥,再转发给 B;
  3. B 拿到的是攻击者的公钥,以为那是 A 的,于是用它加密消息;
  4. 攻击者用自己的私钥解开,读完之后再用 A 的真公钥加密转发给 A。

双方全程看不到任何异常——这就是"公钥替换",也是所有中间人攻击的理论原型(5-14 会展开)。

问题的根子在:公钥只是一个字符串,它自己没法证明"我属于某某"。要证明这一点,得有另一个公钥不算在内的人出来签字担保——于是出现了 CA。

二、数字证书:一张签过名的名片

数字证书(digital certificate)的本质非常朴素:

它是一份结构化的文本,里面写着【某主体的公钥 + 主体信息 + 有效期 + 用途】,然后由证书颁发机构(CA)用自己的私钥签了名。

它的作用:任何人拿到这张证书,先用 CA 的公钥验证签名——验过,就说明这份内容确实是 CA 认可的、中途没被改过。因为 CA 的私钥只有 CA 有,别人伪造不了这张名片。

几个名词就是这套体系的不同切片:

名词 指的是什么
数字证书 那份"签过名的名片"本身
证书颁发机构(CA) 负责核实并签发证书的机构
PKI(公钥基础设施) 整套体系:CA + 证书格式 + 签发与吊销流程 + 客户端校验规则
根证书 信任链的起点,是预置在你系统里的那批 CA 证书
服务器证书 网站用的那一类证书(绑定域名)

三、动手 Demo:一条证书链的验证与篡改

证书不是一张,而是一条链。Demo 用三级链模拟了从根到服务器的验证过程:

# 用"主体的名字 + 签发者的密钥"模拟一次签名
def sig(name, key):
    return hashlib.sha256((name + "|" + str(key)).encode()).hexdigest()[:20]

root  = {"sub": "Global Root CA",            "key": 7001}   # 根:自签
inter = {"sub": "Global Secure Server CA",   "key": 1103}   # 中间:由根签
leaf  = {"sub": "www.example.com",           "key": 1307}   # 服务器:由中间签

# 验证:用【上一级的公钥】重算下一级的签名,看是否一致
sig(inter["sub"], root["key"]) == inter_sig
sig(leaf["sub"],  inter["key"]) == leaf_sig

实跑输出:

一、一条证书链就是三级【签过名的名片】
  层级                    证书主体                  由谁签的
  ① 根证书                Global Root CA            自己签自己(预置在系统里)
  ② 中间证书              Global Secure Server CA   Global Root CA
  ③ 服务器证书            www.example.com           Global Secure Server CA

  三张名片上的签名(模拟):
  根证书签名        f5a5d87e67073a9d0a73
  中间证书签名      f32e7d2bdac5a20671f9
  服务器证书签名    87562b3dae0e50c0a658

二、浏览器怎么验(自下而上,一路验到根)
  ① 用【预置的根公钥】重算中间证书的签名:f32e7d2bdac5a20671f9  → 一致
  ② 用【中间证书的公钥】重算服务器证书的签名:87562b3dae0e50c0a658  → 一致
  ③ 域名是否匹配、是否在有效期内、是否被吊销 → 全过才显示挂锁

三、改一个字符会怎样(形近域名钓鱼)
  原来的域名      www.example.com
  改成            www.examp1e.com   (字母 l 换成数字 1)
  重算签名        80eaf09f824dca72d2fc
  原签名          87562b3dae0e50c0a658
  → 不一致,浏览器拒绝
     证书挡住了【域名被改】这件事,但挡不住
     【攻击者真的注册了这个形近域名、再合法申请一张证书】。

四、自签证书:没有第三方背书,就是自己给自己发名片
  主体 = www.my-lab.local,签发者 = 也是 www.my-lab.local(自己)
  签名 = bc2c4c2273c2d1833d7b
  → 校验技术上能过,但浏览器找不到【信任链的起点】,
     于是红警告:不是私密连接。警告页上那个【继续】不该点。

五、根证书是整套体系的信任起点,也是它最脆弱的地方
  · 浏览器 / 操作系统预置约 100~150 个根证书,签一次就是全网信任
  · 2011 年荷兰 CA DigiNotar 被入侵,签发伪造证书对伊朗用户做中间人,
     事后被所有浏览器吊销、公司破产——一次失守,整个根一起作废
  · 2026 年正在收紧的规则:公开信任的 TLS 证书最长有效期
     2026-03-15 起 200 天 → 2027-03-15 起 100 天 → 2029-03-15 起 47 天

读这个输出:

四、⚠️ 2026 现状

30 秒实验

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

  1. 在浏览器里点开任意网站的证书信息,找到"有效期"那一栏:看它还剩几天。如果这个网站的有效期只剩十几天甚至几天,说明它背后有自动续期在跑——这就是 47 天时代的标准工作方式。
  2. 找一个你自己搭建或见过的自签证书场景(比如路由器管理页、内网设备页),故意访问一次,看清那个红警告页。然后问自己一句:如果我顺手点了"继续",我实际上放弃了什么?——答案:我放弃了"确认对面是它自称的那台机器"这件事,从此中间人换掉公钥我也看不出来。

这一节要带走的一句是:公钥加密给了每个人一把锁,数字证书解决的是"我怎么知道这把锁真是他的"——它靠的不是技术更聪明,而是让一个双方都信的第三方在锁上刻了自己的名字。

常见误区

  1. 错误:有证书就说明这个网站是安全的、可以放心输入密码。——纠正:证书只能证明两件事:这个域名确实归证书持有者控制、以及传输过程没被改过。它证明不了网站是好人、也证明不了网站会妥善处理你的数据。2026 年的现实是,绝大多数钓鱼网站都有合法的证书——因为"证明你控制这个域名"只需要几十秒、不花钱、不查身份。真正该看的是完整的域名,而不是有没有锁(5-8)。

  2. 错误:中间的"中间证书"是多余的,根证书直接签服务器证书不就行了。——纠正:中间证书的存在是为了保护根证书。根证书的私钥是整个体系的命门(它一失守,所有签发的证书全部失效,DigiNotar 就是先例),所以它必须离线保管、极少使用。做法就是让根只签一批中间 CA,日常签发全部由中间 CA 完成——万一中间 CA 出事,可以只吊销它一个分支,根仍然安全。 一句话:分层不是为了好看,是为了"出事时能局部止损"。

  3. 错误:证书有效期缩短纯粹是 CA 想多收钱。——纠正:这是浏览器厂商主导的规则,而且官方给出的理由和钱无关。CA/Browser Forum 的规则变更(SC-081v3)由 Apple 提出、Google/Mozilla/Microsoft 全票支持,主要理由是两条:① 吊销机制不可靠(软失败导致浏览器在验证不了时照样放行),缩短有效期可以让"吊销失败"这件事的影响窗口天然变小;② 为后量子迁移做铺垫——能快速轮换证书的组织,才能在未来算法必须更换时跟得上。而且 CA 明确说过不会因此加价(按年订阅,不按张数)。真正的成本落在使用方:手工续期在 47 天周期下不可行,必须上自动化。

  4. 错误:证书被吊销之后,网站立刻就打不开了。——纠正:不一定,而且"不一定"本身才是问题。吊销信息要通过 CRL 或 OCSP 传播,而浏览器在查不到吊销信息时通常选择"放行"——这个行为叫软失败(soft-fail),原因是"网络一抖就让全网不能访问"代价太大。结果就是:一张已被吊销的证书,现实中可能仍然能正常使用一段时间。这直接解释了为什么业界最后选择了"缩短有效期"这条路——与其指望吊销能及时生效,不如让证书本来就活不长(完整的机制对比见 5-10)。

自测三问(点开对答案) 1. 为什么"公开公钥"这个动作本身不安全? —— **因为公钥只是一个字符串,它不能自证身份**。**攻击者可以在传输过程中把它替换成自己的公钥**,于是**你以为在用对方的锁,实际上用的是攻击者的锁**——**对方的私钥解不开你发的消息,但攻击者的能解开**。**更麻烦的是双方都察觉不到**:A 以为消息安全送到了 B,B 以为自己在和 A 通信。**这个问题的本质是"缺少一个双方都认可的第三方来担保"**——**所以解法不是"把公钥藏起来"(公钥本来就要公开),而是"让第三方在公钥上签名"**,这就是数字证书(本节)。 2. 为什么证书链是"三级"而不是"根直接签服务器"? —— **为了保护根证书的私钥**。**根私钥一旦泄露或被滥用,所有由它签发的证书全部失效**——**2011 年 DigiNotar 事件就是这么收场的:一家 CA 被入侵,它签出的伪造证书直接让整个根在浏览器里被吊销、公司破产。** **分层的做法是:根离线保管、只签少量中间 CA;日常签发全部由中间 CA 承担。** **好处是"故障可隔离"**:**中间 CA 出事只需吊销那个分支,根本身不动。** **这也是各类 PKI 体系(不止 TLS,还有企业内部 PKI、代码签名)共同的结构**。 3. 证书能挡住"形近域名钓鱼"吗? —— **挡不住**。**`www.examp1e.com`(字母 l 换成数字 1)这类域名,攻击者可以自己注册、然后合法申请一张证书——校验全部通过,锁照常显示**。**证书能挡的是"把你原本要访问的域名悄悄改成别的"**(比如在中间替换证书内容),**挡不住"攻击者真的拥有一个长得像的域名"。** **所以防范形近域名靠的是另一套东西**:**看清完整域名、用密码管理器(它只在域名完全匹配时自动填充)、收藏官方入口而不是点邮件链接**(3-4 讲的就是这个场景)。

相关笔记