🏠 总目录📚 本教程 01 · 到底在保护什么
📑 本页目录(点开跳转)

01 · 密码学到底在保护什么

22 分钟 | ⭐ 建立整门学科的坐标系


🎯 一句话

大多数人以为密码学 = 加密 = 「让别人看不懂」。 但「看不懂」只是四个目标里的一个,而且经常是最不重要的那个。


🧱 一、四个安全目标(必须分开谈)

目标 一句话 没有它会怎样
机密性 Confidentiality 别人看不到内容 你的密码被中间人读走
完整性 Integrity 内容没被改过 转账金额从 100 被改成 10000
认证 Authentication 对方确实是他 你在和钓鱼网站聊天
不可否认 Non-repudiation 事后赖不掉 签了合同说"不是我签的"

⚠️ 关键:加密只提供第一个

   一个只加密、不做认证的系统:

   Alice ──[加密的转账指令]──► Bank
                 ▲
                 │ 攻击者看不懂内容 ✅ 机密性有了
                 │ 但他可以【翻转密文里的某几个 bit】
                 │ 然后金额就变了 ❌ 完整性没有

🔑 这是整个领域最重要、也最常被忽略的一句话加密(Encryption)不提供完整性。

很多真实事故的根因就是有人以为"我都加密了还能怎样"。 🔗 第 11 章会讲怎么把两者正确地组合起来 —— 顺序还不能弄错

💡 一个具体的例子:为什么加密挡不住篡改

   用流密码加密(第 5 章):C = M ⊕ 密钥流

   攻击者知道消息格式是 "转账金额:00100"
   他不知道密钥流,但他可以:

       C' = C ⊕ Δ         (Δ 是他构造的一串 bit)

   接收方解密得到:
       C' ⊕ 密钥流 = (M ⊕ 密钥流 ⊕ Δ) ⊕ 密钥流 = M ⊕ Δ  ⭐

   → 攻击者【完全不需要解密】,就能对明文做可控的修改

💥 这不是理论:这类"比特翻转攻击"打穿过真实的支付系统和 cookie 认证。


🔓 二、Kerckhoffs 原则:算法必须公开

系统的安全性应当只依赖于密钥的保密,而不依赖于算法的保密。

   ❌ 隐蔽式安全(Security through obscurity):
      "我自己设计了一套加密算法,没人知道它怎么工作,所以很安全"

   ✅ Kerckhoffs 原则:
      算法完全公开、任人研究,安全性只来自那把密钥

为什么必须这样

理由 说明
算法迟早会泄露 反编译、内部人员、逆向工程 —— 密钥能换,算法不能换
公开才能被审查 没被全世界攻击过的算法,"没人攻破"只是"没人看过"
自己设计必翻车 这不是谦虚。专业密码学家设计的方案也经常在几年后被攻破

🔑 推论,请记住永远不要自己设计密码算法,也不要自己实现标准算法。 用经过审计的库(libsodium、OpenSSL、你的语言的标准库)。

💡 为什么"自己实现标准算法"也不行:即使算法是对的, 实现也可能泄露侧信道信息(运行时间、功耗、缓存命中)—— 见下面第四节。


🎭 三、威胁模型:你在防谁?

"安全"这个词没有绝对含义 —— 必须先说清防的是谁、他能做什么。

   攻击者能力从弱到强:

   COA  仅知密文     只能看到密文
    ⊂
   KPA  已知明文     知道一些「明文-密文」对
    ⊂
   CPA  选择明文 ⭐  能让你加密【他挑的】任意明文
    ⊂
   CCA  选择密文 ⭐  还能让你解密【他挑的】密文(挑战密文除外)

💡 为什么 CPA 不是"过分"的假设

看起来"攻击者凭什么能让你加密他挑的内容"?但现实中这太常见了

场景 攻击者怎么做到的
你的服务器自动加密收到的请求 他直接发请求
HTTPS 里浏览器加密他控制的 URL 参数 他发个链接给你点
加密的日志系统 他触发一个会被记录的事件
加密的数据库字段 他注册一个用户名

🔑 所以现代方案的最低门槛就是 IND-CPA第 8 章会精确定义)。 达不到 CPA 安全的方案,直接出局。

💡 CCA 又是什么场景

   攻击者能拿到「解密结果」的场景:

   · 服务器解密后,如果格式不对会返回一个错误
     → 这个错误就泄露了解密的部分信息 ⭐
     → 这就是【padding oracle 攻击】的原理

   · 解密后的内容被显示在页面上
   · 解密失败和成功的【响应时间不同】

💥 真实事故:padding oracle 攻击曾打穿过 ASP.NET、Ruby on Rails、 以及大量使用 CBC 模式却不做认证的系统。 攻击者只靠"服务器返回的错误信息"就能完整解密任意密文。


🕰️ 四、还有一类攻击不在这个框架里:侧信道

   前面讨论的都是【攻击者只能看到输入输出】

   但真实设备会【漏出别的东西】:
   ├─ 运行时间   ← 比较密码时提前返回 = 泄露了对了几位 ⭐
   ├─ 功耗曲线   ← 能看出 RSA 在算平方还是乘法
   ├─ 电磁辐射
   ├─ 缓存命中   ← 著名的 AES 缓存计时攻击
   └─ 声音       ← 真的有论文用麦克风提取过密钥

最常见也最容易避免的一个:时间侧信道

# ❌ 危险:一旦有一位不同就立刻返回
def check(a, b):
    if len(a) != len(b): return False
    for x, y in zip(a, b):
        if x != y: return False        # ⭐ 提前返回 = 泄露信息
    return True

# ✅ 正确:恒定时间比较,不管哪里不同都跑完
import hmac
hmac.compare_digest(a, b)              # ⭐ 用标准库的

💡 为什么提前返回是致命的:攻击者反复提交猜测, 测响应时间就能一位一位地把正确值试出来 —— 从 256^32 次降到 256×32 次。


🧭 五、这一章该带走的坐标系

   拿到任何一个安全方案,问自己四个问题:

   ① 它提供【四个目标】里的哪几个?        ← 加密只给机密性
   ② 它假设攻击者有什么能力?(COA/CPA/CCA) ← 达不到 CPA 直接出局
   ③ 安全性依赖什么?                      ← 只能是密钥,不能是算法保密
   ④ 实现层面有没有侧信道?                ← 用恒定时间的标准库函数

🔑 这四个问题会贯穿整套教程。 后面每讲一个方案,都可以拿它们过一遍。


🔗 和站内其他章的关系

你可能已经知道的 这里的位置
https 的小锁 机密性 + 认证,第 18 章讲完整流程
"密码不要明文存" 那用的是哈希,第 9 章
区块链"不可篡改" 完整性,靠哈希链,第 20 章
电子签名的法律效力 不可否认性,第 17 章
智能体教程的沙箱与注入防护 同一种思维:假设对手是主动且聪明的

✅ 检查点

  1. 四个安全目标分别是什么?加密提供哪几个?
  2. 举例说明为什么"加密了"不等于"不能被篡改"。
  3. Kerckhoffs 原则说了什么?为什么算法必须公开?
  4. 为什么"自己实现标准算法"也不安全?
  5. CPA 攻击模型为什么不是过分的假设?举两个现实场景。
  6. padding oracle 攻击属于哪个攻击模型?它靠什么信息工作?
  7. 为什么密码比较必须用恒定时间函数?
👀 答案
  1. 机密性、完整性、认证、不可否认。加密只提供机密性这一个。
  2. 流密码下 C = M ⊕ 密钥流,攻击者构造 C' = C ⊕ Δ,接收方解密得到 M ⊕ Δ——完全不需要解密就能对明文做可控修改(比特翻转攻击)。
  3. 安全性应只依赖密钥的保密,不依赖算法的保密。因为①算法迟早泄露而密钥能换算法不能换 ②公开才能被全世界审查 ③自己设计必翻车。
  4. 因为即使算法逻辑正确,实现可能泄露侧信道信息——运行时间、功耗、缓存命中。
  5. 因为现实中攻击者太容易让你加密他选的内容:服务器自动加密收到的请求、浏览器加密他控制的 URL 参数、他注册一个用户名进加密的数据库字段、触发一条会被记录的日志。
  6. CCA(选择密文攻击)。它靠服务器返回的错误信息(padding 对不对)作为解密预言机,只用这一位信息就能完整解密任意密文。
  7. 因为提前返回会泄露"前几位对了",攻击者反复提交并测响应时间,能一位一位试出正确值——把 256³² 次降到 256×32 次。

🛑 可以停在这里

走神救援

四个安全目标:机密性(看不到)、完整性(没被改)、认证(确实是他)、不可否认(赖不掉)。⭐最重要的一句:加密只提供机密性,不提供完整性——流密码下攻击者构造 C'=C⊕Δ,接收方解出 M⊕Δ,完全不用解密就能可控篡改明文(比特翻转攻击,打穿过真实支付系统)。Kerckhoffs 原则:安全只能依赖密钥、不能依赖算法保密(密钥能换,算法不能换)→ 推论:永远不要自己设计密码算法,也不要自己实现标准算法(实现会泄露侧信道)。威胁模型 COA⊂KPA⊂CPA⊂CCA,⭐CPA 不是过分假设——服务器自动加密请求、浏览器加密你控制的URL参数、注册一个用户名,都是让对方加密你选的内容;达不到 IND-CPA 的方案直接出局CCA 的真实形态是 padding oracle——只靠"服务器返回的错误"就能完整解密,打穿过 ASP.NET 和 Rails。侧信道不在这个框架内:时间/功耗/缓存/声音;最常见的是比较密码时提前返回,必须用 hmac.compare_digest 这类恒定时间函数。坐标系四问:提供哪几个目标 / 假设攻击者什么能力 / 安全依赖什么 / 有没有侧信道。

下一节 👉 02-古典密码为什么全倒了.md

打卡记录保存在你的浏览器里,首页能看到总进度