本文最后更新于39 天前,其中的信息可能已经过时,如有错误可以直接在文章下留言
题目附件给了一下数据
e = 65537
n = 248254007851526241177721526698901802985832766176221609612258877371620580060433101538328030305219918697643619814200930679612109885533801335348445023751670478437073055544724280684733298051599167660303645183146161497485358633681492129668802402065797789905550489547645118787266601929429724133167768465309665906113
dp = 905074498052346904643025132879518330691925174573054004621877253318682675055421970943552016695528560364834446303196939207056642927148093290374440210503657
c = 140423670976252696807533673586209400575664282100684119784203527124521188996403826597436883766041879067494280957410201958935737360380801845453829293997433414188838725751796261702622028587211560353362847191060306578510511380965162133472698713063592621028959167072781482562673683090590521214218071160287665180751
题目给的dp,而没有给RSA算法解密需要用的p和q,这里的n无法分解。
先看看什么是dp,当然还有dq
dp=d%(p-1)
dq=d%(q-1)
变换公式则有dp ≡ d (mod(p-1))
根据同余的性质有 e·dp ≡ ed (mod(p-1))
则ed = k1(p-1) + e·dp
由RSA的加密原理可知φ(n) = (p-1)(q-1)、ed ≡ 1 (mod φ(n))
则ed ≡ 1 (mod (p-1)(q-1))
ed = k2(p-1)(q-1) + 1
联立以上两个等式,则有
k2(p-1)(q-1) + 1 = k1(p-1) + e·dp
e·dp = (k2(q-1)-k1)(p-1) +1
我们令X = (k2(q-1)-k1)
则e·dp = X(p-1) +1
根据取模运算的性质,dp<(p-1)
且由等式e·dp = X(p-1) +1可得X<e,且X>0,即X∈(0,e)
在这个等式当中我们已知e,dp,再得到X即可算出p,那就能得到q了。
变换上面的等式可得 (e·dp-1)/X = (p-1)
那么就可以得到X需要满足条件(e·dp-1)%X = 0
p = ((e·dp-1)/X) + 1
由n=pq,又得n % p = 0
故我们可以得出X必须满足两个等式,即
(e·dp-1)%X = 0
n % (((e·dp-1)/X) + 1) = 0
且X的范围并不算特别大,我们就可以通过爆破得到X。
解题脚本如下
from Crypto.Util.number import *
import gmpy2
e = 65537
n = 248254007851526241177721526698901802985832766176221609612258877371620580060433101538328030305219918697643619814200930679612109885533801335348445023751670478437073055544724280684733298051599167660303645183146161497485358633681492129668802402065797789905550489547645118787266601929429724133167768465309665906113
dp = 905074498052346904643025132879518330691925174573054004621877253318682675055421970943552016695528560364834446303196939207056642927148093290374440210503657
c = 140423670976252696807533673586209400575664282100684119784203527124521188996403826597436883766041879067494280957410201958935737360380801845453829293997433414188838725751796261702622028587211560353362847191060306578510511380965162133472698713063592621028959167072781482562673683090590521214218071160287665180751
for i in range(1, e):
if (dp * e - 1) % i == 0:
if (n % ((dp * e - 1) // i + 1)) == 0:
p = (dp * e - 1) // i + 1
q = n // p # 注意都是整除
phi_n = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi_n)
m = pow(c, d, n)
print(long_to_bytes(m))
#输出b'flag{wow_leaking_dp_breaks_rsa?_98924743502}'
脚本也可以作为解dp泄露的RSA题目的通用脚本,这里必须是整除运算的原因也很好理解,如果用/的话结果会是浮点数,但是浮点数精度有限,会造成运算的错误
所以flag就是flag{wow_leaking_dp_breaks_rsa?_98924743502}