题目
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 + 2
和e = 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}