CTF实战:用Python脚本5分钟搞定RSA共模攻击(附SWPUCTF 2021新生赛真题解析)
当你第一次在CTF比赛中遇到RSA共模攻击题目时,可能会感到无从下手。别担心,本文将带你从零开始,用Python脚本快速解决这类问题。我们以SWPUCTF 2021新生赛的crypto2题目为例,手把手教你编写攻击脚本,让你在5分钟内搞定这道题。
1. 理解RSA共模攻击的基本原理
RSA共模攻击(Common Modulus Attack)是指当两个不同的公钥使用相同的模数n时,攻击者可以利用这两个公钥对同一明文进行加密的密文来恢复原始明文。这种情况在实际应用中很少见,但在CTF比赛中却很常见。
关键条件 :
- 相同的模数n
- 两个不同的公钥指数e1和e2
- 对应的密文c1和c2
- e1和e2互质(gcd(e1, e2) = 1)
攻击的核心思想是利用扩展欧几里得算法找到满足e1 s + e2 t = 1的整数s和t,然后通过计算(c1^s * c2^t) mod n来恢复明文m。
2. 准备Python环境
在开始编写攻击脚本前,我们需要准备以下Python库:
from Crypto.Util.number import long_to_bytes
import gmpy2
-
gmpy2:用于高效的大数运算 -
Crypto.Util.number:提供数字和字节串之间的转换功能
如果你还没有安装这些库,可以使用pip安装:
pip install pycryptodome gmpy2
3. 分析SWPUCTF 2021新生赛crypto2题目
题目给出了以下参数:
flag1 = 100156221476910922393504870369139942732039899485715044553913743347065883159136513788649486841774544271396690778274591792200052614669235485675534653358596366535073802301361391007325520975043321423979924560272762579823233787671688669418622502663507796640233829689484044539829008058686075845762979657345727814280
flag2 = 86203582128388484129915298832227259690596162850520078142152482846864345432564143608324463705492416009896246993950991615005717737886323630334871790740288140033046061512799892371429864110237909925611745163785768204802056985016447086450491884472899152778839120484475953828199840871689380584162839244393022471075
e1 = 3247473589
e2 = 3698409173
n = 103606706829811720151309965777670519601112877713318435398103278099344725459597221064867089950867125892545997503531556048610968847926307322033117328614701432100084574953706259773711412853364463950703468142791390129671097834871371125741564434710151190962389213898270025272913761067078391308880995594218009110313
4. 编写攻击脚本
现在,我们一步步编写攻击脚本:
4.1 计算贝祖系数
首先,我们需要使用扩展欧几里得算法找到满足e1 s + e2 t = 1的整数s和t:
gcd, s, t = gmpy2.gcdext(e1, e2)
这里,
gcdext
函数返回三个值:
- gcd:e1和e2的最大公约数(应该是1,因为题目保证e1和e2互质)
- s和t:满足e1 s + e2 t = gcd的贝祖系数
4.2 处理负指数
由于s或t可能为负数,我们需要处理这种情况。负数指数意味着我们需要先计算模逆元:
if s < 0:
s = -s
c1 = gmpy2.invert(c1, n)
elif t < 0:
t = -t
c2 = gmpy2.invert(c2, n)
4.3 计算明文
现在,我们可以计算明文m了:
m = (pow(c1, s, n) * pow(c2, t, n)) % n
4.4 完整脚本
将以上步骤组合起来,我们得到完整的攻击脚本:
from Crypto.Util.number import long_to_bytes
import gmpy2
# 题目给出的参数
c1 = 100156221476910922393504870369139942732039899485715044553913743347065883159136513788649486841774544271396690778274591792200052614669235485675534653358596366535073802301361391007325520975043321423979924560272762579823233787671688669418622502663507796640233829689484044539829008058686075845762979657345727814280
c2 = 86203582128388484129915298832227259690596162850520078142152482846864345432564143608324463705492416009896246993950991615005717737886323630334871790740288140033046061512799892371429864110237909925611745163785768204802056985016447086450491884472899152778839120484475953828199840871689380584162839244393022471075
e1 = 3247473589
e2 = 3698409173
n = 103606706829811720151309965777670519601112877713318435398103278099344725459597221064867089950867125892545997503531556048610968847926307322033117328614701432100084574953706259773711412853364463950703468142791390129671097834871371125741564434710151190962389213898270025272913761067078391308880995594218009110313
# 计算贝祖系数
gcd, s, t = gmpy2.gcdext(e1, e2)
# 处理负指数
if s < 0:
s = -s
c1 = gmpy2.invert(c1, n)
elif t < 0:
t = -t
c2 = gmpy2.invert(c2, n)
# 计算明文
m = (pow(c1, s, n) * pow(c2, t, n)) % n
# 输出结果
print(long_to_bytes(m))
5. 运行脚本获取flag
运行上述脚本,你将得到flag:
b'NSSCTF{RSA_Common_Modulus_Attack}'
6. 常见问题与调试技巧
在实际操作中,你可能会遇到一些问题。以下是一些常见问题及其解决方法:
-
gmpy2安装失败 :
-
尝试使用
pip install gmpy2-wheel安装预编译的版本 -
或者使用
pip install gmpy2==2.0.8安装旧版本
-
尝试使用
-
脚本运行但得不到正确结果 :
- 检查输入的参数是否正确
- 确保e1和e2确实互质(gcd(e1, e2) == 1)
- 验证n是否确实是两个大素数的乘积
-
性能优化 :
- 对于非常大的数,可以考虑使用多线程或更高效的算法
-
使用
pow的三参数形式(pow(a,b,c))比先计算a^b再取模更高效
7. 扩展应用
掌握了RSA共模攻击后,你可以在以下场景中应用这一技术:
- CTF比赛中类似的RSA题目
- 分析使用相同模数的多个RSA公钥
- 理解RSA实现中的安全陷阱
在实际的CTF比赛中,RSA共模攻击题目可能会有一些变种,比如:
- 隐藏部分参数,需要你自己推导
- 结合其他加密方式
- 使用不标准的编码方式
记住,理解原理比记住脚本更重要。掌握了基本原理后,你就能灵活应对各种变种题目。
639

被折叠的 条评论
为什么被折叠?



