一、安全通信的四个属性

属性 含义 靠什么实现
机密性(Confidentiality) 只有发送方和接收方能理解内容 加密
完整性(Integrity) 内容未被篡改(或篡改能被检测) MAC / 数字签名
认证(Authentication) 双方能确认对方的身份 挑战-响应 / 证书
可用性(Availability) 服务可被合法用户访问 抗 DDoS、冗余

⚠️ 四者互相独立,缺一不可。

只有机密性没有完整性 → 攻击者虽读不懂,但可以【翻转密文比特】造成可预测的明文改变
只有完整性没有认证   → 你确认消息没被改,但不知道是谁发的
只有认证没有机密性   → 你知道是他发的,但所有人都能读

📌 一个真实的教训:早期的 WEP(第 25 讲)加密了内容但完整性保护极弱,攻击者可以在不解密的情况下篡改分组——加密不等于安全


二、对称密钥密码

2.1 基本模型

   Alice                                  Bob
    │                                      │
明文 m ──[加密 K_s]──▶ 密文 ──[解密 K_s]──▶ 明文 m
                        │
                    ⭐ 双方共享【同一个】密钥

2.2 从替换密码到分组密码

凯撒密码/单表替换:每个字母映射到另一个字母。

⚠️ 靠频率分析几分钟就能破解——英文中 e 出现频率最高,密文中出现最多的字母就是 e

分组密码(Block Cipher):现代做法。把明文切成固定长度的分组,每组用密钥做多轮的替换 + 置换

算法 分组 密钥 状态
DES 64 位 56 位 ⚠️ 已被暴力破解(1997 年起)
3DES 64 位 168 位 慢,逐步淘汰
AES 128 位 128/192/256 位 当前标准,有硬件指令加速

2.3 分组密码的工作模式 ⭐

关键问题:如果两个明文分组相同,密文也会相同吗?

ECB 模式(电码本):每组独立加密。

⚠️ 相同的明文分组 → 相同的密文分组
→ ⭐ 明文的【结构】完全泄露

📌 著名的"ECB 企鹅"图:用 ECB 加密一张企鹅图片,加密后仍然能清楚看出企鹅的轮廓。这是密码学教学中最有力的一张图。

CBC 模式(密码分组链接)

C_i = E(K, P_i ⊕ C_{i−1})       C_0 = IV(初始向量,随机)

⭐ 每一组的加密都依赖前一组的密文
→ 相同的明文产生不同的密文

CTR 模式(计数器):把分组密码当成流密码用,⭐ 可并行

GCM 模式(Galois/Counter Mode)CTR + 认证标签

⭐ 同时提供【机密性】和【完整性】—— 称为 AEAD(带关联数据的认证加密)
→ 这是 TLS 1.3 唯一允许的模式类型(第 28 讲)

📌 现代密码学的一条铁律:**永远不要只加密不认证。**AEAD 把两者绑在一起,从 API 层面消除了「忘了做完整性校验」这类错误。

2.4 对称密钥的根本问题

Alice 和 Bob 如何在从未见过面的情况下,约定一个只有他们知道的密钥?

**这就是密钥分发问题。**它无法在对称密码的框架内解决——因为约定密钥本身就需要一个安全信道。


三、公钥密码

3.1 突破性思想(Diffie-Hellman, 1976)

每个人有【一对】密钥:
   ⭐ 公钥 K⁺  —— 公开给所有人
   ⭐ 私钥 K⁻  —— 只有自己知道

⭐ 关键性质:K⁻(K⁺(m)) = m  且  K⁺(K⁻(m)) = m
   而【从公钥无法推算出私钥】

加密:任何人用 Bob 的公钥加密 → 只有 Bob 能用私钥解密。

密钥分发问题被解决了:公钥可以公开发布。

3.2 RSA

密钥生成

① 选两个大素数 p、q
② n = p·q,   z = (p−1)(q−1)
③ 选 e,使 1 < e < z 且 ⭐ e 与 z 互质
④ 求 d,使 ⭐ e·d ≡ 1 (mod z)
⑤ 公钥 = (n, e),私钥 = (n, d)

加解密

加密:  c = m^e  mod n
解密:  m = c^d  mod n

3.3 手算示例 ⭐

① p = 5, q = 7
② n = 35,  z = 4 × 6 = 24
③ 取 e = 5   (5 与 24 互质 ✓)
④ 求 d 使 5d ≡ 1 (mod 24)
   d = 5:  25 mod 24 = 1  ✓
   ⭐ d = 5
   
公钥 = (35, 5),私钥 = (35, 5)

加密字母 l(在字母表中是第 12 个)

c = 12^5 mod 35
  = 248832 mod 35

248832 ÷ 35 = 7109 余 17
⭐ c = 17

解密

m = 17^5 mod 35
  = 1419857 mod 35

分步计算避免大数:
   17^2 = 289;  289 mod 35 = 9
   17^4 = 9^2 = 81; 81 mod 35 = 11
   17^5 = 11 × 17 = 187; 187 mod 35 = 12
   
⭐ m = 12 = 'l'  ✅

📌 模幂的分步技巧(考试必用):a^b mod n 不要先算 a^b 再取模(数字会爆炸),而要每一步都取模

3.4 RSA 的安全性基础

⭐ 已知 n,很难分解出 p 和 q(大整数分解问题)

n 为 2048 位时,用已知最好的算法与现有算力,分解需要天文数字的时间

⚠️ 注意措辞是"很难"而不是"不可能"——RSA 的安全性依赖于尚未被证明的计算困难性假设。⭐ Shor 算法证明了量子计算机可以在多项式时间内分解大整数,这就是后量子密码学(PQC)研究的动机。

3.5 ⭐ 为什么必须混合使用

RSA 比 AES 慢【 2–3 个数量级】

因此实际做法(混合加密 / 会话密钥)

① Alice 生成一个【随机的对称会话密钥 K_s】
② ⭐ 用 Bob 的公钥加密 K_s,发给 Bob         ← 公钥密码,只用一次
③ Bob 用私钥解出 K_s
④ ⭐ 之后所有数据都用 K_s 做 AES 加密        ← 对称密码,速度快

🎯 这就是 TLS、SSH、PGP 全都采用的模式用公钥密码解决"密钥分发",用对称密码解决"批量加密"。各自做自己擅长的事。


四、完整性:哈希、MAC、数字签名

4.1 密码学哈希函数

H(m) → 固定长度的摘要(如 SHA-256 输出 256 位)

三个必需性质

性质 含义
单向性 由 H(m) 无法反推出 m
抗第二原像 给定 m,找不到 m’ ≠ m 使 H(m’) = H(m)
抗碰撞 找不到任意一对 m ≠ m’ 使 H(m) = H(m')
算法 输出 状态
MD5 128 位 ⚠️ 碰撞已可在几秒内构造,绝对不可用于安全场景
SHA-1 160 位 ⚠️ 2017 年被 Google 实际构造出碰撞,已淘汰
SHA-256 / SHA-3 256 位 当前推荐

⚠️ 注意 MD5/SHA-1 仍可用于非安全用途(文件去重、校验传输错误),但任何涉及对手的场景都不能用

4.2 ⭐ 单独的哈希不能提供完整性

这是一个极其常见的误解。

Alice 发送:  (m, H(m))
攻击者截获后:  把 m 改成 m',⭐ 重新计算 H(m'),发送 (m', H(m'))
Bob 验证:    H(m') 与收到的一致 ✅ —— 但内容已被篡改

因为哈希函数是公开的,任何人都能计算。

解法:加入一个只有双方知道的秘密。

4.3 MAC(报文认证码)

⭐ MAC = H(m + s)      s 是双方共享的秘密(认证密钥)

Alice 发送: (m, H(m + s))
攻击者不知道 s → 无法构造合法的 MAC

实际使用 HMAC(RFC 2104),它做了两次嵌套哈希:

HMAC(K, m) = H( (K ⊕ opad) ‖ H( (K ⊕ ipad) ‖ m ) )

为什么不用朴素的 H(s‖m)?因为多数哈希函数(MD5、SHA-1、SHA-256)采用 Merkle-Damgård 结构,存在长度扩展攻击:攻击者在不知道 s 的情况下,可以由 H(s‖m) 计算出 H(s‖m‖m')HMAC 的双层结构消除了这个问题。

4.4 数字签名

MAC 的局限

⚠️ MAC 用【共享】密钥 → Alice 和 Bob 都能生成
→ Bob 无法向第三方证明"这条消息是 Alice 发的"(他自己也能造)
→ ⭐ 没有【不可否认性】(non-repudiation)

数字签名用私钥

签名:  Alice 用【自己的私钥】加密 H(m)  →  签名 σ = K⁻_A(H(m))
验证:  任何人用【Alice 的公钥】解开 σ,与自己算出的 H(m) 比对

只有 Alice 有私钥 → 只有 Alice 能签 → Alice 无法否认

为什么签名 H(m) 而不是 m 本身?

  1. 性能:公钥运算慢,签 256 位的摘要比签 10 MB 的文件快得多
  2. 长度:签名长度固定,与消息大小无关

4.5 三者对比 ⭐

用什么密钥 机密性 完整性 认证 不可否认
哈希
MAC 共享秘密
数字签名 私钥
AEAD(GCM) 共享秘密

📌 这张表建议直接背下来,期末必考。


五、公钥分发与证书

5.1 剩下的问题

公钥密码解决了对称密钥的分发问题,但引入了一个新问题

你怎么知道拿到的"Bob 的公钥"真的是 Bob 的?

中间人攻击

Alice ──"给我 Bob 的公钥"──▶ ⭐ Trudy(冒充)
       ◀── Trudy 的公钥 K⁺_T ──
Alice 用 K⁺_T 加密 → Trudy 能解密、读取、篡改、再用 K⁺_B 转发给 Bob

⭐ Alice 和 Bob 都以为在安全通信,实际上 Trudy 读了全部内容

5.2 认证中心(CA)与证书

⭐ 证书 = CA 用【自己的私钥】签名的一份声明:
        「公钥 K⁺_B 属于 Bob(域名 bob.com)」

任何人用【CA 的公钥】验证签名 → 确认这个绑定是可信的

证书包含

主体名称(域名)· 主体公钥 · 颁发者 · 有效期
序列号 · 用途扩展 · ⭐ CA 的数字签名

5.3 信任链

   ⭐ 根 CA(自签名,公钥【预置在操作系统/浏览器中】)
        │  签发
   中间 CA
        │  签发
   服务器证书(bob.com)

⚠️ 信任的起点必须是「预置的」——根 CA 的公钥不能从网上下载(那又是中间人问题),必须随操作系统或浏览器一起分发。

📌 这意味着一件重要的事你的浏览器信任着数百个根 CA。任何一个被攻破或作恶,都能为任意域名签发有效证书。

真实案例

年份 事件
2011 荷兰 CA DigiNotar 被入侵,攻击者为 *.google.com 签发了有效证书,用于对伊朗用户的大规模中间人攻击。DigiNotar 随后破产
多次 若干 CA 因误签发或流程违规被浏览器厂商吊销信任

缓解机制

  • 证书透明度(Certificate Transparency, CT):所有签发的证书必须记入公开的、只可追加的日志。域名所有者可以监控是否有人为自己的域名签发了未授权的证书。今天的浏览器要求证书必须有 CT 日志凭据。
  • HPKP(公钥固定):已废弃,因为配置错误会让网站永久无法访问——一个"安全机制本身成为可用性风险"的教训
  • CAA 记录(DNS):域名所有者声明"只有 CA X 可以为我签发证书"。

六、认证协议的演进 ⭐

这一节是本讲最好的教学材料:每一版协议都被一种具体的攻击击破,逼出下一版。

ap1.0

Alice ──"我是 Alice"──▶ Bob

⚠️ 任何人都可以这么说。

ap2.0:用 IP 地址认证

Alice ──"我是 Alice"(源 IP = Alice 的 IP)──▶ Bob

⚠️ 被 IP 欺骗击破(第 4 讲)——源地址可以随意伪造。

ap3.0:用密码

Alice ──"我是 Alice" + 密码──▶ Bob

⚠️ 被嗅探击破——密码明文传输,共享介质上任何人都能读到。

ap3.1:加密密码

Alice ──"我是 Alice" + 【加密的】密码──▶ Bob

⚠️ ⭐ 被【重放攻击】击破!

Trudy 不需要【解密】那段密文,
她只需要【原样录下来,下次原样发出去】
→ Bob 解密后得到正确的密码 → 认证通过

📌 这是本讲最重要的一个洞察:**加密不能防重放。**攻击者无需理解内容就能复用它。

ap4.0:引入现时数(Nonce)⭐

⭐ Nonce = 一生只用一次的随机数

Alice ──"我是 Alice"──────────────▶ Bob
      ◀──── ⭐ 随机数 R ───────────
      ──── K_{A-B}(R) ───────────▶  Bob 解密,验证得到的是 R

为什么能防重放

R 每次都不同 → 上次录下的 K(R_old) 这次没用
→ 攻击者必须【现场】用密钥加密新的 R,而她没有密钥

🎯 **Nonce 是密码协议中最基本、最重要的构件之一。**你会在 TLS 握手、WPA3、Kerberos、JWT 中反复见到它。

ap5.0:用公钥代替共享密钥

Alice ──"我是 Alice"────────────────▶ Bob
      ◀──── 随机数 R ───────────────
      ──── ⭐ K⁻_A(R)(用私钥签名)──▶
      ◀──── "把你的公钥给我" ────────
      ──── K⁺_A ──────────────────▶  Bob 验证 K⁺_A(K⁻_A(R)) = R ✓

⚠️ ⭐ 仍然被中间人攻击击破!

Trudy 截获全部通信:
   对 Bob 冒充 Alice(用自己的私钥签 R,发自己的公钥)
   对 Alice 冒充 Bob
   ⭐ 双方都认证"成功",但中间坐着 Trudy

⭐ 根本原因:Bob 拿到的"Alice 的公钥"没有经过【认证】

最终解法:证书。Bob 不接受裸公钥,只接受由可信 CA 签名的证书

演进总结表

版本 机制 被什么击破
ap1.0 声称身份 任何人都能声称
ap2.0 IP 地址 IP 欺骗
ap3.0 明文密码 嗅探
ap3.1 加密密码 重放攻击
ap4.0 Nonce + 共享密钥 ✅ 可用,但需要预先共享密钥
ap5.0 Nonce + 公钥 中间人攻击
最终 Nonce + 公钥 + 证书 这就是 TLS 握手(第 28 讲)

七、例题(Worked Example)

题目

(a) RSA:p = 3, q = 11, e = 3。求 n、z、d,并加密 m = 4,再解密验证。 (b) Alice 想向 Bob 发送消息 m,同时保证机密性、完整性、认证和不可否认性。请设计一个方案,写出 Alice 的操作和 Bob 的验证步骤。 (c) 在 (b) 中,如果先加密再签名,与先签名再加密,有什么区别? (d) 为什么单独用哈希不能提供完整性,而 HMAC 可以?

解答

(a)

n = p·q = 3 × 11 = 33
z = (p−1)(q−1) = 2 × 10 = 20
e = 3   (3 与 20 互质 ✓)

求 d 使 3d ≡ 1 (mod 20):
   d=7:  21 mod 20 = 1  ✓
⭐ d = 7

公钥 = (33, 3),私钥 = (33, 7)

加密 m = 4

c = 4³ mod 33 = 64 mod 33 = ⭐ 31

解密 c = 31

m = 31⁷ mod 33

分步取模:
   31 ≡ −2 (mod 33)
   31² ≡ 4 (mod 33)
   31⁴ ≡ 4² = 16 (mod 33)
   31⁷ = 31⁴ × 31² × 31 ≡ 16 × 4 × 31 (mod 33)
        = 64 × 31 ≡ 31 × 31 (mod 33)   (64 mod 33 = 31)
        = 961 mod 33
   961 ÷ 33 = 29 余 4
⭐ m = 4  ✅

(b) 方案:签名 + 混合加密

Alice 的操作:
① 计算摘要:  h = H(m)                          (SHA-256)
② ⭐ 签名:   σ = K⁻_Alice(h)                   → 完整性 + 认证 + 不可否认
③ 生成随机对称会话密钥 K_s
④ ⭐ 加密:   c = AES-GCM(K_s, m ‖ σ)           → 机密性(+ 传输完整性)
⑤ ⭐ 封装密钥: k = K⁺_Bob(K_s)                 → 只有 Bob 能取出 K_s
⑥ 发送 (c, k)

Bob 的验证:
① 用私钥解出 K_s = K⁻_Bob(k)
② 用 K_s 解密并验证 GCM 认证标签 → 得到 m 和 σ
③ ⭐ 用 Alice 的【证书中的】公钥验证 σ:K⁺_Alice(σ) 是否等于 H(m)
④ 一致 → 四个属性全部满足 ✅

⚠️ 第 ③ 步必须使用【证书中的】公钥,而不是 Alice 随消息附带的裸公钥——否则就退回到 ap5.0 的中间人问题。

(c) 区别很重要。

推荐:先签名再加密(Sign-then-Encrypt),即上面的方案。

先签名再加密:
   ✅ 签名被加密保护 → ⭐ 第三方无法看到"Alice 给某人发过消息"这一事实
   ✅ 签名覆盖的是【真正的明文】,语义清晰

先加密再签名:
   ⚠️ 签名在密文外面,任何人可见 → ⭐ 泄露了通信关系(元数据泄露)
   ⚠️ 更严重的问题:⭐ 攻击者可以【剥掉 Alice 的签名,换上自己的】,
      声称这份密文是【他】发的 —— 这叫"签名剥离攻击"(surreptitious forwarding)
      Bob 无法判断真正的作者是谁

📌 一般原则签名应当覆盖你真正想承诺的内容,而你想承诺的是明文的语义,不是某段密文的字节。

(d)

单独用哈希不行,因为哈希函数是公开的、无密钥的:攻击者把 m 改成 m’ 后,可以自己重新计算 H(m’) 并一并替换,接收方验证会通过。哈希只能检测随机的传输错误,不能对抗有意的篡改

HMAC 可以,因为它把一个只有通信双方知道的密钥 K 混入了哈希计算:HMAC(K, m)。攻击者不知道 K,因此无法为篡改后的 m’ 生成正确的 HMAC。

关键区别是「是否引入了对手不知道的秘密」——这是所有完整性保护机制的共同本质(MAC 用共享秘密,数字签名用私钥)。


八、随堂自测

  1. 安全通信的四个属性是什么?举一个"有机密性但没有完整性"导致的真实问题。
  2. ECB 模式为什么不安全?什么是 AEAD?
  3. 对称密钥密码的根本问题是什么?公钥密码如何解决它?
  4. RSA:p=7, q=11, e=13,求 d。
  5. ⭐ 为什么实际系统不直接用 RSA 加密数据?
  6. ⭐ 为什么单独发送 (m, H(m)) 不能保证完整性?
  7. MAC 和数字签名的关键区别是什么?哪个提供不可否认性?
  8. 为什么数字签名要签哈希值而不是原文?
  9. ⭐ ap3.1 被什么攻击击破?为什么加密不能防这种攻击?
  10. ap5.0 已经用了公钥和 nonce,为什么还会被中间人攻击?最终怎么解决?

九、本讲要点回顾

  • 四个属性:机密性、完整性、认证、可用性——互相独立,缺一不可。⭐ 加密 ≠ 安全
  • ECB 泄露明文结构;⭐ AEAD(AES-GCM)同时提供机密性与完整性,是现代标准。
  • 对称密码快但有密钥分发问题;公钥密码解决分发但慢 2–3 个数量级
  • 混合加密:公钥加密会话密钥,对称密钥加密数据。TLS/SSH/PGP 都这样做。
  • 模幂计算每一步都要取模
  • 单独的哈希不提供完整性(哈希是公开的);必须引入对手不知道的秘密
  • MAC(共享秘密)无不可否认性;数字签名(私钥)有
  • 证书 = CA 签名的「公钥属于某主体」的声明;信任起点是预置的根 CA 公钥
  • CT(证书透明度) 让误签发可被检测。
  • 认证协议演进:ap3.1 被重放击破 → Nonce;ap5.0 被中间人击破 → 证书
  • 加密不能防重放——这是本讲最重要的单条洞察。

十、自测答案

1. 机密性、完整性、认证、可用性。真实问题:早期 WEP(第 25 讲)加密了内容但完整性保护极弱(用 CRC-32 而非 MAC),攻击者可以在不解密的情况下翻转密文中的特定比特,造成明文中可预测的改变,并相应修正 CRC——从而在保持"加密"的同时篡改数据包。

2. ECB 对每个分组独立加密,相同的明文分组必然产生相同的密文分组,因此明文的结构完全泄露(著名的"ECB 企鹅"图能透过密文看出原图轮廓)。AEAD(带关联数据的认证加密)指同时提供机密性和完整性/认证的加密模式,如 AES-GCM、ChaCha20-Poly1305;它把加密和认证绑定在一个原语中,从 API 层面杜绝了"只加密忘了认证"这类错误。

3. 根本问题是密钥分发:Alice 和 Bob 若从未见过面,如何约定一个只有他们知道的密钥?在对称密码的框架内这是循环的——约定密钥本身就需要一个安全信道。公钥密码通过一对数学上关联但无法互相推导的密钥解决:公钥可以完全公开发布,任何人用它加密的内容只有私钥持有者能解开,因而无需事先共享任何秘密

4.

n = 77,  z = 6 × 10 = 60
求 d 使 13d ≡ 1 (mod 60)
   13 × 37 = 481;  481 mod 60 = 1  ✓
⭐ d = 37

5. 因为 RSA 比 AES 慢 2–3 个数量级(公钥运算涉及大整数模幂)。加密一个几十 MB 的文件用 RSA 在性能上完全不可接受。此外 RSA 每次能加密的数据量受密钥长度限制。因此实际做法是混合加密:用 RSA(或 ECDH)只加密一个短的随机对称会话密钥,之后所有数据都用 AES 加密——公钥密码做密钥分发,对称密码做批量加密

6. 因为哈希函数是公开的、不含任何秘密。攻击者截获 (m, H(m)) 后,可以把 m 篡改为 m’,然后自己重新计算 H(m’),发送 (m’, H(m’))。接收方的验证会完全通过。裸哈希只能检测随机的传输差错(等价于一个很强的校验和),无法对抗有意的篡改

7. MAC 使用双方共享的秘密,因此 Alice 和 Bob 都能生成合法的 MAC——Bob 无法向第三方证明某条消息一定是 Alice 发的(他自己也能造一条)。数字签名使用签名者的私钥,只有 Alice 拥有该私钥,因此只有她能生成,任何人都能用她的公钥验证。只有数字签名提供不可否认性(non-repudiation)。

8. 两个原因:① 性能——公钥运算慢,对 256 位的摘要做一次模幂远快于对 10 MB 的原文做运算;② 长度——签名长度固定且很短,与消息大小无关,便于传输和存储。(哈希的抗碰撞性保证了"签摘要"与"签原文"在安全上等价——若攻击者能找到同摘要的另一条消息,那是哈希函数被攻破,而非签名方案的问题。)

9. 被 ⭐ 重放攻击(replay attack) 击破。加密不能防它,是因为攻击者根本不需要理解密文的内容——她只需把那段密文原样录下来,在下一次认证时原样重放。接收方解密后得到的是完全正确的密码,认证通过。这揭示了一个关键认识:加密保护的是"内容不被读懂",而不是"消息不被复用"。防重放需要引入新鲜性(freshness),即 Nonce 或时间戳。

10. 因为 Bob 拿到的"Alice 的公钥"本身没有经过任何认证。攻击者 Trudy 可以同时对两边冒充:对 Bob 出示自己的公钥并声称是 Alice 的(她能用自己的私钥正确签署 Bob 发来的 nonce),对 Alice 同样冒充 Bob。双方的认证都"成功",但所有流量都经过 Trudy。最终解法是证书:Bob 不接受裸公钥,只接受由可信 CA 用其私钥签名的证书,而 CA 的公钥是预置在系统中的(信任的起点不能从网络获取)。这条链条构成的完整协议,就是第 28 讲的 TLS 握手。