RSA 攻击讲解—从数学原理到实战利用
RSA 基础回顾
RSA 的安全性基于大整数分解难题(IFP, Integer Factorization Problem)。密钥生成:
- 选两个大素数 p, q
- n = p × q
- φ(n) = (p-1)(q-1)
- 选 e 满足 1 < e < φ(n) 且 gcd(e, φ(n)) = 1
- d = e⁻¹ mod φ(n)
公钥 (n, e),私钥 (n, d)。加密 c = m^e mod n,解密 m = c^d mod n。
RSA 本身的数学是安全的,但实现和使用中的错误会导致各种攻击。CTF 中的 RSA 题几乎都是在考这些攻击方法。
攻击 1:小模数分解(n 太小)
当 n 的位数不够(如 256 位以下),可以直接用工具分解:
1 | # 在线分解 |
Python 实现:
1 | from sympy import factorint |
CTF 中 n < 512 位基本都可以直接分解,512-1024 位需要看具体情况。
攻击 2:低加密指数攻击(e 太小)
当 e = 3 且明文 m 较小时,m^e < n,此时密文 c = m^e 没有取模效果,直接开 e 次方即可:
1 | from gmpy2 import iroot |
如果 m^e > n 但差距不大,可以用 Coppersmith 攻击(见攻击 6)。
低指数广播攻击(Håstad’s Broadcast Attack)
当同一个明文用相同的小 e 加密,但用不同的 n 加密至少 e 次时,可以用中国剩余定理(CRT)恢复明文:
1 | from sympy.ntheory.modular import crt |
原理:m^3 < n1×n2×n3(因为 m < n_i),所以 CRT 结果就是 m^3 的精确值。
攻击 3:共模攻击(Common Modulus)
当两个用户使用相同的 n 但不同的 e1, e2 加密同一个明文时:
c1 = m^e1 mod n
c2 = m^e2 mod n
如果 gcd(e1, e2) = 1,存在 a, b 使得 a×e1 + b×e2 = 1(扩展欧几里得算法),则:
m = c1^a × c2^b mod n
1 | from gmpy2 import gcdext, invert |
攻击 4:Wiener 攻击(d 太小)
当私钥指数 d 太小(d < n^0.25 / 3)时,Wiener 攻击可以通过连分数展开从公钥 (n, e) 恢复 d。
原理:d/e 是 φ(n)/e 的一个连分数收敛项,而 φ(n) ≈ n,所以可以通过 e/n 的连分数展开找到 d。
1 | from sympy import continued_fraction_convergents, continued_fraction_iterator |
Wiener 攻击的扩展:Boneh-Durfee 攻击可以在 d < n^0.292 时恢复 d,但实现更复杂(需要格基约减)。
攻击 5:p 和 q 接近(Fermat 分解)
当 p 和 q 非常接近时,n = p×q 可以用 Fermat 分解法快速分解。
原理:设 a = ceil(sqrt(n)),则 n = a² - b² = (a-b)(a+b),其中 p = a-b, q = a+b。p 和 q 越接近,b 越小,需要的迭代次数越少。
1 | from gmpy2 import isqrt, is_square |
当 |p-q| < n^0.25 时,Fermat 分解非常快。
攻击 6:Coppersmith 攻击
Coppersmith 攻击是 RSA 攻击中最强大的工具之一,由 Don Coppersmith 于 1996 年提出。它可以在已知多项式的小根时,通过格基约减(LLL 算法)恢复根。
场景 1:已知明文高位(明文中的 Coppersmith)
当知道明文 m 的高位部分(如 m = known_prefix + x,其中 x 很小),可以构造多项式 f(x) = (known_prefix + x)^e - c mod n,求 f(x) 的小根。
1 | # 使用 sage math |
场景 2:低指数相关消息攻击
当 e=3 且两个明文 m1, m2 满足 m2 = m1 + b(b 已知),可以用 Coppersmith 恢复 m1。
场景 3:部分密钥泄露攻击
当知道 d 的一部分比特(如低位或高位),可以用 Coppersmith 恢复完整的 d。
Coppersmith 攻击的核心是 LLL 格基约减算法,把多项式求根问题转化为格中的短向量问题。这是 CTF RSA 题中最常考的高级攻击。
攻击 7:CRT 实现错误
RSA 解密通常用 CRT(中国剩余定理)加速:
m_p = c^(d mod (p-1)) mod p
m_q = c^(d mod (q-1)) mod q
m = CRT(m_p, m_q)
如果 CRT 实现有错误(如 Garner 算法中的符号错误),可以通过一个错误的解密结果分解 n:
- 如果 m_p 正确但 m_q 错误,则 gcd(m - m_correct, n) = p
- 更常见的:错误解密结果 m_wrong,gcd(m_wrong - m_correct, n) 可以分解 n
1 | from math import gcd |
攻击 8:侧信道攻击
在实际环境中,RSA 实现可能受到侧信道攻击:
- 计时攻击:测量解密时间差异,恢复 d 的比特(Kocher 攻击)
- 功耗分析:通过功耗轨迹恢复密钥(DPA / CPA)
- 故障注入:在解密过程中注入故障,利用错误结果分解 n(Bellcore 攻击)
CTF 中偶尔会出现侧信道相关的题目,通常是给一组计时数据或功耗轨迹,需要写脚本分析。
攻击 9:填充预言机攻击(Padding Oracle)
当 RSA 使用 PKCS#1 v1.5 填充且服务器会返回”填充是否正确”的信息时,可以用 Bleichenbacher 攻击逐步恢复明文。
攻击原理:构造大量密文,根据服务器返回的填充正确/错误信息,逐步缩小明文的范围,最终恢复完整明文。
1 | # Bleichenbacher 攻击简化框架 |
攻击 10:其他常见 CTF 考点
模逆不存在(gcd(e, φ(n)) != 1)
当 e 和 φ(n) 不互素时,d 不存在。此时如果 gcd(e, φ(n)) = g,可以:
- 先求 c^(e/g)^(-1) mod n,得到 m^g
- 然后对 m^g 开 g 次方(如果 m 较小)
n 是素数幂(n = p^k)
如果 n = p^k(k > 1),φ(n) = p^(k-1)(p-1),可以直接计算 d。
多个素数(n = p×q×r…)
如果 n 是多个素数的乘积,φ(n) = ∏(p_i - 1),分解后正常计算。
明文就是 flag 的某种编码
有时候不需要攻击,直接:
- c 转 hex 转 ASCII 就是 flag
- n 或 e 中隐藏了 flag(LSB 隐写)
- 公钥文件中注释里有 flag
实战工具
RsaCtfTool
一站式 RSA CTF 工具,自动检测并执行各种攻击:
1 | git clone https://github.com/RsaCtfTool/RsaCtfTool |
支持的攻击:factordb、wiener、boneh_durfee、smallq、fermat、londahl、common_modulus、hastad、coppersmith 等。
SageMath
高级 RSA 攻击(Coppersmith、格基约减)基本都需要 SageMath:
1 | # 安装 |
yafu / msieve
大整数分解工具:
1 | yafu 'factor(123456...)' |
CTF 解题流程
1 | 拿到 RSA 题 |
总结
RSA 的数学本身是安全的,但 CTF 中的 RSA 题几乎都是在考实现和使用中的错误。从小模数分解、低指数攻击,到 Wiener 攻击、Coppersmith 攻击,每一种攻击都对应着一种特定的密钥生成或使用错误。
掌握 RSA 攻击需要:
- 数论基础:欧拉定理、中国剩余定理、连分数、格基约减
- 攻击方法库:记住每种攻击的适用条件和原理
- 工具熟练度:RsaCtfTool、SageMath、yafu 的使用
- 数学直觉:看到 n、e、c 的特征,能快速判断可能的攻击方向
RSA 是 CTF 密码学方向的入门必修课,也是实际密码学安全的重要内容。理解这些攻击,不仅能做 CTF 题,也能在实际工程中避免这些致命的实现错误。










