# 当e约去公约数t后与phi(n)互素 defdecrypt(p, q, e, c): n = p * q phi = (p - 1) * (q - 1) t = gmpy2.gcd(e, phi) d = gmpy2.invert(e // t, phi) m = pow(c, d, n) print(m) msg = gmpy2.iroot(m, t) print(msg) if msg[1]: print(long_to_bytes(msg[0])) e=74 p= 86053582917386343422567174764040471033234388106968488834872953625339458483149 q= 72031998384560188060716696553519973198388628004850270102102972862328770104493 c= 3319022875033974423964187739917595278427184197383708001806576530909609086508041781233603918453326670975069669017566120311964861589659101428987255146018427
decrypt(p, q, e, c)
# XAUTCTF{e_1s_n0t_@_Prime}
Close Enough
题目描述:听说 RSA 非常安全?可是如果两个质数选得“太接近”,结果会怎样呢?
打开附件,
from Crypto.Util.number import getPrime, bytes_to_long, isPrime, inverse
//找到大于n的最大素数 defnextprime(n): n += 1 whilenot isPrime(n): n += 1 return n
flag = "" e = 65537
p = getPrime(512) q = nextprime(p + (1 << 20))
n = p * q phi = (p - 1) * (q - 1) d = inverse(e, phi)
m = bytes_to_long(bytes(flag, 'utf-8')) c = pow(m, e, n)
print("n =", n) print("c =", c)
''' n = 123396213393166669967180741417142386608199293295343396860771048265983027294499309946576382614888097841439905355747919662299668639065387197060901118151079928153661471067906790612624750455011912757452786783406975664690965235505528837643347037179762435944987875469138529309017524600020070268892228090521628748157 c = 96164959972807254618417630680358223130932461911993510788732180904733021127322517962027522173599694137945712716717847174536035583857007099675639087774330478493529755676338936283880541666682835088571888431839407259147158612358623749706985446040831405827991266588402528874606153834653456725906949141238839683080 '''
a = (p+q)/2 b = (q-p)/2 得 n = (a+b)(a-b) = a^2-b^2
本题,p和q接近,可以从ceil(sqrt(n))将n开方后尝试a,直至a^2-n为完全平方数
基于偏移量的暴力搜索(逼近):
我们知道了q = p +2^20,则n = p*q = p*(p +2^20) = p^2 + 2^20 * p
则p^2 + 2^20 * p - n也就约等于0了,解方程式得p。
知道了p,也就知道了q,之后就是RSA的常规操作了。
所以,我们解密该RSA的核心思路就是通过p^2 + 2^20 * p - n解方程得到p的大概值,从其前后各试多个数,从是不是素数、q_ca = p+2^20大的下一个素数、p*q_ca是不是为n几个方面猜测,循环直至得到找到p和q。通过数学估算+暴力逼近解密RSA。
EXP:
from math import isqrt from Crypto.Util.number import isPrime, inverse, long_to_bytes
n = 123396213393166669967180741417142386608199293295343396860771048265983027294499309946576382614888097841439905355747919662299668639065387197060901118151079928153661471067906790612624750455011912757452786783406975664690965235505528837643347037179762435944987875469138529309017524600020070268892228090521628748157 c = 96164959972807254618417630680358223130932461911993510788732180904733021127322517962027522173599694137945712716717847174536035583857007099675639087774330478493529755676338936283880541666682835088571888431839407259147158612358623749706985446040831405827991266588402528874606153834653456725906949141238839683080 e = 65537
defnextprime(n): n += 1 whilenot isPrime(n): n += 1 return x