朝花夕拾(一)0CTF 2016

回顾一些曾经的高质量比赛。

rsa

给了PEM文件(DER证书的base-64编码机制),可以很容易得到e=3,n比较小直接分解即可,但phi是e的倍数,所以无法求d需要在有限域下开根然后crt组合。

from Crypto.Util.number import *

fac = [26440615366395242196516853423447, 27038194053540661979045656526063, 32581479300404876772405716877547]
e = 3
c = 2485360255306619684345131431867350432205477625621366642887752720125176463993839766742234027524

root = []
for p in fac:
    P.<a>=PolynomialRing(Zmod(p),implementation='NTL')
    f=a^e-c
    mps=f.monic().roots()
    root.append(mps)

print(root)
for i,i_ in root[0]:
    for j,j_ in root[1]:
        for k,k_ in root[2]:
            m = crt([ZZ(i),ZZ(j),ZZ(k)],[fac[0],fac[1],fac[2]])
            flag = long_to_bytes(m)
            if b'ctf' in flag:
                print(flag)
                break

equation

题目给了一个flag.enc和一张半遮掩的私钥信息图:

image

参考RSA 公私钥 pem 文件解析,可以得到以下信息:
\(d_p,d_q,q_{low},q^{-1}\;mod\;p\)\(q_{low}\)是指的q低200位。首先可以通过类似dp泄露的攻击手法求q:
\(d_qe=1+k(q-1)=>d_qe\equiv1+k(q_{low}-1)\;mod\;2^{200}\),显然k<e,所以直接爆破k。得到k之后q就出来了,而求p有所不同,\(qq^{-1}\equiv 1\;mod\;p\),因此\(qq^{-1}-1\)为p的倍数,如果能再找到一个p的倍数,求最大公因子就是p。根据费马小定理,\(a^{ed_p}\equiv1\;mod\;p\),进一步可能有\(a^{ed_p}\equiv1\;mod\;kp\),于是得到了第二个p的倍数,求出p解密即可。

from gmpy2 import *
from Crypto.Util.number import *

q_low = 0x3acf6684e41176a5b673056b9cd23bd832dc017a57509d471b
dp = 0x00d5a225c0d41b16699c4471570eecd3dd7759736d5781aa7710b31b4a46e441d386da1345bc97d1aa913f853f850f6d4684a80e6067fb71cf213b276c2cbaed59
dq = 0x1338c593d3b5428ce978bed7a553527155b3d138aeac084020c0c67f54b953015e55f60a5d31386505e02e6122dad7db0a05ecb552e448b347adc2c9170fa2f3
q_inv_mod_p = 0x00d5c8d6dc583ecdf3c321663ba32ae4ab1c9a2ded6702691993184209e93914f0d5adf415634788d5919d84a8d77429959d40fba47b29cf70b943124217c9a431
e = 0x10001
mod = 2 ** 200
# recover q
for k in range(e):
    if (dq * e) % mod == (1 + k * (q_low - 1)) % mod:
        print('k:',k)
        break

q = (dq * e - 1)//k + 1
print(q.bit_length())
# recover p

kp = gcd(q_inv_mod_p * q - 1,pow(2,e * dp,q_inv_mod_p * q - 1) - 2)
if int(kp).bit_length() > 500:
    print(kp)

p = kp//10
print(p.bit_length())

c = open('flag.enc','rb').read()
c = bytes_to_long(c)
phi = (p-1) * (q-1)
d = invert(e,phi)
print(long_to_bytes(pow(c,d,p*q)))

peoples-square

posted @ 2023-03-04 13:08  ZimaB1ue  阅读(97)  评论(0编辑  收藏  举报