EzRSA
题目
from gmpy2 import lcm , powmod , invert , gcd , mpz
from Crypto.Util.number import getPrime
from sympy import nextprime
from random import randint
p = getPrime(1024)
q = getPrime(1024)
n = p * q
gift = lcm(p - 1 , q - 1)
e = 54722
flag = b'NPUCTF{******************}'
m = int.from_bytes(flag , 'big')
c = powmod(m , e , n)
print('n: ' , n)
print('gift: ' , gift)
print('c: ' , c)
#n: 17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121
#gift: 2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104
#c: 3738960639194737957667684143565005503596276451617922474669745529299929395507971435311181578387223323429323286927370576955078618335757508161263585164126047545413028829873269342924092339298957635079736446851837414357757312525158356579607212496060244403765822636515347192211817658170822313646743520831977673861869637519843133863288550058359429455052676323196728280408508614527953057214779165450356577820378810467527006377296194102671360302059901897977339728292345132827184227155061326328585640019916328847372295754472832318258636054663091475801235050657401857262960415898483713074139212596685365780269667500271108538319
分析
一 道 R S A , e 是 一 个 偶 数 , 而 φ ( n ) 中 一 定 有 一 个 因 子 为 2 一道RSA,e是一个偶数,而\varphi(n)中一定有一个因子为2 一道RSA,e是一个偶数,而φ(n)中一定有一个因子为2
print(isPrime(54722//2))
#1
且给了 g i f t = l c m ( p − 1 , q − 1 ) gift=lcm(p-1,q-1) gift=lcm(p−1,q−1),即 ( p − 1 ) 与 ( q − 1 ) 的 最 小 公 倍 数 (p-1)与(q-1)的最小公倍数 (p−1)与(q−1)的最小公倍数
在RSA中,安全性由大数n分解难题保证,如果能分解 n n n,就等同于得知了 p , q p,q p,q,就等同于得知了 φ ( n ) = ( p − 1 ) ∗ ( q − 1 ) \varphi(n)=(p-1)*(q-1) φ(n)=(p−1)∗(q−1)
这里告诉了我们 ( p − 1 ) 与 ( q − 1 ) (p-1)与(q-1) (p−1)与(q−1)的最小公倍数,那么我们看看也没有什么办法通过这个条件得知p或者q或者直接得到 φ ( n ) = ( p − 1 ) ∗ ( q − 1 ) \varphi(n)=(p-1)*(q-1) φ(n)=(p−1)∗(q−1)也是可以的。
回顾一下算术基本定理:
算术基本定理可表述为:任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积 N = P 1 a 1 P 2 a 2 P 3 a 3 . . . . . . P n a n N=P_1^{a_1}P_2^{a_2}P_3^{a_3}......P_n^{a_n} N=P1a1P2a2P3a3......Pnan,这里 P 1 < P 2 < P 3 . . . . . . < P n P_1<P_2<P_3......<P_n P1<P2<P3......<Pn均为质数,其中指数 a i a_i ai是正整数。这样的分解称为 N 的标准分解式,最早证明是由欧几里得给出的。
假 如 现 在 有 两 个 数 { N 1 = P 1 a 1 P 2 a 2 P 3 a 3 N 2 = P 1 a 1 ′ P 2 a 2 ′ P 3 a 3 ′ 假如现在有两个数\begin{cases}N_1=P_1^{a_1}P_2^{a_2}P_3^{a_3}\\N_2=P_1^{a_1'}P_2^{a_2'}P_3^{a_3'}\end{cases} 假如现在有两个数{N1=P1a1P2a2P3a3N2=P1a1′P2a2′P3a3′
则 { l c m ( N 1 , N 2 ) = P 1 m a x { a 1 , a 1 ′ } P 2 m a x { a 2 , a 2 ′ } P 3 m a x { a 3 , a 3 ′ } g c d ( N 1 , N 2 ) = P 1 m i n { a 1 , a 1 ′ } P 2 m i n { a 2 , a 2 ′ } P 3 m i n { a 3 , a 3 ′ } 则\begin{cases}lcm(N_1,N_2)=P_1^{max\{a_1,a_1'\}}P_2^{max\{a_2,a_2'\}}P_3^{max\{a_3,a_3'\}}\\gcd(N_1,N_2)=P_1^{min\{a_1,a_1'\}}P_2^{min\{a_2,a_2'\}}P_3^{min\{a_3,a_3'\}}\end{cases} 则{lcm(N1,N2)=P1max{a1,a1′}P2max{a2,a2′}P3max{a3,a3′}gcd(N1,N2)=P1min{a1,a1′}P2min{a2,a2′}P3min{a3,a3′}
观 察 一 下 会 发 现 l c m 中 取 的 是 m a x { a n , a n ′ } , g c d 中 取 的 是 m i n { a n , a n ′ } , 相 当 于 两 个 指 数 在 l c m 中 被 取 走 一 个 , 在 g c d 中 被 取 走 一 个 观察一下会发现lcm中取的是max\{a_n,a_n'\},gcd中取的是min\{a_n,a_n'\},相当于两个指数在lcm中被取走一个,在gcd中被取走一个 观察一下会发现lcm中取的是max{an,an′},gcd中取的是min{an,an′},相当于两个指数在lcm中被取走一个,在gcd中被取走一个
所 以 若 将 l c m ( N 1 , N 2 ) 乘 以 g c d ( N 1 , N 2 ) , 两 个 指 数 则 都 会 出 现 在 结 果 中 , 成 为 P 1 a 1 + a 1 ′ P 2 a 2 + a 2 ′ P 3 a 3 + a 3 ′ = N 1 ∗ N 2 所以若将lcm(N_1,N_2)乘以gcd(N_1,N_2),两个指数则都会出现在结果中,成为P_1^{a_1+a_1'}P_2^{a_2+a_2'}P_3^{a_3+a_3'}=N_1*N_2 所以若将lcm(N1,N2)乘以gcd(N1,N2),两个指数则都会出现在结果中,成为P1a1+a1′P2a2+a2′P3a3+a3′=N1∗N2
所 以 对 于 这 道 题 目 来 说 , 我 们 只 需 要 找 到 g c d ( p − 1 , q − 1 ) 就 可 以 把 φ ( n ) = ( p − 1 ) ∗ ( q − 1 ) 求 出 。 所以对于这道题目来说,我们只需要找到gcd(p-1,q-1)就可以把\varphi(n)=(p-1)*(q-1)求出。 所以对于这道题目来说,我们只需要找到gcd(p−1,q−1)就可以把φ(n)=(p−1)∗(q−1)求出。
即 l c m ( p − 1 , q − 1 ) ∗ g c d ( p − 1 , q − 1 ) = p ∗ q − p − q + 1 = φ ( n ) 即lcm(p-1,q-1)*gcd(p-1,q-1)=p*q-p-q+1=\varphi(n) 即lcm(p−1,q−1)∗gcd(p−1,q−1)=p∗q−p−q+1=φ(n)
print(len(bin(n)[2:]))
print(len(bin(gift)[2:]))
#2048
#2045
可 以 看 到 g i f t ( l c m ) 的 位 数 与 n 的 接 近 , 且 φ ( n ) 的 值 还 要 比 n 小 一 些 , 证 明 g c d ( p − 1 , q − 1 ) 很 小 , 所 以 我 们 可 以 选 择 爆 破 一 下 g c d 。 可以看到gift(lcm)的位数与n的接近,且\varphi(n)的值还要比n小一些,证明gcd(p-1,q-1)很小,所以我们可以选择爆破一下gcd。 可以看到gift(lcm)的位数与n的接近,且φ(n)的值还要比n小一些,证明gcd(p−1,q−1)很小,所以我们可以选择爆破一下gcd。
Solve
from gmpy2 import *
from Crypto.Util.number import *
n = 17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121
gift = 2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104
c = 3738960639194737957667684143565005503596276451617922474669745529299929395507971435311181578387223323429323286927370576955078618335757508161263585164126047545413028829873269342924092339298957635079736446851837414357757312525158356579607212496060244403765822636515347192211817658170822313646743520831977673861869637519843133863288550058359429455052676323196728280408508614527953057214779165450356577820378810467527006377296194102671360302059901897977339728292345132827184227155061326328585640019916328847372295754472832318258636054663091475801235050657401857262960415898483713074139212596685365780269667500271108538319
print(len(bin(n)[2:]))
print(len(bin(gift)[2:]))
e = 54722
print(isPrime(54722//2))
e //= 2
for i in range(10000):
phi = i*gift
try:
d = invert(e, phi)
m = pow(c, d, n)
flag = long_to_bytes(iroot(m, 2)[0])
if b'{' in flag:
print(long_to_bytes(iroot(m, 2)[0]))
print("gcd={}".format(i))
break
else:
continue
except:
pass
#2048
#2045
#1
#b'NPUCTF{diff1cult_rsa_1s_e@sy}'
#gcd=1
发现 g c d = 1 , 挺 有 意 思 的 , g i f t 就 是 φ ( n ) , 去 验 证 一 下 , 发 现 在 gcd=1,挺有意思的,gift就是\varphi(n),去验证一下,发现在 gcd=1,挺有意思的,gift就是φ(n),去验证一下,发现在factordb上已经有人把n分解的结果传到数据库上面去了(做题的时候应该是没有分解的,这里也不推荐大家每次做RSA都只有分解这一条路)
p = 106021448991021391444550749375115277080844281746248845802565680557785009341952320484175568763707424932172033597514861602114171459176440279045761846695231788376075050452154924141266290931413542110639081792550648106240966552406813059396358355737185354885474455248579946190266152416149137616855791805617206153497
q = 161136651053130509602530659420755324119806487925813087617466818245407407797561810253722204813002837916779909309520498985459703212021249251124954613236122142746302911323565396331355397916764254680629384957057354297855676493062493901977415968666512459829211010720514167083018352796496733697235524845188512914793
assert(p*q==n)
print((p-1)*(q-1))
print(gift)
assert((p-1)*(q-1)==gift)
这里assert没过,证明gift和phi不相等
那就是因为phi是gift的倍数,导致通过gift出来的私钥也能解密。
print(gcd(p-1,q-1))
#8
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0JkPlM59-1653542192491)(http://cdn.jsdelivr.net/gh/MangoFeng/Mango-img/IMG_0929(20220525-182939)].PNG)
print(54722//2%8)
#1