[NewStarCTF 2023 公开赛道]eazy_crt

MagicianV RSA 题解(WP)

题目源码:

复制代码
from Crypto.Util.number import *
from secret import flag, p, q
from hashlib import *
import random

assert 'flag{' + md5(str(p).encode()).hexdigest() + '}' == flag
assert isPrime(p), isPrime(q)
assert p.bit_length() == 1024, q.bit_length() == 1024

m = random.getrandbits(400)
e = 65537
d = inverse(e, (p - 1) * (q - 1))
r1, r2, r3 = getPrime(20), getPrime(20), getPrime(10)

dp, dq = d % (p - 1), d % (q - 1)
Sp, Sq = pow(m + getPrime(10), dp, r1 * p), pow(m, dq, r2 * q)
s1, s2 = pow(m, dp % (r1 - 1), r1), pow(m, dq % (r2 - 1), r2)

S_ = Sq + (q * r2) * (int(inverse(q * r2, p * r1)) * (Sp - Sq) % (p * r1))

c1, c2 = (S_ - s1 + 1) % r1, (S_ - s2 + 1) % r2

gamma = (r3 * c1 + (2 ** 10 - r3) * c2) // (2 ** 10)

S = pow(S_, gamma, p * q)

给出了:

  • m

  • n = p*q

  • S_

  • S

目标:

复制代码
flag = flag{md5(str(p))}

所以核心是:

分解 n


一、观察关键点

最关键的一句:

复制代码
S = pow(S_, gamma, n)

即:

复制代码
S ≡ S_^gamma mod n

这里:

复制代码
gamma = (r3 * c1 + (2 ** 10 - r3) * c2) // (2 ** 10)

其中:

  • r3 是 10 bit 素数

  • c1 < r1

  • c2 < r2

  • r1,r2 是 20 bit 素数

因此:

gamma 很小

数量级:

复制代码
gamma < 2^20

二、爆破 gamma

因为:

复制代码
S = S_^gamma mod n

而:

复制代码
gamma < 2^20

所以直接暴力:

复制代码
for g in range(2**20):
    if pow(S_, g, n) == S:
        print(g)

得到:

复制代码
gamma = 337756

三、利用 gamma 分解 n

由于:

复制代码
S ≡ S_^gamma mod n

则:

复制代码
S_^gamma - S ≡ 0 mod n

即:

复制代码
n | (S_^gamma - S)

这意味着:

复制代码
pow(S_, gamma, n) - S

n 存在巨大关系。

进一步考虑:

RSA 中常用:

复制代码
gcd(a^k - b, n)

去提取因子。

于是尝试:

复制代码
g = gcd(pow(S_, gamma) - S, n)

即可得到:

复制代码
p

随后:

复制代码
q = n // p

完成分解。


四、计算 flag

题目:

复制代码
flag = flag{md5(str(p))}

因此:

复制代码
from hashlib import md5

flag = "flag{" + md5(str(p).encode()).hexdigest() + "}"

得到:

复制代码
flag{b40ea076da8c73572ae5d067aa0fc22e}

五、完整 EXP

复制代码
from Crypto.Util.number import *
from hashlib import md5
from math import gcd

m = ...
n = ...
S_ = ...
S = ...

for gamma in range(1 << 20):
    if pow(S_, gamma, n) == S:
        print("[+] gamma =", gamma)
        break

x = pow(S_, gamma) - S
p = gcd(x, n)
q = n // p

print("[+] p =", p)
print("[+] q =", q)

flag = "flag{" + md5(str(p).encode()).hexdigest() + "}"
print(flag)

六、题目考点

这题核心是:

小指数泄露

由于:

复制代码
gamma < 2^20

导致:

复制代码
S = S_^gamma mod n

可以直接离散爆破。

随后通过:

复制代码
gcd(pow(S_, gamma) - S, n)

恢复 RSA 因子。

本质属于:

RSA 参数构造失误 + 小指数攻击

相关推荐
m0_631529821 小时前
MySQL如何解决锁等待超时异常_捕获MySQL Error 1205错误
jvm·数据库·python
qq_392690661 小时前
如何防止MongoDB副本集被误初始化_副本集名称(replSetName)锁定
jvm·数据库·python
小短腿的代码世界1 小时前
QCefView深度解析:在Qt中嵌入Chromium的架构设计与性能优化实战
开发语言·qt·性能优化
m0_748554811 小时前
Go 中调用纯函数的并发安全性详解
jvm·数据库·python
小短腿的代码世界1 小时前
Qt反射机制深度解析:从QMetaObject到运行时类型推导的底层密码
开发语言·qt
水木流年追梦1 小时前
【python因果库实战26】逆概率加权模型1
开发语言·python·算法·leetcode
m0_740653221 小时前
SQL如何利用聚合函数进行库存预测_历史数据分组汇总
jvm·数据库·python
2301_787312431 小时前
如何利用宝塔面板设置网站限流策略_防止恶意高并发请求
jvm·数据库·python
m0_733565461 小时前
SQL如何统计各分组下指标的波动率_STDDEV聚合函数应用
jvm·数据库·python