编程语言研究书库

分布式安全 — 在谁也不信的网络上,怎样仍然谈得成生意

22 分布式安全 — 在谁也不信的网络上,怎样仍然谈得成生意

1. 这一章讲什么

安全部分的最后一章,回答第 21 章刻意欠下的那笔债: 公钥分发那条「漫长而阴森的路」。在分布式系统里, OS 的边界消失了:对面的机器不归你管(它可能不执行、 甚至根本不认你的安全策略),中间的网络也不归你管 (攻击者与你的包同行同路,能伪造、复制、重放、篡改、 拖延)。本章给出实用主义的答案:别自己造,用精心设计的 标准工具——证书、会话密钥、防重放、安全通道。

2. 顶层全景

  两大麻烦:
    ① 远端机器不归你管(它可能已经被攻陷,或根本不认你的策略)
    ② 网络可被窃听/伪造/重放/篡改/拖延
        │
  四个标准件:
    证书:可信第三方用自己的私钥签名「公钥 ↔ 身份」
          ── 公钥不必保密,只需可验证地属于谁
    会话密钥:握手时用公钥商量出一把短期对称密钥,
          之后的通信全走对称加密(快几百倍)
    防重放:一次性数(nonce)挑战 + 序列号
    安全通道:一次握手完成认证+换钥,之后双向保密通信
        │
  工程落地:SSL/TLS = 普通 socket + 上述全部
          (SSL 本体已死,用 TLS;Diffie-Hellman 当着
           窃听者换钥,配证书签名防冒充)
        │
  一句当头棒喝:网络安全做得再好,
    也防不住「对面那台机器本身就是坏人」

图说:上半是威胁模型,下半是工具箱,底部是全章最重要的一句提醒。

3. 核心原理

3.1 威胁模型先立住

书里开头就把两条写死:远端机器可能不实现你的安全策略, 或者是个冒名顶替者;网络谁都能用,攻击者可以 「伪造、复制、重放、篡改、销毁、拖延」你的消息1。 密码学因此是本章的主角——但作者在章首就立下规矩: 正因为密码学难做对,必须用精心设计、久经考验的标准工具, 不要自己动手造2。

3.2 主线例子:浏览器怎么敢把信用卡号交给亚马逊

这是全章的主线例子,我们照原书走一遍3:

  1. 问题:你从没见过亚马逊的人。它说「我是 amazon.com」, 它给你一个公钥,你凭什么信这公钥不是攻击者中途换掉的? 总不能让 Bezos 挨个登门送公钥——「亚马逊会因此不怎么成功」 (书里的原话玩笑)4。
  2. 证书登场。解法:找一个大家都信任的第三方(证书机构, CA),由它用自己的私钥给一捆信息签名——这捆信息就是 证书:主体是谁、公钥是什么、有效期到哪天,打包, 附 CA 的签名5。客户端验法完全机械:对证书内容重算哈希、 用 CA 的公钥验签名,一致 → 这把公钥确实是 Frobazz(书里的 虚拟公司)的6。三个附带的好处书里点名:证书可以从 任何地方获取(验证不依赖来路)、每客户只做一次、 证书检查之前就可以小心开工(边验证边继续)7。
  3. 证书不是魔法,是信任转移。「任何人都能造证书」—— X.509 是格式标准,不是信任标准;判据只有一条:你信不信 签发者。不信 CA,证书一文不值;内网完全可以自建 「证书签发机」,手工装好它的公钥,从此告别商业 CA8。 证书的全部意义就是分发公钥;如果你的系统有别的好办法 分发公钥(比如 Kerberos 式的密钥分发中心,或干脆预先 手工交换),证书可以整个不用9。 这里有个必须想明白的鸡生蛋:验证书靠 CA 的公钥, **CA 的公钥又是哪来的?**答案只能是自举——总得有 第一把公钥以不带密码学保护的方式来到你手里:最常见的 是浏览器出厂时预装的几百个可信签发机构的公钥—— 你「认识」几百家公司吗?不认识也谈不上,但你的浏览器 实际上就是这么信它们的10。信任的总量没有减少, 只是被压缩进了那次装机。
  4. 为什么握手之后还要换对称密钥?(握手:通信开头那几轮交换凭证、商定参数的对话。)公钥运算比对称加密 慢几百倍;全部流量都走公钥加密付不起。所以标准姿势: 握手阶段用公钥完成认证 + 交换一把短期会话密钥(session key), 之后的通信全走对称加密——各取所长11。
  5. 防重放。握手本身也可能被重放:攻击者录下当年的握手, 指望重放骗出新会话。对策是一次性数(nonce): 每次会话挑战一个只新鲜一次的随机数,能正确应答的 必然在线持有私钥;随后的消息再靠序列号挡住录制重放12。
  6. 安全通道。把以上打包:一次握手(验证身份、协商密钥、 建立参数)→ 一条安全通道:双向保密、完整性可验、 防重放。一次性投入,长期受益13。

3.3 工程终态:SSL/TLS 把标准件装进 socket

上面的标准件在工程上长成一个具体协议:给普通 socket 接上加密结构,这头进明文、那头出密文,对端反过来—— 这就是 SSL 当年的想法;SSL 自己已被攻破、永不许再用, 今天该用的是继任者 TLS(写书时是 1.3)——人们口头说的 「SSL」几乎都是「SSL/TLS」的简称14。它的开局叫握手, 步骤照原书走一遍15:

  1. **协商算法套件。**两端各自报自己能干什么(版本、 加密算法、哈希、换钥方式、认证方式),凑出一套双方都接受、 安全与性能兼顾的组合。一副典型的牌:RSA 2048 位做认证、 Diffie-Hellman 换出会话钥匙、SHA-3 保完整性、 AES-256 加密流量;一台现代机器能支持 50 多种组合, 多数应用不必亲自挑,让 TLS 自己谈拢16。
  2. **每条连接一把全新对称钥匙。**最佳实践:每次建立连接, bulk 数据都用新钥匙;公钥只做认证和换钥,重的加密活 全交给对称——第 21 章那几百倍的差距在这里兑现15。
  3. **用证书给换钥验明正身。**Diffie-Hellman 能当着窃听者 商量出钥匙,但不能保证你在跟谁商量,所以服务器用自己的 私钥给换钥消息签名,客户端拿证书里的公钥验——钥匙确实 只与真服务器共享。典型 Web 配置里客户端没有证书、 签不了名,于是握手中只有服务器验明了,客户端身份仍是 未知数——没关系,客户端接下来会用密码在这条受保护的 通道里认证自己17。

Diffie-Hellman 值得单独看一眼:TLS 常用它换钥18。 两人公开约定两个数(大素数 n、生成元 g,不怕被听); Alice 私选大随机数 x、发出 g^x mod n,Bob 私选 y、 发出 g^y mod n;窃听者只看到 g、n 和两个结果值。 然后 Alice 算 (g^y)^x mod n,Bob 算 (g^x)^y mod n—— 指数的交换律让两人得到同一个数,它就是共享钥匙; 窃听者想从 g^x 反推 x,得算离散对数——已知结果倒找 那个指数的计算,数大了现实中算不动 (书里给的尺度:600 位素数够用)。但它有一个洞: 防得住偷听,防不住冒充——Mallory 可以两头各换一次钥。 所以 D-H 从不单独使用,永远配认证(TLS 里就是证书加签名)。

最后一条工程教训:SSL/TLS 是协议,不是某个软件。 同一个协议有多个实现,实现各自的洞互不相干——Heartbleed 是 OpenSSL 的实现漏洞,微软的实现就没中;听说的 SSL 事故, 先分清是协议洞还是实现洞,再决定要不要动手19。

3.4 认证之后与其他标准件

**免密续聊靠 cookie。**网站不会你每点一个链接就要一次密码。 它认的是服务器发给你的一段数据(cookie):服务器用 只有自己知道的钥匙把「你的身份」签进去,浏览器之后每个请求 自动捎带,服务器验签即知你是谁。书里点破了它的本质: cookie 就是密码学能力——服务器替你造了一张别人伪造不了 的票,第 21 章能力一节欠下的「再续」在此兑现;这套做法也是 大量分布式系统的通用模式20。代价同样写明:别人坐上你 登录过的电脑就能用,这是为可用性付的安全账。

挑战/应答:不用加密信道的认证。服务器每次发一个不同的 随机挑战,你用自己的秘密(人或硬件令牌)对它算出一个应答; 挑战每次不同,录下旧应答毫无用处,所以挑战和应答根本不必 加密21。在线认证服务器是另一种:你和一个双方都信的 服务器打交道,它在线为你的身份担保——证书是这种服务器的 「离线版」,离线证书发了就很难收回,在线服务器却能立刻 吊销被攻陷方的认证,Kerberos 是著名例子22。

两个高层工具的诚实注脚。HTTPS 几乎就是「HTTP 流过一条 TLS 连接」——正因如此便宜,它成了整门课;但证书验过了 只证明「这把钥匙属于这个名字」,不证明这个名字是好人: 持证网站照样能攻击你(又绕回 3.5 的当头棒喝)。HSTS 是 配套的硬度选项:开了它的网站拒绝回退到明文 HTTP23。 SSH(安全外壳)第一次连陌生主机时,公钥往往只是现场 问对方要的、没有证书背书——中间人把真公钥扣下、换上 自己的,你就信了坏人;SSH 会弹警告,而民间智慧说: 所有人,包括安全专家,都点「继续」24。

3.5 那句当头棒喝

本章最诚实的一句告诫:就算你把网络安全做到完美, 对面那台机器本身仍可能是坏人——被攻陷的合作伙伴 发来的攻击,再「认证加密」也不 consolation(书里原话: 它给了你一点点安慰都没有)25。安全是分层的事业: 这一章只管「网线这一段」;对面系统的健康状况, 属于威胁模型里要另外处理的问题(最小权限、监控、 备份——前面章节的主题在这里合流)。

4. 作者的判断与证据

书里给了证据的判断:

  • 证书验证的五步(取证书 → 验 CA 签名 → 重算哈希对比 → 查有效期 → 信任链)是可机械执行的完整协议6;
  • 公钥加密比对称慢「数百倍」是本章换钥方案的性能依据11;
  • Kerberos 与预共享公钥被列为证书的合法替代, 取决于域内信任形状9。

作者的判断(立场):

  • 「自己造密码学工具」被直接判为坏主意——本章开篇即立此规矩; 这是安全写作的惯例,但作者给了理由:密码学的失败模式 不直观,成功无法自证2。
  • 「信任谁」的判断被明确推回给人:工具只转移信任,不创造信任8。

5. 边界与局限

  • 本章是导论级:PKI 的生态(CA 被入侵、证书透明度、 交叉签名)、TLS 握手的完整报文格式、前向保密 (forward secrecy)等一概未展开——够建立心智模型, 不够指导部署(部署请回到标准文档)。
  • Kerberos 只点到「在线认证服务器」一层;它在企业内网的 完整故事(票据、KDC 单点、跨域信任)是一章装不下的。
  • 成书时点的主流仍是「服务器持证、用户持密码」; 客户端证书、passkey/WebAuthn 这类双向变革 在本章视野之外(补充,不在书里)。

6. 可带走的

  1. 威胁模型先行:先写清「对手能做什么」,再选工具; 不写威胁模型的安全讨论都是闲聊。
  2. 证书 = 可信第三方对「公钥 ↔ 身份」的签名; 验证是机械五步,信任只有一条:你信不信签发者。
  3. 公钥做认证与换钥,对称做通信——慢的用于握手,快的用于干活。
  4. 重放是分布式特有的攻击面:nonce + 序列号是标配疫苗。
  5. 「对面已被攻陷」不是这一层防得住的——分层防御, 每层只守自己的一段。
  6. 最后一条是元教训:安全部件全部用标准件;自造是 连专家都会栽的坑,我们不是专家。
  7. 协议 ≠ 实现:听说 SSL/TLS 出事,先分清是协议洞还是 某个实现的洞——Heartbleed 只中了 OpenSSL, 别的实现没中,不必全员恐慌。
  8. 证书的鸡生蛋解法是「预装」:你信的几百个 CA, 其实是浏览器出厂时替你做的决定——自建系统就自己动手 装那把第一公钥。

7. 原文地图

主题原书章原文位置
两大麻烦与威胁模型57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:17(搜「forge」)
用标准工具,别自造57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:23(搜「standard」)
「网络完美也不防对面」57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:110(搜「even if you secure」)
证书的定义与内容57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:142(搜「certificate」)
客户验证书五步57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:172(搜「examines」)
「任何人都能造证书」与信任判据57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:225(搜「Anyone can create」)
可不用证书的情形57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:238(搜「dispense」)
会话密钥与性能差57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:364(搜「fresh key」)
重放与 nonce57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:251(搜「replay」)
证书的鸡生蛋与浏览器预装57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:196(搜「chicken」)与:206(搜「several hundred」)
SSL 已死、用 TLS57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:325(搜「insecure and should never」)
握手:协商套件与新钥匙57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:352(搜「brand new key」)与:372(搜「negotiation」)
典型套件与 50 多种组合57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:381(搜「50 or more」)
服务器签名换钥、客户端无证书57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:450(搜「sign its」)
Diffie-Hellman 换钥与防冒充57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:439(搜「600 digit」)与:440(搜「fly in the ointment」)
协议 ≠ 实现(Heartbleed)57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:475(搜「protocol, not a software」)
cookie 与密码学能力57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:512(搜「web cookies」)与:536(搜「these web cookies are」)
挑战/应答协议57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:547(搜「challenge/response」)
在线认证服务器与即时吊销57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:581(搜「instantly」)与:583(搜「Kerberos」)
HTTPS、HSTS 与持证攻击57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:605(搜「passed through an SSL」)与:626(搜「still launch an attack」)与:642(搜「Strict Transport」)
SSH 首连中间人57. Distributed System Securitytext/59-ch57-57-distributed-system-security.txt:696(搜「substitute one containing」)与:705(搜「folk wisdom」)

Footnotes

  1. 出处:「57. Distributed System Security」第 13–19 段(text/59-ch57-57-distributed-system-security.txt:17,搜「forge」)。原文:攻击者可伪造、复制、重放、篡改、销毁、拖延消息。 ↩

  2. 出处:「57. Distributed System Security」第 20–89 段(text/59-ch57-57-distributed-system-security.txt:23,搜「standard」)。原文:密码学难做对,应使用精心设计的标准工具而非自造。 ↩ ↩2

  3. 出处:「57. Distributed System Security」第 90–215 段(text/59-ch57-57-distributed-system-security.txt:90,搜「PK cryptography」)。原文:网站用公钥向所有用户认证自己,用户用密码向网站认证——非对称与对称各得其所。 ↩

  4. 出处:「57. Distributed System Security」第 116–126 段(text/59-ch57-57-distributed-system-security.txt:124,搜「in-person」)。 ↩

  5. 出处:「57. Distributed System Security」第 131–146 段(text/59-ch57-57-distributed-system-security.txt:142,搜「certificate」)。 ↩

  6. 出处:「57. Distributed System Security」第 152–183 段(text/59-ch57-57-distributed-system-security.txt:172,搜「examines」)。Frobazz/Acmesign 的例子:重算 SHA-3 哈希、验签名、比对。 ↩ ↩2

  7. 出处:「57. Distributed System Security」第 186–194 段(text/59-ch57-57-distributed-system-security.txt:187,搜「literally anywhere」)。 ↩

  8. 出处:「57. Distributed System Security」第 225–232 段(text/59-ch57-57-distributed-system-security.txt:225,搜「Anyone can create」)。原文:判据是「你信不信签发者」;内网可自建签发机并手工装公钥。 ↩ ↩2

  9. 出处:「57. Distributed System Security」第 238–240 段(text/59-ch57-57-distributed-system-security.txt:238,搜「dispense」)。原文:证书的全部意义就是分发公钥;有别的好办法就免了。 ↩ ↩2

  10. 出处:「57. Distributed System Security」第 195–210 段(text/59-ch57-57-distributed-system-security.txt:196,搜「chicken」)与 :206(搜「several hundred」)。原文:总得自举——第一把可信公钥最常见的来源是浏览器预装的几百个签发机构的公钥。 ↩

  11. 出处:「57. Distributed System Security」对称/公钥性能对比(text/58-ch56-56-protecting-information-with-cryptography.txt:280,搜「hundreds of times longer」)与会话密钥的建立(text/59-ch57-57-distributed-system-security.txt:364,搜「fresh key」)。 ↩ ↩2

  12. 出处:「57. Distributed System Security」第 245–270 段(text/59-ch57-57-distributed-system-security.txt:251,搜「replay」)。 ↩

  13. 出处:「57. Distributed System Security」安全通道小节(text/59-ch57-57-distributed-system-security.txt:369,搜「secure connection」)。 ↩

  14. 出处:「57. Distributed System Security」第 313–358 段(text/59-ch57-57-distributed-system-security.txt:325,搜「insecure and should never」)。原文:SSL 形式上说已不安全,不该再用于任何事,用 TLS;TLS 1.3 堵上了 1.2 的若干漏洞。 ↩

  15. 出处:「57. Distributed System Security」第 349–389 段(text/59-ch57-57-distributed-system-security.txt:352,搜「brand new key」)与 :372(搜「negotiation」)。原文:每条连接为 bulk 数据用一把全新对称钥匙;握手第一步是协商双方都能接受的算法组合。 ↩ ↩2

  16. 出处:「57. Distributed System Security」第 377–382 段(text/59-ch57-57-distributed-system-security.txt:381,搜「50 or more」)。原文:一副典型组合 RSA 2048 / Diffie-Hellman / SHA-3 / AES-256;现代 SSL 安装可支持 50 多种组合。 ↩

  17. 出处:「57. Distributed System Security」第 390–474 段(text/59-ch57-57-distributed-system-security.txt:450,搜「sign its」)。原文:服务器用私钥给 Diffie-Hellman 消息签名以证明身份;客户端通常没有证书、不能签名,之后在通道内用密码认证。 ↩

  18. 出处:「57. Distributed System Security」Diffie-Hellman 旁注(text/59-ch57-57-distributed-system-security.txt:439,搜「600 digit」)与 :440(搜「fly in the ointment」)。原文:两人各自算 (g^y)^x 与 (g^x)^y mod n 得同一把钥匙,窃听者须算离散对数;但防不住中间冒充,须配认证。 ↩

  19. 出处:「57. Distributed System Security」第 475–489 段(text/59-ch57-57-distributed-system-security.txt:475,搜「protocol, not a software」)。原文:SSL/TLS 是协议不是软件包;Heartbleed 是 OpenSSL 实现的问题,微软的实现没中。 ↩

  20. 出处:「57. Distributed System Security」第 491–545 段(text/59-ch57-57-distributed-system-security.txt:512,搜「web cookies」)与密码学能力的脚注(:536,搜「these web cookies are」)。原文:cookie 是服务器用私有钥匙造的、别人伪造不了的能力,验过密码后代替密码完成后续认证;大量分布式系统同此模式。 ↩

  21. 出处:「57. Distributed System Security」第 546–565 段(text/59-ch57-57-distributed-system-security.txt:547,搜「challenge/response」)。原文:挑战每次不同,录旧应答无益,故挑战与应答无需加密。 ↩

  22. 出处:「57. Distributed System Security」第 566–584 段(text/59-ch57-57-distributed-system-security.txt:581,搜「instantly」)与 :583(搜「Kerberos」)。原文:在线认证服务器可即时吊销被攻陷方的认证,离线证书则很难收回;Kerberos 是著名实例。 ↩

  23. 出处:「57. Distributed System Security」HTTPS 小节(text/59-ch57-57-distributed-system-security.txt:605,搜「passed through an SSL」)、:626(搜「still launch an attack」)与 :642(搜「Strict Transport」)。原文:HTTPS ≈ HTTP 过 SSL 连接;证书验过不等于对方是好人;HSTS 拒绝回退明文 HTTP。 ↩

  24. 出处:「57. Distributed System Security」SSH 小节(text/59-ch57-57-distributed-system-security.txt:696,搜「substitute one containing」)与 :705(搜「folk wisdom」)。原文:首次连接的公钥只是现场问来的,中间人可换入自己的;警告弹出时所有人都点「继续」。 ↩

  25. 出处:「57. Distributed System Security」第 109–114 段(text/59-ch57-57-distributed-system-security.txt:110,搜「even if you secure」)。原文:被攻陷的伙伴发起的攻击,「authenticated and encrypted」也无济于事。 ↩

On this page