CTF-Crypto-BUUCTF-[NPUCTF2020]EzRSA
[NPUCTF2020]EzRSA
task:
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
analysis:
预期解:首先我们通过大数在线分解网站进行对n的分解,后续求出phi,同时我们注意到e=54722,一个非常用的非质数的一个加密指数,经过验证gcd(e,phi)=2,所以我们这里就要采用e与phi不互素的攻击脚本了。但是这里有一个比较异于其他e与phi不互素的点。
因此,我们可以先去求解m^2,进而开方求解。
非预期解:首先我们要知道gift = lcm(p - 1 , q - 1)的意义,lcm(a,b)即求a,b的最大公倍数,而我们也知道下面最大公因数和最小公倍数的关系.
同时,经过小小的测试,我们发现p=getPrime(1024),q=getPrime(1024)时,(p-1,q-1)=2是个概率性比较小的事件.
from Crypto.Util.number import *
counter = 0
for _ in range(10):
p = getPrime(1024)
q = getPrime(1024)
if GCD(p-1,q-1) == 2:
counter += 1
print(counter)
# 3 4 7 5 3
但是,gcd(p-1,q-1)<=10是一个概率比较大的事件.
from Crypto.Util.number import *
counter = 0
for _ in range(10):
p = getPrime(1024)
q = getPrime(1024)
if GCD(p-1,q-1) <= 10:
counter += 1
print(counter)
# 9 9 9 9 9 8 8 9
这里原本只是考虑了(p-1)(q-1)的最大公因数是2,但是看到很多师傅的脚本都是说要在小范围内进行爆破,后面仔细想了一想,这样做的必要性并不是很高。
这里在证明的时候还引发了一下思考,即对于欧拉定理,两边对于n的幂运算是成立的,但是对于1/n的幂运算是否成立,在下面进行一下探讨。
exp:
from gmpy2 import gmpy2
from sympy import *
from Crypto.Util.number import *
from gmpy2 import *
n = 17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121
gift = 2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104
c = 3738960639194737957667684143565005503596276451617922474669745529299929395507971435311181578387223323429323286927370576955078618335757508161263585164126047545413028829873269342924092339298957635079736446851837414357757312525158356579607212496060244403765822636515347192211817658170822313646743520831977673861869637519843133863288550058359429455052676323196728280408508614527953057214779165450356577820378810467527006377296194102671360302059901897977339728292345132827184227155061326328585640019916328847372295754472832318258636054663091475801235050657401857262960415898483713074139212596685365780269667500271108538319
phi = gift * 2
e = 54722
d = inverse(e//2,phi)
print(long_to_bytes(gmpy2.iroot(pow(c,int(d),n),2)[0]))
# NPUCTF{diff1cult_rsa_1s_e@sy}
exp(plus):
注意:遍历过程中不是所有的值都符合条件,可能会报ZeroDivisionError,因此需要加异常处理.
from sympy import *
from Crypto.Util.number import *
from gmpy2 import *
n = 17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121
gift = 2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104
c = 3738960639194737957667684143565005503596276451617922474669745529299929395507971435311181578387223323429323286927370576955078618335757508161263585164126047545413028829873269342924092339298957635079736446851837414357757312525158356579607212496060244403765822636515347192211817658170822313646743520831977673861869637519843133863288550058359429455052676323196728280408508614527953057214779165450356577820378810467527006377296194102671360302059901897977339728292345132827184227155061326328585640019916328847372295754472832318258636054663091475801235050657401857262960415898483713074139212596685365780269667500271108538319
phi = 1
for k in range(20):
phi = gift * k
try:
e = 54722
d = inverse(e//2,phi)
print(long_to_bytes(iroot(pow(c,int(d),n),2)[0]))
except ZeroDivisionError:
continue
# NPUCTF{diff1cult_rsa_1s_e@sy}
接下来就验证了前面所说的遍历爆破必要性不大的原因.无需考虑gcd(p-1,q-1)是否真的是2来考虑,也就是说我们通过2gift得到虽说(p-1)(q-1)的一个因数,但完成解密已经足够了,后续再继续剖析一下具体是为何,我认为是d=inverse(e,phi)中的ed-1=k*phi中的k和刚刚讨论的一个2弥补了我们这里(p-1)(q-1)与2gift之间的倍数关系。
'''
from Crypto.Util.number import *
p = []
q = []
gcd_p_q = []
for _ in range(10):
p_ = getPrime(1024)
q_ = getPrime(1024)
if GCD(p_-1,q_-1) != 2:
p.append(p_)
q.append(q_)
gcd_p_q.append(GCD(p_-1,q_-1))
print(p)
print(q)
print(gcd_p_q)
'''
def Decry(c,gift,n):
phi = gift * 2
e = 54722
d = inverse(e // 2, phi)
print(long_to_bytes(iroot(pow(c, int(d), n), 2)[0]))
from Crypto.Util.number import *
from gmpy2 import *
flag = b"NPUCTF{diff1cult_rsa_1s_e@sy}"
m = bytes_to_long(flag)
e = 54722
p = [165769529982557110338607340915156100801098416130997439576334379508821440848971174760048158587119547406635600893637841681086158438768213772214517750339428677315490555160942003232596459062054959738891686870233195536532370860140063189202797190059610081047576305497597409561188937939408990727950563176781704539297, 116343395174340190092069503777310556723178648009455212305248936396963169816077553838209612655736616510743366230652670832031080277340066999260068760526903315620866319662209329442140259409352974980517540228598521026450329104744230723749861337620234549111269789911144248755958059375257103021764571856195434301387, 146568701354861789150883161023275226504781623545753594360497139291866572700518772979039334432548181398117756736230748400100137433915940836998928478273562599500891612293792908778898338203112830493255218572714331970616169322682552907753048099396156540995404910656800648470192680527779367214626376302869837925939, 150341231289414416060634578191054813824878951723964362268322860494417549544786593982620701089756170421851522916910605706843581797034345010775524379791837772220498032814311641041106375055871308744692823800173809715197258287370221884954687753741599202758781471611242752026561882594616146654392958052627699225601, 106076318345280302832178114745987989092752970236833697669940616165610071852837660365905689921882465580551218479519413505153944238605510532770399306387751379357148388328037897750411868377806232012937141988679989359139482214257132906339735969578486791176650914341348176150226323174041636877671233002119978031669, 105604279265427565452784118653427605131869284838204225350681729287773965522475641691360342432073291656216393802493324304950298647313986478535009569011980897388663221571514270675630511922377073557285084679790187942469615294088901857815697983385152465218065868867750466181794105118546299757138223330343840032793, 93461576609835033605841101610168486628467197777335704657201919738990521241395464464813394887787310854994148413440260042145048542049122223105918837508753060849466078866306710557442859628055523948192545184001155472371548703547381150198215470590756627123249322868496934135361879230778639538190555630569027015027]
q = [108823859720471012173859316048546486537605945743756768449486042387362076763659513042206041025307864534414461851677011129643485898990309713140498018701189709479388344757525159178073567582542321101894872647005875743761477642752627748557958295757092892949897539046285604738634618096724444489959674986804408405589, 98651309624762006732009418081168299907808810489731365996737381459105046257489514199375204345329804376405214839618499854678499333910197962963306321825212413280039614793177543713663142246649256980173494716800539140045333936791697405139355963022199838362955049004395658761432730207589497047658551199605843578677, 118497423490194307284667137560978387533828136098350298237667801667211096542290588421970801995534170030924197735729685080089566186235395734834105747074635659555988817969591461732245846129805235021246178123746536160807552040539922343021226938305514790846947175156522351695247300716962588618737255280374838470673, 169026359117248311582306387124537343617148374820940677616896541363508993960327728685474790595428505958840154541840299526497201613942229579631943668376733101180289467189938895824249369799047985645964616955947624305635837546080656702779444534113838191372360932135630458061515401181264664654344208446693023810783, 126621763227970282639222137762233004110489598214753251715370483441342903102762962410133600810641899016780733163603742410095606748821254051407116388029355612083698051982893487748415364927499079910760259387069256653163463477570668804168818601031632313723907641322622465172365124656602068677472129669290980808429, 128031097611979910338887890267118733772342943653310373203139494323767039137385085548810399689985515037564508637801856790178090230653485425614914876104489201056405851326219927796063889341663918612504780090694590641843228352622249272140010929258747701816194142886683076766214320361472812362106745670373358014033, 161468293916232629321247821135558960374709304686863679248094593079628805462576454755913841143624642702650211054408188808724989182603135707534064363489671879058378037440674418421271485450016802827437648624225238515539548800930850552361454242042394619838900742476102363197669558270443253409133122593563224964113]
gcd_p_q = [4, 6, 6, 1186, 12, 24, 6]
counter = 0
gcd_n_flag = []
for i in range(len(p)):
n = p[i] * q[i]
gcd_n_flag.append(GCD(n, m))
c = pow(m,e,n)
gift = lcm(p[i]-1,q[i]-1)
Decry(c,gift,n)
print(gcd_n_flag)
'''
b'NPUCTF{diff1cult_rsa_1s_e@sy}'
b'NPUCTF{diff1cult_rsa_1s_e@sy}'
b'NPUCTF{diff1cult_rsa_1s_e@sy}'
b'NPUCTF{diff1cult_rsa_1s_e@sy}'
b'NPUCTF{diff1cult_rsa_1s_e@sy}'
b'NPUCTF{diff1cult_rsa_1s_e@sy}'
b'NPUCTF{diff1cult_rsa_1s_e@sy}'
[1, 1, 1, 1, 1, 1, 1]
'''
这道题收益颇多,如有错误,还请各位师傅斧正。