非对称加密算法RSA的深度解析,在CTF中RSA题目

一、背景

现代密码体系中,主要分为两类,对称加密和非对称加密两大类。在安全性方面上,非对称加密以安全可靠,在互联网中特别广泛的使用,就如我们平时接触到的https的TLS等一些证书的实现,也深得非对称加密算法的精华。

⾮对称密码体制也叫公钥密码体制,该技术就是针对私钥密码体制的缺陷被提出来的。在公钥加密系统中,加密和解密是相对独⽴的,加密和解密会使⽤两把不同的密钥,加密密钥(公开密钥)向公众公开,谁都可以使⽤,解密密钥(秘密密钥)只有解密⼈⾃⼰知道,⾮法使⽤者根据公开的加密密钥⽆法推算出解密密钥,顾其可称为公钥密码体制。 ⼀般的钥匙都是既能上锁、也能开锁的。但是,⾮对称加密中,密钥有两种:公有密钥、私有秘钥。公有密钥⽤于上锁(加密)。私有密钥⽤于解锁(解密)。非对称加密算法包括 RSA算法、DSA算法(数字签名算法的一种)、ECC算法(是一种基于椭圆曲线的加密),其中RSA算法是最早被广泛使用的非对称加密算法,它利用质数分解的困难性,通过生成公钥和私钥来实现加密和解密。
CTF中RSA也是一个经常被用来出题的考点,接下来我们就RSA进行深度学习。

二、原理

RSA算法的具体描述:
非对称加密算法RSA的深度解析,在CTF中RSA题目_第1张图片
接下来我们看一下他的程序实现流程图:
非对称加密算法RSA的深度解析,在CTF中RSA题目_第2张图片

三、RSA已知情况攻击

RSA题目主要是在题目给定某系条件下进行的攻击

3.1 已知p,q,e 求d

示例:【CTF秀-crypto4】 p=447685307 q=2037 e=17,提交flag{d}即可。
解题思路:

import gmpy2
p = 447685307
q = 2037
e = 17
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
print(d)

3.2已知p,q,dp,dq,c 求m

示例:【BUUCTF-RSA1】
解题思路:
非对称加密算法RSA的深度解析,在CTF中RSA题目_第3张图片

p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229 
q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469 
dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929 
dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041 
c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852

import gmpy2
import binascii
I = gmpy2.invert(p,q)
mp = gmpy2.powmod(c,dp,p)
mq = gmpy2.powmod(c,dq,q)

m = ((I*(mp-mq))%q)*p+mp
print(binascii.unhexlify(hex(m)[2:]))

3.3已知e,n,dp,c 求m

解题思路:
非对称加密算法RSA的深度解析,在CTF中RSA题目_第4张图片

import gmpy2
import binascii
e = 65537
n = 248254007851526241177721526698901802985832766176221609612258877371620580060433101538328030305219918697643619814200930679612109885533801335348445023751670478437073055544724280684733298051599167660303645183146161497485358633681492129668802402065797789905550489547645118787266601929429724133167768465309665906113
dp = 905074498052346904643025132879518330691925174573054004621877253318682675055421970943552016695528560364834446303196939207056642927148093290374440210503657

c = 140423670976252696807533673586209400575664282100684119784203527124521188996403826597436883766041879067494280957410201958935737360380801845453829293997433414188838725751796261702622028587211560353362847191060306578510511380965162133472698713063592621028959167072781482562673683090590521214218071160287665180751

for i in range(1,e):
    if (e*dp-1)%i == 0 and n%((e*dp-1)//i+1)==0:
        q = n//((e*dp-1)//i+1)
        phi = (q-1)*((e*dp-1)//i)
        d = gmpy2.invert(e,phi)
        m = gmpy2.powmod(c,d,n)

print(binascii.unhexlify(hex(m)[2:]))

3.4共模攻击,求m

适用情况,多组c,e但模数n相同,且e之间最好互质。
非对称加密算法RSA的深度解析,在CTF中RSA题目_第5张图片
题目给了c1,c2;e1,e2以及一个共同的n,尝试共模攻击,脚本如下:

import gmpy2
from Crypto.Util.number import getPrime,long_to_bytes
 
e1 = 2767
e2 = 3659
n = 21058339337354287847534107544613605305015441090508924094198816691219103399526800112802416383088995253908857460266726925615826895303377801614829364034624475195859997943146305588315939130777450485196290766249612340054354622516207681542973756257677388091926549655162490873849955783768663029138647079874278240867932127196686258800146911620730706734103611833179733264096475286491988063990431085380499075005629807702406676707841324660971173253100956362528346684752959937473852630145893796056675793646430793578265418255919376323796044588559726703858429311784705245069845938316802681575653653770883615525735690306674635167111
 
c1 = 20152490165522401747723193966902181151098731763998057421967155300933719378216342043730801302534978403741086887969040721959533190058342762057359432663717825826365444996915469039056428416166173920958243044831404924113442512617599426876141184212121677500371236937127571802891321706587610393639446868836987170301813018218408886968263882123084155607494076330256934285171370758586535415136162861138898728910585138378884530819857478609791126971308624318454905992919405355751492789110009313138417265126117273710813843923143381276204802515910527468883224274829962479636527422350190210717694762908096944600267033351813929448599
c2 = 11298697323140988812057735324285908480504721454145796535014418738959035245600679947297874517818928181509081545027056523790022598233918011261011973196386395689371526774785582326121959186195586069851592467637819366624044133661016373360885158956955263645614345881350494012328275215821306955212788282617812686548883151066866149060363482958708364726982908798340182288702101023393839781427386537230459436512613047311585875068008210818996941460156589314135010438362447522428206884944952639826677247819066812706835773107059567082822312300721049827013660418610265189288840247186598145741724084351633508492707755206886202876227
 
_,s1, s2 = gmpy2.gcdext(e1, e2)
m = pow(c1, s1, n) * pow(c2, s2, n) % n
print(long_to_bytes(m))

3.5给出c,n,e 求m

import RSAwienerHacker
import binascii
c = 17250922799297131008803303235771955129
n = 134097988095851988085603926250918812377
e = 0x10001
d = RSAwienerHacker.hack_RSA(e,n)
m = gmpy2.powmod(c,d,n)
 
print(binascii.unhexlify(hex(m)[2:]))

3.6低加密指数攻击(e很小)

示例:【CTF秀-easyrsa4】
解题思路: 题中e=3相对于n,c来说极小,故可知是低加密指数攻击。
在这里插入图片描述

import gmpy2
import binascii

e = 3
n = 18970053728616609366458286067731288749022264959158403758357985915393383117963693827568809925770679353765624810804904382278845526498981422346319417938434861558291366738542079165169736232558687821709937346503480756281489775859439254614472425017554051177725143068122185961552670646275229009531528678548251873421076691650827507829859299300272683223959267661288601619845954466365134077547699819734465321345758416957265682175864227273506250707311775797983409090702086309946790711995796789417222274776215167450093735639202974148778183667502150202265175471213833685988445568819612085268917780718945472573765365588163945754761
c = 150409620528139732054476072280993764527079006992643377862720337847060335153837950368208902491767027770946661

i = 0
while True:
    if gmpy2.iroot((c+i*n),3)[1] == True:
        m = gmpy2.iroot((c+i*n),3)[0]
        break
    i += 1

print(binascii.unhexlify(hex(m)[2:]))

3.7低指数加密广播攻击(e很小;多组n,c)

适用情况:很多组不同的n和c,但用的是同一个e且很小。

此时我们可以使用中国剩余定理来求出m^{e},什么是中国剩余定理自己去了解,这里只讲怎么用python解题,见例题:

例题:BUUCTF RSA4
题目给了很多组n和c
当n很大时我们就可以考虑e=3的低指数情况,把n和c放到数组里,像n=[n1,n2,n3],c=[c1,c2,c3].然后最方便的是调用sympy库里的中国剩余定理,也就是crt(c,n)方法直接可以求出m的e次,然后开方得到m就行了。其中sympy也是第三方库,可以pip或者pycharm里导入的时候顺手装上去就行了。

这道题还有一点要注意的是给出的n和c是五进制,注意先转换成10进制。python解题脚本如下:

import gmpy2
import libnum
from Crypto.Util.number import long_to_bytes
from sympy.ntheory.modular import crt
 
N1 = int('331310324212000030020214312244232222400142410423413104441140203003243002104333214202031202212403400220031202142322434104143104244241214204444443323000244130122022422310201104411044030113302323014101331214303223312402430402404413033243132101010422240133122211400434023222214231402403403200012221023341333340042343122302113410210110221233241303024431330001303404020104442443120130000334110042432010203401440404010003442001223042211442001413004',5)
c1 = int('310020004234033304244200421414413320341301002123030311202340222410301423440312412440240244110200112141140201224032402232131204213012303204422003300004011434102141321223311243242010014140422411342304322201241112402132203101131221223004022003120002110230023341143201404311340311134230140231412201333333142402423134333211302102413111111424430032440123340034044314223400401224111323000242234420441240411021023100222003123214343030122032301042243',5)
 
N2 = int('302240000040421410144422133334143140011011044322223144412002220243001141141114123223331331304421113021231204322233120121444434210041232214144413244434424302311222143224402302432102242132244032010020113224011121043232143221203424243134044314022212024343100042342002432331144300214212414033414120004344211330224020301223033334324244031204240122301242232011303211220044222411134403012132420311110302442344021122101224411230002203344140143044114',5)
c2 = int('112200203404013430330214124004404423210041321043000303233141423344144222343401042200334033203124030011440014210112103234440312134032123400444344144233020130110134042102220302002413321102022414130443041144240310121020100310104334204234412411424420321211112232031121330310333414423433343322024400121200333330432223421433344122023012440013041401423202210124024431040013414313121123433424113113414422043330422002314144111134142044333404112240344',5)
 
N3 = int('332200324410041111434222123043121331442103233332422341041340412034230003314420311333101344231212130200312041044324431141033004333110021013020140020011222012300020041342040004002220210223122111314112124333211132230332124022423141214031303144444134403024420111423244424030030003340213032121303213343020401304243330001314023030121034113334404440421242240113103203013341231330004332040302440011324004130324034323430143102401440130242321424020323',5)
c3 = int('10013444120141130322433204124002242224332334011124210012440241402342100410331131441303242011002101323040403311120421304422222200324402244243322422444414043342130111111330022213203030324422101133032212042042243101434342203204121042113212104212423330331134311311114143200011240002111312122234340003403312040401043021433112031334324322123304112340014030132021432101130211241134422413442312013042141212003102211300321404043012124332013240431242',5)
 
e = 3
n = [N1,N2,N3]
c = [c1,c2,c3]
resultant, mod = crt(n, c)
value, is_perfect = gmpy2.iroot(resultant, e)
print(long_to_bytes(value))

3.8公因数攻击(多组n,c)

适用情况:很多组n和c

和上面的广播攻击类似,题目会给你很多组n和c。我们知道n=p*q,而p、q是两个大素数。所以说当有很多组n的时候,很有可能出现两个n之间存在公因数。而这个公因数就是p和q其中的一个,当然知道其中一个另一个也就知道了,我们就可以求出d进而根据对应密文求出m。

例题:BUUCTF RSA5
题目中e = 65537,然后给了多达20组的n和c。

import  gmpy2
import libnum
from Crypto.Util.number import long_to_bytes
 
n1 = 20474918894051778533305262345601880928088284471121823754049725354072477155873778848055073843345820697886641086842612486541250183965966001591342031562953561793332341641334302847996108417466360688139866505179689516589305636902137210185624650854906780037204412206309949199080005576922775773722438863762117750429327585792093447423980002401200613302943834212820909269713876683465817369158585822294675056978970612202885426436071950214538262921077409076160417436699836138801162621314845608796870206834704116707763169847387223307828908570944984416973019427529790029089766264949078038669523465243837675263858062854739083634207
c1 = 974463908243330865728978769213595400782053398596897741316275722596415018912929508637393850919224969271766388710025195039896961956062895570062146947736340342927974992616678893372744261954172873490878805483241196345881721164078651156067119957816422768524442025688079462656755605982104174001635345874022133045402344010045961111720151990412034477755851802769069309069018738541854130183692204758761427121279982002993939745343695671900015296790637464880337375511536424796890996526681200633086841036320395847725935744757993013352804650575068136129295591306569213300156333650910795946800820067494143364885842896291126137320
 
#...此处省略20组n和c
 
e = 65537
n=[]
c=[]
p=[]
for i in range(1,20):
	n.append(eval('n'+str(i)))
	c.append(eval('c'+str(i)))
data=list(zip(n,c))
for i in range(len(n)):
	for j in range(i+1,len(n)):
		if gmpy2.gcd(n[i],n[j])!=1:
			print(i,j)#i=4,j=17
			print(gmpy2.gcd(n[i],n[j]))
p=gmpy2.gcd(n5,n18)
q=n5//p
d = gmpy2.invert(e, (p-1)*(q-1))
print(d)
m = pow(c5,d,n5)
print(long_to_bytes(m))

3.9低解密指数攻击(e很大)

适用情况:e很大

和低加密指数攻击相反,当e很大的时候我们怎么办呢,这里就要用到低解密指数攻击。当e很大时,相对的d就会很小。这里我们用到github上一个wienerHacker脚本pablocelayes/rsa-wiener-attack: A Python implementation of the Wiener attack on RSA public-key encryption scheme. (github.com)

下载之后把里面RSAwienerHacker.py改一改输入题目给你的e和n就可以帮你解出d

#低解密指数攻击,使用 RSAwienerHacker脚本解出d
#注意python2和python3在hex转换时数据结尾相差差一个L字符,会导致hash值不一样
N = 101991809777553253470276751399264740131157682329252673501792154507006158434432009141995367241962525705950046253400188884658262496534706438791515071885860897552736656899566915731297225817250639873643376310103992170646906557242832893914902053581087502512787303322747780420210884852166586717636559058152544979471
e = 46731919563265721307105180410302518676676135509737992912625092976849075262192092549323082367518264378630543338219025744820916471913696072050291990620486581719410354385121760761374229374847695148230596005409978383369740305816082770283909611956355972181848077519920922059268376958811713365106925235218265173085
 
d = 8920758995414587152829426558580025657357328745839747693739591820283538307445
dd = hex(d)
dd = dd+"L"
print(dd)
import hashlib
flag = "flag{" + hashlib.md5(dd.encode("utf-8")).hexdigest() + "}"
print(flag)

3.10 dp泄露

适用情况:题目提供dp\dq

有时候除了e,n,c之外题目还会给你像dp,dq这样的值,这是为了方便计算产生的,同时也给了我们另一种解题思路。首先,了解dp,dq是什么东西:

dp=d%(p-1)

然后就可以进行推导,简单过程如下:

d = dp + k1 * (p-1)
d * e = 1 + k2(p-1)(q-1)
把第二个式子的d代换掉:
e * (dp + k1(p-1)) = 1 + k2(p-1)(q-1)
两边同时对(p-1)取模,消去k
e * dp % (p - 1) = 1
e * dp = 1 + k(p - 1)

得到这个式子之后我们就可以通过爆破k的方式来求出p,进而求出d,进而求出m

import gmpy2
from Crypto.Util.number import long_to_bytes
 
e = 65537
n = 248254007851526241177721526698901802985832766176221609612258877371620580060433101538328030305219918697643619814200930679612109885533801335348445023751670478437073055544724280684733298051599167660303645183146161497485358633681492129668802402065797789905550489547645118787266601929429724133167768465309665906113
dp = 905074498052346904643025132879518330691925174573054004621877253318682675055421970943552016695528560364834446303196939207056642927148093290374440210503657
 
c = 140423670976252696807533673586209400575664282100684119784203527124521188996403826597436883766041879067494280957410201958935737360380801845453829293997433414188838725751796261702622028587211560353362847191060306578510511380965162133472698713063592621028959167072781482562673683090590521214218071160287665180751
 
for i in range(1, e):
    if (dp * e - 1) % i == 0:
        if n % (((dp * e - 1) // i) + 1) == 0:
            p = ((dp * e - 1) // i) + 1
            q = n // (((dp * e - 1) // i) + 1)
            d = gmpy2.invert(e, (p-1)*(q-1))
            m = pow(c, d, n)
 
print(m)
print(long_to_bytes(m))

3.11 dp,dq泄露

适用情况:dp,dq同时泄露
有的时候题目把dpdq都给我们了,这个时候我们不用知道e也可以解密。
此时有:

m1 = c^dpmodp
m2 = c^dqmodq
m = (((m1-m2)*I)%p)*q+m2
其中I为对pq求逆元

import gmpy2
from Crypto.Util.number import long_to_bytes
p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229
q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469
dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929
dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041
c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852
I = gmpy2.invert(q,p)
m1 = pow(c,dp,p)
m2 = pow(c,dq,q)
m = (((m1-m2)*I)%p)*q+m2
print(long_to_bytes(m))

3.12 已知(p, q, e,c),求m

示例:【CTF秀-crypto5】 p=447685307 q=2037 e=17 c=704796792,提交flag{m}。
解题思路:

import gmpy2
p=447685307
q=2037
e=17
c=704796792

phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = gmpy2.powmod(c,d,p*q)

print(m)

3.13已知(n, e1, e2,c1,c2),求m

示例:【BUUCTF-RSA3】
解题思路: 涉及知识点为共模攻击
非对称加密算法RSA的深度解析,在CTF中RSA题目_第6张图片

import gmpy2
import binascii

n = 22708078815885011462462049064339185898712439277226831073457888403129378547350292420267016551819052430779004755846649044001024141485283286483130702616057274698473611149508798869706347501931583117632710700787228016480127677393649929530416598686027354216422565934459015161927613607902831542857977859612596282353679327773303727004407262197231586324599181983572622404590354084541788062262164510140605868122410388090174420147752408554129789760902300898046273909007852818474030770699647647363015102118956737673941354217692696044969695308506436573142565573487583507037356944848039864382339216266670673567488871508925311154801
c1 = 22322035275663237041646893770451933509324701913484303338076210603542612758956262869640822486470121149424485571361007421293675516338822195280313794991136048140918842471219840263536338886250492682739436410013436651161720725855484866690084788721349555662019879081501113222996123305533009325964377798892703161521852805956811219563883312896330156298621674684353919547558127920925706842808914762199011054955816534977675267395009575347820387073483928425066536361482774892370969520740304287456555508933372782327506569010772537497541764311429052216291198932092617792645253901478910801592878203564861118912045464959832566051361
c2 = 18702010045187015556548691642394982835669262147230212731309938675226458555210425972429418449273410535387985931036711854265623905066805665751803269106880746769003478900791099590239513925449748814075904017471585572848473556490565450062664706449128415834787961947266259789785962922238701134079720414228414066193071495304612341052987455615930023536823801499269773357186087452747500840640419365011554421183037505653461286732740983702740822671148045619497667184586123657285604061875653909567822328914065337797733444640351518775487649819978262363617265797982843179630888729407238496650987720428708217115257989007867331698397
e1 = 11187289
e2 = 9647291

s = gmpy2.gcdext(e1,e2)
a = s[1]
b = s[2]

if a<0:
    a = -a
    c1 = gmpy2.invert(c1,n)
else:
    b = -b
    c2 = gmpy2.invert(c2,n)
m = (gmpy2.powmod(c1,a,n)*gmpy2.powmod(c2,b,n))%n
print(binascii.unhexlify(hex(m)[2:]))

3.14 已知( e,n1,c1,n2,c2),求m

示例:【CTF秀-easyrsa2】
解题思路: 两组数中e相同,n,c不同,求出n1与n2的最大公因数即为p,之后就可以得到q和d,从而求解m。

import gmpy2
import binascii

e = 65537
n1 = 23686563925537577753047229040754282953352221724154495390687358877775380147605152455537988563490716943872517593212858326146811511103311865753018329109314623702207073882884251372553225986112006827111351501044972239272200616871716325265416115038890805114829315111950319183189591283821793237999044427887934536835813526748759612963103377803089900662509399569819785571492828112437312659229879806168758843603248823629821851053775458651933952183988482163950039248487270453888288427540305542824179951734412044985364866532124803746008139763081886781361488304666575456680411806505094963425401175510416864929601220556158569443747
c1 = 1627484142237897613944607828268981193911417408064824540711945192035649088104133038147400224070588410335190662682231189997580084680424209495303078061205122848904648319219646588720994019249279863462981015329483724747823991513714172478886306703290044871781158393304147301058706003793357846922086994952763485999282741595204008663847963539422096343391464527068599046946279309037212859931303335507455146001390326550668531665493245293839009832468668390820282664984066399051403227990068032226382222173478078505888238749583237980643698405005689247922901342204142833875409505180847943212126302482358445768662608278731750064815

n2 = 22257605320525584078180889073523223973924192984353847137164605186956629675938929585386392327672065524338176402496414014083816446508860530887742583338880317478862512306633061601510404960095143941320847160562050524072860211772522478494742213643890027443992183362678970426046765630946644339093149139143388752794932806956589884503569175226850419271095336798456238899009883100793515744579945854481430194879360765346236418019384644095257242811629393164402498261066077339304875212250897918420427814000142751282805980632089867108525335488018940091698609890995252413007073725850396076272027183422297684667565712022199054289711
c2 = 2742600695441836559469553702831098375948641915409106976157840377978123912007398753623461112659796209918866985480471911393362797753624479537646802510420415039461832118018849030580675249817576926858363541683135777239322002741820145944286109172066259843766755795255913189902403644721138554935991439893850589677849639263080528599197595705927535430942463184891689410078059090474682694886420022230657661157993875931600932763824618773420077273617106297660195179922018875399174346863404710420166497017196424586116535915712965147141775026549870636328195690774259990189286665844641289108474834973710730426105047318959307995062

p = gmpy2.gcd(n1,n2)
q = n1 // p
phi = (p-1)*(q-1)

d = gmpy2.invert(e,phi)
m = gmpy2.powmod(c1,d,n1)

print(binascii.unhexlify(hex(m)[2:]))

3.15 已知(p+q,p-q, e,c),求m

示例:[BJDCTF 2nd]rsa0
解题脚本:

import gmpy2
import libnum
e=16300321

a=21350430512059560135536506725886192791652921782342757815537127809818896096167861777432862988721624947176730121127946250044713187944377040826978092675745896

b=1553262765888789433201396543987134442184487100865056152409628170591088051337453032936901834118611146414395714768350794090251064953913440485676167006809370

c=54505145716437017236783669089525458569996474667747952435007039609752579283598944353442923680602360632342975079757448484712025793719352475806343163818881133707590318426509468029706897810742965068881431810720947035196632950024324040788801133194474150406380691624739115334015886740557921339305357167098392744905

p = (a+b)//2
q = (a-b)//2

phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)

m = gmpy2.powmod(c,d,p*q)
print(libnum.n2s(m))

3.16 已知(e,n,c),求m

示例:【CTF秀-easyrsa1】
解题思路:
可以分解n得到p,q,在线分解大整数网址 。

脚本代码如下:

import gmpy2
import binascii

e = 65537
n = 1455925529734358105461406532259911790807347616464991065301847
c = 69380371057914246192606760686152233225659503366319332065009
p = 1201147059438530786835365194567
q = 1212112637077862917192191913841

phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = gmpy2.powmod(c,d,n)

print(binascii.unhexlify(hex(m)[2:]))

3.17已知(e,n,c),求m。(低解密指数攻击)

示例:【CTF秀-easyrsa5】
解题思路: 题中e很大,故可知是低解密指数攻击。
可以使用破解脚本:求出d的值,文件下载地址 https://github.com/pablocelayes/rsa-wiener-attack
(注意,这里要将破解脚本和rsa-wiener-attack的py文件放在同一个目录下)

import gmpy2
import binascii
import RSAwienerHacker

e = 284100478693161642327695712452505468891794410301906465434604643365855064101922252698327584524956955373553355814138784402605517536436009073372339264422522610010012877243630454889127160056358637599704871937659443985644871453345576728414422489075791739731547285138648307770775155312545928721094602949588237119345
n = 468459887279781789188886188573017406548524570309663876064881031936564733341508945283407498306248145591559137207097347130203582813352382018491852922849186827279111555223982032271701972642438224730082216672110316142528108239708171781850491578433309964093293907697072741538649347894863899103340030347858867705231
c = 350429162418561525458539070186062788413426454598897326594935655762503536409897624028778814302849485850451243934994919418665502401195173255808119461832488053305530748068788500746791135053620550583421369214031040191188956888321397450005528879987036183922578645840167009612661903399312419253694928377398939392827

d = RSAwienerHacker.hack_RSA(e,n)
m = gmpy2.powmod(c,d,n)

print(binascii.unhexlify(hex(m)[2:]))

3.18 分解n得到p,q,求m

适用情况:n已知且可因式分解

既然n = p*q,那么最常规的想法就是把n因式分解得到p,q,上面说n很难分解,但对于一些不太大的n,我们可以借助工具去分解它。下面介绍两种常规因式分解方法:

第一种:在线因式分解网站,例如factordb.com,我们可以利用在线网站快速分解出p,q

第二种:yafu大数分解工具,windows下载地址:yafu download | SourceForge.net使用相关命令分解n:

yafu-x64 factor(n) //常规分解n
yafu-x64 “factor(@)” -batchfile 1.txt //把n复制到txt文件中再分解,用于n过长的情况

脚本

import gmpy2
from Crypto.Util.number import long_to_bytes
 
 
q = 189239861511125143212536989589123569301
p = 386123125371923651191219869811293586459
 
e = 65537
c = 28767758880940662779934612526152562406674613203406706867456395986985664083182
# n = 73069886771625642807435783661014062604264768481735145873508846925735521695159
n = q*p
# print(n)
d = gmpy2.invert(e, (p - 1) * (q - 1))
print("d=",d)
m = pow(c, d, n)
print(m)
print(long_to_bytes(m))

3.20已知c,hint,n,e求m

这一道题目需要进行模运算。p q无法啊直接通过n分解出来,但仔细分析n和phi(n)我们可以发现公约数是p,那么我们的突破点就在这。
通过题目可以发现直接求出phi(n)是不切实际的,那我们只需要让phi存在于某一个式子即可。
下面给出脚本:

from Crypto.Util.number import *
import math
import gmpy2
import Crypto.Util.number
n=1232865496850144050320992645475166723525103370117149219196294373695624167653495180701004894188767069545579706264513808335877905149818445940067870026924895990672091745229251935876434509430457142930654307044403355838663341948471348893414890261787326255632362887647279204029327042915224570484394917295606592360109952538313570951448278525753313335289675455996833500751672463525151201002407861423542656805624090223118747404488579783372944593022796321473618301206064979
hint=611144874477135520868450203622074557606421849009025270666985817360484127602945558050689975570970227439583312738313767886380304814871432558985582586031211416586296452510050692235459883608453661597776103386009579351911278185434163016083552988251266501525188362673472772346212970459561496301631587043106524741903627979311997541301471894670374945556313285203740782346029579923650160327646876967315182335114575921178144825057359851607166387868294019144940296084605930
c =1135954814335407362237156338232840769700916726653557860319741136149066730262056907097728029957898420630256832277578506404721904131425822963948589774909272408535427656986176833063600681390871582834223748797942203560505159946141171210061405977060061656807175913366911284450695116982731157917343650021723054666494528470413522258995220648163505549701953152705111304471498547618002847587649651689203632845303117282630095814054989963116013144483037051076441508388998829
e =0x10001
x=pow(e,e,n)
#求出e**e模n
y = gmpy2.invert(x, n)
#求出1/(e*e)模n
a = (hint-y)%n
p=math.gcd(a,n)
q=n//p**2
phi = (p - 1) * (q - 1)*p
d = gmpy2.invert(e, phi)
m=pow(c,d,n)
m=Crypto.Util.number.long_to_bytes(m)
print(m)

四、总结

今天对RSA的原理进行了讲解,并且收集了一些CTF中RSA攻击的脚本,这些脚本基本包括了基础的应用。整个逻辑还是需要对整个过程进行推导,这些推导需要一定的数学知识。好吧,今天就分享到这里。每天学习每天进步。

你可能感兴趣的:(CTF密码学,网络安全,CTF中RSA,RSA算法推导,CTF,Python脚本破解RSA算法,CTF中常见的RSA攻击,RSA)