从已知e高位推导出已知p高位

题目

  • ! CISCN2024初赛-OVO
from Crypto.Util.number import *
from secret import flag
nbits = 512
p = getPrime(nbits)
q = getPrime(nbits)
n = p * q
phi = (p-1) * (q-1)
while True:
    kk = getPrime(128)
    rr = kk + 2
    e = 65537 + kk * p + rr * ((p+1) * (q+1)) + 1
    if gcd(e, phi) == 1:
        break
m = bytes_to_long(flag)
c = pow(m, e, n)

e = e >> 200 << 200
print(f'n = {n}')
print(f'e = {e}')
print(f'c = {c}')

"""
n = 111922722351752356094117957341697336848130397712588425954225300832977768690114834703654895285440684751636198779555891692340301590396539921700125219784729325979197290342352480495970455903120265334661588516182848933843212275742914269686197484648288073599387074325226321407600351615258973610780463417788580083967
e = 37059679294843322451875129178470872595128216054082068877693632035071251762179299783152435312052608685562859680569924924133175684413544051218945466380415013172416093939670064185752780945383069447693745538721548393982857225386614608359109463927663728739248286686902750649766277564516226052064304547032760477638585302695605907950461140971727150383104
c = 14999622534973796113769052025256345914577762432817016713135991450161695032250733213228587506601968633155119211807176051329626895125610484405486794783282214597165875393081405999090879096563311452831794796859427268724737377560053552626220191435015101496941337770496898383092414492348672126813183368337602023823
"""

解题思路

  • 观察rr = kk + 2e = 65537 + kk * p + rr * ((p+1) * (q+1)) + 1这段代码
  • $e$ 近似 $(kk+2)*n$ ,所以 $e//n≈rr$
  • 化简 $e=65538+kkp+(kk+2)(n+p+q+1)=65538+kkp+kkn+kkp+kkq+kk+2n+2p+2*q+2$
  • 两边同时乘以 $p$ 再结合n=p*q化简 $ep=65538p+kkp2+kk*n*p+kk*p2+kkqp+kkp+2np+2p2+2*q*p+2*p=65538+kk*p2+(kk+2)(p^2+n*p+n+p)$
  • 最后得到 $ep=65538+kkp^2+rr((p+1)(n+p))$
  • 然后我们直接解这个方程, $p$ 相当于 $x$ 构造方程得 $f = ex-(65538+rr(n+1))*x + (kk+rr) * x^2 + rr * n$
  • 脚本类似[[已知d高位攻击(位数不变)]]不过求的是 $p$

解答

from Crypto.Util.number import *

def partial_p(p0, kbits, n):
    PR.<x> = PolynomialRing(Zmod(n))
    nbits = n.nbits()
    f = x + p0
    f = f.monic()
    roots = f.small_roots(X=2^(kbits), beta=0.4)
    if roots:
        x0 = int(roots[0])
        p = gcd(x0 + p0, n)
        return int(p)

def find_p(e, kbits, n):
    P.<x> = PolynomialRing(RealField(1000))
    f = e*x - (65538+rr*(n+1))*x + (kk+ rr) * x**2 + rr * n
    res = f.monic().roots()
    if res:
        for i in res:
            ph = int(i[0])
            p = partial_p(ph, kbits, n)
            if p and isPrime(p):
	            return p

n = 111922722351752356094117957341697336848130397712588425954225300832977768690114834703654895285440684751636198779555891692340301590396539921700125219784729325979197290342352480495970455903120265334661588516182848933843212275742914269686197484648288073599387074325226321407600351615258973610780463417788580083967
e = 37059679294843322451875129178470872595128216054082068877693632035071251762179299783152435312052608685562859680569924924133175684413544051218945466380415013172416093939670064185752780945383069447693745538721548393982857225386614608359109463927663728739248286686902750649766277564516226052064304547032760477638585302695605907950461140971727150383104
c = 14999622534973796113769052025256345914577762432817016713135991450161695032250733213228587506601968633155119211807176051329626895125610484405486794783282214597165875393081405999090879096563311452831794796859427268724737377560053552626220191435015101496941337770496898383092414492348672126813183368337602023823
rr = e // n
kk = rr - 2
p = find_p(e, 200, n)
if p:
    q = n // p
    e = 65537 + kk * p + rr * ((p+1) * (q+1)) + 1
    d = inverse(e, (p-1)*(q-1))
    print(long_to_bytes(pow(c, d, n)))
#flag{b5f771c6-18df-49a9-9d6d-ee7804f5416c}
from Crypto.Util.number import *  
  
n = 111922722351752356094117957341697336848130397712588425954225300832977768690114834703654895285440684751636198779555891692340301590396539921700125219784729325979197290342352480495970455903120265334661588516182848933843212275742914269686197484648288073599387074325226321407600351615258973610780463417788580083967  
e = 37059679294843322451875129178470872595128216054082068877693632035071251762179299783152435312052608685562859680569924924133175684413544051218945466380415013172416093939670064185752780945383069447693745538721548393982857225386614608359109463927663728739248286686902750649766277564516226052064304547032760477638585302695605907950461140971727150383104  
c = 14999622534973796113769052025256345914577762432817016713135991450161695032250733213228587506601968633155119211807176051329626895125610484405486794783282214597165875393081405999090879096563311452831794796859427268724737377560053552626220191435015101496941337770496898383092414492348672126813183368337602023823  
  
k=e//n-2  
tmp=65537+(k+2)*n+(k+2)+1  
R.<x>=PolynomialRing(RealField(1024))  
f=e*x-(2*(k+1)*x^2+(k+2)*n+tmp*x)  
res=f.roots()  
for root in res:  
    p_high=int(root[0])  
    RP.<x>=PolynomialRing(Zmod(n))  
    f1=x+p_high  
    roots=f1.monic().small_roots(X=2^200,beta=0.4)  
if roots:  
    p=int(roots[0]+p_high)  
    q=n//p  
    e=65537+k*p+(k+2)*((p+1)*(q+1))+1  
    d=inverse(e,(p-1)*(q-1))  
    m=pow(c,d,n)  
    print(long_to_bytes(int(m)))
#flag{b5f771c6-18df-49a9-9d6d-ee7804f5416c}
from Crypto.Util.number import *

n = 111922722351752356094117957341697336848130397712588425954225300832977768690114834703654895285440684751636198779555891692340301590396539921700125219784729325979197290342352480495970455903120265334661588516182848933843212275742914269686197484648288073599387074325226321407600351615258973610780463417788580083967
e = 37059679294843322451875129178470872595128216054082068877693632035071251762179299783152435312052608685562859680569924924133175684413544051218945466380415013172416093939670064185752780945383069447693745538721548393982857225386614608359109463927663728739248286686902750649766277564516226052064304547032760477638585302695605907950461140971727150383104
c = 14999622534973796113769052025256345914577762432817016713135991450161695032250733213228587506601968633155119211807176051329626895125610484405486794783282214597165875393081405999090879096563311452831794796859427268724737377560053552626220191435015101496941337770496898383092414492348672126813183368337602023823

k = e // n - 2
R.<x> = PolynomialRing(RealField(1024))
f=e*x-(65538*x+k*x^2+(k+2)*n*x+(k+2)*x^2+(k+2)*n)
res = f.roots()
for i in res:
    p_h = int(i[0])
    PR.<x> = PolynomialRing(Zmod(n))
    f1 = x + p_h
    roots = f1.monic().small_roots(X=2^200,beta=0.4)
    if roots:
        p = int(roots[0]) + p_h
        #print(p,n%p)
        if p and n%p==0:
            q= n // p
            e = 65537 + k * p + (k+2) * ((p+1) * (q+1)) + 1
            d = inverse(e,(p-1)*(q-1))
            m = pow(c,d,n)
            print(long_to_bytes(int(m)))
#flag{b5f771c6-18df-49a9-9d6d-ee7804f5416c}
from Crypto.Util.number import *

def get_full_p(p_high, n, bits):
    PR.<x> = PolynomialRing(Zmod(n))    
    f = x + p_high
    f = f.monic()
    roots = f.small_roots(X=2^(bits + 10), beta=0.4)  
    if roots:
        x0 = roots[0]
        p = gcd(x0 + p_high, n)
        return ZZ(p)

n = 111922722351752356094117957341697336848130397712588425954225300832977768690114834703654895285440684751636198779555891692340301590396539921700125219784729325979197290342352480495970455903120265334661588516182848933843212275742914269686197484648288073599387074325226321407600351615258973610780463417788580083967
e = 37059679294843322451875129178470872595128216054082068877693632035071251762179299783152435312052608685562859680569924924133175684413544051218945466380415013172416093939670064185752780945383069447693745538721548393982857225386614608359109463927663728739248286686902750649766277564516226052064304547032760477638585302695605907950461140971727150383104
c = 14999622534973796113769052025256345914577762432817016713135991450161695032250733213228587506601968633155119211807176051329626895125610484405486794783282214597165875393081405999090879096563311452831794796859427268724737377560053552626220191435015101496941337770496898383092414492348672126813183368337602023823

k = e // n - 2
a = 65537 + (k + 2) * n + (k + 2) + 1
P.<x> = PolynomialRing(RealField(1024))
f = e * x - ((2 * k + 2) * x ^ 2 + (k + 2) * n + a * x)
res = f.roots()

if res:
    for y in res:
        p_high = int(y[0])
        p = get_full_p(p_high, n, 200)
        if p:
            print(p)
            #9915449532466780441980882114644132757469503045317741049786571327753160105973102603393585703801838713884852201325856459312958617061522496169870935934745091

n = 111922722351752356094117957341697336848130397712588425954225300832977768690114834703654895285440684751636198779555891692340301590396539921700125219784729325979197290342352480495970455903120265334661588516182848933843212275742914269686197484648288073599387074325226321407600351615258973610780463417788580083967
e = 37059679294843322451875129178470872595128216054082068877693632035071251762179299783152435312052608685562859680569924924133175684413544051218945466380415013172416093939670064185752780945383069447693745538721548393982857225386614608359109463927663728739248286686902750649766277564516226052064304547032760477638585302695605907950461140971727150383104
c = 14999622534973796113769052025256345914577762432817016713135991450161695032250733213228587506601968633155119211807176051329626895125610484405486794783282214597165875393081405999090879096563311452831794796859427268724737377560053552626220191435015101496941337770496898383092414492348672126813183368337602023823
k = e // n - 2
p = 9915449532466780441980882114644132757469503045317741049786571327753160105973102603393585703801838713884852201325856459312958617061522496169870935934745091
q = n // p
#print(n % p)
#0
e = 65537 + k * p + (k + 2) * ((p+1) * (q+1)) + 1
phi = (p - 1) * (q - 1)
d = inverse(e,phi)
print(long_to_bytes(pow(c,d,n)))
#flag{b5f771c6-18df-49a9-9d6d-ee7804f5416c}
posted @ 2025-07-25 19:22  sevensnight  阅读(26)  评论(0)    收藏  举报