高级 #crypto#cryptanalysis#attack
密码分析
密码分析(Cryptanalysis)是研究如何破解密码系统的科学——从频率分析破解古典密码到侧信道攻击窃取现代密钥,攻防对抗推动密码学发展
🕵️ 攻防对抗——密码学进步的动力
密码学的每一次进步,都来自一次成功的”破解”。
古典密码 → 被频率分析破解 → 催生了维吉尼亚密码
维吉尼亚 → 被 Kasiski 破解 → 催生了更复杂的机械密码
Enigma → 被图灵破解 → 催生了现代密码学
DES → 被暴力破解 → 催生了 AES
MD5/SHA-1→ 被碰撞攻击破解→ 催生了 SHA-256/3
RSA → 量子 Shor 算法威胁 → 催生了后量子密码
密码分析(Cryptanalysis) 就是”攻击密码系统的科学”——不是搞破坏,而是发现密码系统中的弱点,推动密码学向前发展。
📐 一个核心原则:密码系统应该是公开的——安全性只依赖密钥的保密性,不依赖算法的保密性(Kerckhoffs 原则)。
📊 攻击者的能力——四种模型
| 攻击类型 | 攻击者知道什么 | 类比 |
|---|---|---|
| 唯密文攻击 | 只截获了一些密文 | 偷看一封信,但看不懂 |
| 已知明文攻击 | 密文 + 对应的部分明文 | 知道”今天天气”加密成了”XXXYYY” |
| 选择明文攻击 | 可以让加密任意选择的明文 | 拿任意文件让系统签名 |
| 选择密文攻击 | 可以让解密任意选择的密文 | 拿任意密文让系统解密看结果 |
攻击难度:唯密文 > 已知明文 > 选择明文 > 选择密文
攻击者掌握的信息越多(选择能力越强)→ 攻击越容易
一个好的密码算法,需要能抵抗"选择明文攻击"。
🔧 经典攻击方法
① 暴力破解(Brute Force)
尝试所有可能的密钥——最简单也最”笨”的方法。
# 暴力破解对密钥长度的敏感性
# 假设每秒尝试 10⁹ 个密钥
keys = {
"DES (56位)": 2**56, # 约 2 年
"AES-128 (128位)": 2**128, # 约 10²⁰ 年
"AES-256 (256位)": 2**256, # 宇宙年龄都远远不够
}
# 所以:128 位的密钥,暴力破解就已经不可行了
② 频率分析(Frequency Analysis)
利用语言的统计特性——英文中最常见的字母是 E,其次是 T、A、O……
# 对单表替换密码的频率分析
cipher = "KHOOR ZRUOG" # "HELLO WORLD" 用密钥 3 加密
# 统计密文中每个字母的出现次数
from collections import Counter
freq = Counter(cipher.replace(" ", ""))
# 密文中出现最多的字母 → 大概率是 E 加密后的结果
# KHOOR 中 O 出现 3 次 → O 很可能是 E → O-E 位移 10
# 验证:H(7)+10=R(17) → 确实!密钥是 10
③ 中间相遇攻击(Meet-in-the-Middle)
针对”双重加密”的攻击:
# 如果 E1 和 E2 是两个不同的加密算法
# 双重加密:C = E2(E1(M, K1), K2)
# 中间相遇攻击:
# 从左边:尝试所有 K1,记录 E1(M, K1)
# 从右边:尝试所有 K2,记录 D2(C, K2)
# 找匹配 → 同时破解了 K1 和 K2
# 复杂度从 2^(n+m) 降至 2^(max(n,m)+1)
这就是为什么 3DES(三次 DES)的实际安全性只有 112 位,而不是 168 位。
⚡ 侧信道攻击——不破解算法,破解实现
侧信道攻击(Side-Channel Attack) 不攻击密码算法本身——而是利用密码实现的物理泄露。
# ❌ 不安全的实现——比较时间是变量
def compare_password(input, stored):
for i in range(len(stored)):
if input[i] != stored[i]:
return False # 在第一个不同的字符就返回了
time.sleep(0.01) # 每个字符比对耗时不同!
return True
# 攻击者:测量每次返回的时间差异
# 第一个字符对了 → 耗时 > 0.01s
# 第一个字符错了 → 耗时 < 0.01s
# → 逐位猜出密码!这就是"时序攻击(Timing Attack)"
# ✅ 安全的实现——固定时间比较
def constant_time_compare(a, b):
if len(a) != len(b):
return False
result = 0
for i in range(len(a)):
result |= ord(a[i]) ^ ord(b[i]) # 始终比较所有位
return result == 0
常见的侧信道攻击
| 攻击 | 利用什么 | 经典案例 |
|---|---|---|
| 时序攻击 | 加密时间与密钥/数据的相关性 | 远程猜出 RSA 私钥 |
| 功耗分析 | CPU 执行不同指令的功耗不同 | 从智能卡芯片读出 AES 密钥 |
| 电磁攻击 | 芯片工作时辐射电磁信号 | 从手机中提取密钥 |
| 缓存攻击 | 缓存命中率的差异 | Meltdown/Spectre 漏洞 |
| 声学攻击 | 风扇、电容的声波泄露 | 从打印机声音还原打印内容 |
🛡️ 如何防御?
| 攻击 | 防御 |
|---|---|
| 暴力破解 | 足够长的密钥(≥128 位) |
| 频率分析 | 用现代分组密码(不是单表替换) |
| 时序攻击 | 常数时间算法 |
| 缓存攻击 | 清除敏感数据后的缓存、不使用共享内存 |
| 量子攻击 | 后量子密码(Kyber、Dilithium) |
📝 小结
| 概念 | 一句话 |
|---|---|
| 密码分析 | 研究如何破解密码系统的科学 |
| 攻击模型 | 唯密文 < 已知明文 < 选择明文 < 选择密文 |
| 暴力破解 | 尝试所有密钥——密钥 ≥ 128 位后不可行 |
| 频率分析 | 利用语言统计特性——破解替换密码 |
| 侧信道攻击 | 利用物理泄露——不破解算法,破解实现 |
| Kerckhoffs 原则 | 密码系统安全性只依赖密钥保密性 |
🎯 思考题:Kerckhoffs 原则说”算法应该是公开的,安全性只依赖密钥”——这和”安全通过隐蔽”(Security by Obscurity,把算法藏起来)有什么根本不同?为什么前者是好的设计原则,后者不是?
为什么先学这个? 密码分析是密码学板块的最后一节。至此密码学 9 个节点全部完成。你可以进入其他板块继续探索。