题目源码:
from Crypto.Util.number import getPrime, bytes_to_long
from secret import flag
import gmpy2
import random
def pad(s,i):
return i * pow(3,s.bit_length()) + s**2
def gen_N():
return getPrime(512) * getPrime(512)
assert len(flag) == 54
invite = bytes_to_long(flag)
e_list = [random.choice([3,5,7]) for i in range(14)]
N_list = [gen_N() for i in range(14)]
with open('./invitations','w') as f:
for i in range(14):
invis = pow(pad(invite,i+1),e_list[i],N_list[i])
f.write('Invitation%d: %d \n'%(i+1,invis))
f.write('Wait a minute! \n')
for i in range(14):
f.write('[e%d,N%d]: [%d,%d]\n'%(i+1,i+1,e_list[i],N_list[i]))
输出内容:
#invitations
Invitation1: 2726880165485794753015221799903015469859604350960070462389832770775190258204902795671085685627736110579803076064313238826997962227132535666379117171603278182417820587346210511971127809627876548907651538393737303011542136469304569045407566630840981287558726831003180186144633381044057099863505591978316576331
Invitation2: 52844103418322232725177561034428083147725292376614668718220523666259095447694889972949103379829470432332480992707892007073319952276490981511612735696207090391646476749895265951654074573797235607971038590694835782189124391368712277613425337912212240432011011071881837734857743183367019103096901117395938690572
Invitation3: 129274519334082165644106292383763271862424981496822335330342328217347928093592453953990448827969549377883054831490973006383371688359344675312001881631556371220779971357039899721241880304156884612458373310254854821837978876725801047977081900824202659636258168216028784656056334358157381820784576207338479493823
Invitation4: 56852637683122735164568970875066131746509133403072354742812890131597805562226047560392266004050592533316793038372256396537829143627478792510526346644756590135871716813976819138793368813440386409129373327577756689416990858633825538766694242123021009535005392002648416127869437948525458000795891155650312894218
Invitation5: 24933581882539143383805596779774030477763512752520375486982562296903063067503747125713029403793101373585417342942950790457235350083784905974251188305010098928244056980941419687746319300184530161551239060873604405554973757867815783641391659818219177575212360602858057667033472530286856616676363511656764861866
Invitation6: 7491476722927235473944826192371870577426352529433316210668760004930228302472920679959949471665143237333356259221787618020560963460668303766902416340056446225333025453011937952801159044781738493694911250765543392959285625650198325627539546777165439291150376527665779894748453633305704694635029402487576286720
Invitation7: 46994515206702516116723205176259615067102717099690856936455392000070823814544052445278146449282379251128163008476565339875497253781717590664182753552262233895322322657625202522815172174432182181682631558679857615390973133346476079858014623412440411395083299226947371458955797627789607079672039131280242758091
Invitation8: 8140023566779187828652447593867705813386781164538611122714708931585587727699213769519135028841126072130625547328311301696554048174772606261707345115571968105138543476580875347239912760797035694220505996377127309341770427102697008350472060971360460756799310951343070384766137332401117333917901167639276168214
Invitation9: 8385766476371753553977800353128766303065572190592509929058486984964439147256960481698015327599879810752997804957814193113184978479627127131318723231581432235920975812354556190022727375961505764199831794239507708621401077801662954349957627630157786326057704380977697746043041515978455150985893713987598581167
Invitation10: 25434511525127530194830986592289179576070740435049947678930286998924519588985583799757299734846614343604661534391991096353170465467791358514448923161460366596251448937540153262731348684727026598527904328268639060306102090278287818149679940661579357649191023269947102746200467430583428889484549034314463114080
Invitation11: 9435583236354598287661880148272717764447540972316605192855157484524753847806158586224733743434644389385148450722945845355791145016665856388503878165725148745517696840251674049929524448078129458846254866804153080766917319923905682824180976106679633180818527967145571143203594244851742143986040226240019541346
Invitation12: 42653412322252936189967169320174001935456500265020295381235749570735595316912049949245536609634786767873783560657460914097412643705264107040560389003526999720357122717443215007182355846769697457076620951388839672721527406861414375682603373503445636748304326212654026233985520038237509837611802457243967916967
Invitation13: 50163996128508874413636370533324079468893191391677157815578286348174669089976633631417431754505804284298354381223186985949160012660340790440711469708712479223582014168361667639570586425626182863344576254691662799762136734638820942002509860333817967414572002225418810272184173820322912928927789061077468994953
Invitation14: 55181712049788569218094734913693030675622116883683701002270524678292896232044695586872582672159854063365203462010143885417632291300773699604618481578372258936513301821561273604986211363808846581429372811764533701610119228124866223770584249909429743735157839245622925997548481946831963456454939343358587988983
Wait a minute!
[e1,N1]: [5,90361246179367799606636863352077187566064794796456461177972505143929614628873639223638940051613378291778175724735519020067052934403115774679961661481160141872257338930620863078688082915958381094674423803586734810828570206667419458295735288184697613296663226516640069281835035704453280781694226293902395215269]
[e2,N2]: [5,83202136479583179143205059354864808364257451670037867814548678142629716115373207061455185843132942837300718212806534861585785041547496145915392175827479376792813058845422044909477892978293495048968520853100992244672416436363272286740068846609018921112995562647093952700070707124842514243806528982910520604851]
[e3,N3]: [3,146694460234280339612721415368435987068740712812770728817136582256341063038147863645902264969297892447333024201649306207442798919845916187823646745721109151386096190207317810424580842120750075213595282979568495342617919336417068886973047979116994072272482630372638964064972815256237040541007947708358680368391]
[e4,N4]: [7,145212137982314671207105886550619275956842416412937060552686822638155412950680057688522218990023473104787006548449644240065948769143660097622695125682017688804838701293738298008178105057147539522368965730223561911750657089352591376219016726977232279206451303896573325330139830440927228125810665303608828462177]
[e5,N5]: [5,69335368232766044823545542187513771534967902179150417021053554241638095909666122935053210964003511014870892979205875153115719406287728162111662254890513324436473313860142126335197489227724691042286796058111753972895113145188906829975189506125997319609609974126645475084944238417929532560409919420929255247813]
[e6,N6]: [5,93889543065608951579836429313520485233295158467296710329997599807630401722519056218864031741675898621375735347229494633577571323057785261271373295860331130588582231771193563731092603614818963592931492474988532068227153492022582339704874613690044001529412669510094771064646843676765163737757104643318364446839]
[e7,N7]: [7,66174700839404221060785862467924299511645570336361033287335855493589093141782896451863402373425798838446538369142584932156150350565382116869446083154097803842190010954019565857767923584979615770650706675094209251111816761431713779074557571353022624477001770694207393369796369620048999514683357963227119554487]
[e8,N8]: [3,65031485534704406281490718325237831433086480239135617407356760819741796565231283220528137697949585150709734732370203390254643835828984376427852793969716489016520923272675090536677771074867975287284694860155903327351119710765174437247599498342292671117884858621418276613385329637307269711179183430246951756029]
[e9,N9]: [5,72454311940971803130612024751128556938725737742029062979349607787083978826668706819793864356790325653817555839762732164812521831864626411495002267399139766907846534945632792910468487287154661692733986224962564621615361536373173705359255153606552352581704159462310354407361311378558150604159961029937052901709]
[e10,N10]: [3,126172075578367446151297289668746433680600889845504078949758568698284471307000358407453139846282095477016675769468273204536898117467559575203458221600341760844973676129445394999861380625435418853474246813202182316736885441120197888145039130477114127079444939102267586634051045795627433724810346460217871661901]
[e11,N11]: [3,75691424835079457343374072990750986689075078863640186724151061449621926239051140991748483370587430224317778303489124525034113533087612981452189061743589227565099659070008017454957304620495920813121234552401715857719372861565651204968408267740732475458128601061676264465241188491988485848198323410127587280471]
[e12,N12]: [7,88063052818271125442049408332053226451497067720511502513828848476569985821115735898897947439175727789641390104005400308936768495751619165683456550165811034670341697022370415202614387373196086237042577737857259724530596416810462125219296930758592032765843338961894697491961439584875235274163072466474940670589]
[e13,N13]: [5,86478932133708863968749977073639049451666195461247968321317885106346907736572028122496476049748246757185316498949163898915427948597498506162230927380667345132742891001640364064647368394822175742973968167028656790729030556005407153405955458636780270673780720333871959638216946584461925553782697695137132507853]
[e14,N14]: [7,137641493263428303662262187582231235637921833879366309318941383348412296182252654397496377642861646991438721153462001357875169325595544056465299787575422581289053630686684843044593163904089201855371863459503176022957832807726507152235818181000484878683030989944063049622694810207054366378176225221479695833371]
大概分析一下题目逻辑。flag中有54个字符,转为数字后保存为invite变量。
e_list数组有14个元素,每个元素是3,5,7中的随机值。
N_list数组也有14个元素,每个元素都是两个512bit随机素数的乘积。
接下来就是14轮加密,每轮包含两个步骤
ok,这是一道比较典型的paper题,来源:Twenty Years of Attacks on the RSA Cryptosystem。此处为中文译文参考第4.2章 Hastad’s Broadcast Attack,线性填充条件下的RSA广播攻击。而本题的nb之处是采用了非线性填充。
霍斯塔德还进一步证明,即便使用填充来预防广播攻击,如果填充方案产生的消息相互之间有线性关系,那么只要消息数量k>e,广播攻击仍然可以恢复明文。这种情况下的广播攻击还是基于中国余数定理,但具体的破解方法有赖于线性关系的信息。
先分析一下invite的位数,由于本题flag格式是flag = b’GWHT{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx’
开头几位是固定的,所以可以得出invite的位数:
from Crypto.Util.number import *
flag = b'GWHT{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
invite = bytes_to_long(flag)
print(invite.bit_length())
#431
另外由于解出明文的前提是消息数量k大于指数e,那么第一选择当然是挑出指数e=3的4条消息来做计算。
对于每组N,e=3和c都有 c i ′ = i n v i t e 2 + i × 3 431 c'_i=invite^2+i \times 3^{431} ci′=invite2+i×3431
以及 c i = ( c i ′ ) 3 m o d N i c_i=(c'_i)^3 \mod N_i ci=(ci′)3modNi
同时根据中国剩余定理,当N两两互质时,存在唯一的c满足 c = c i m o d N i c=c_i \mod N_i c=cimodNi
以本题为例,使用crt计算 t 1 = 1 m o d N 1 t 1 = 0 m o d N 2 t 1 = 0 m o d N 3 t 1 = 0 m o d N 4 ⋯ t 4 = 0 m o d N 1 t 4 = 0 m o d N 2 t 4 = 0 m o d N 3 t 4 = 1 m o d N 4 t_1=1 \mod N_1 \\ t_1=0 \mod N_2 \\ t_1=0 \mod N_3 \\ t_1=0 \mod N_4 \\ \cdots \\ t_4=0 \mod N_1 \\ t_4=0 \mod N_2 \\ t_4=0 \mod N_3 \\ t_4=1 \mod N_4 t1=1modN1t1=0modN2t1=0modN3t1=0modN4⋯t4=0modN1t4=0modN2t4=0modN3t4=1modN4
则 c = t 1 c 1 + t 2 c 2 + t 3 c 3 + t 4 c 4 m o d N 1 N 2 N 3 N 4 c=t_1c_1+t_2c_2+t_3c_3+t_4c_4 \mod N_1N_2N_3N_4 c=t1c1+t2c2+t3c3+t4c4modN1N2N3N4
即 0 = t 1 ( ( i n v i t e 2 + 1 × 3 431 ) 3 − c 1 ) + ⋯ + t 4 ( ( i n v i t e 2 + 4 × 3 431 ) 3 − c 4 ) m o d N 1 N 2 N 3 N 4 0=t_1((invite^2+1 \times 3^{431})^3-c_1)+ \\ \cdots \\+t_4((invite^2+4 \times 3^{431})^3-c_4) \mod N_1N_2N_3N_4 0=t1((invite2+1×3431)3−c1)+⋯+t4((invite2+4×3431)3−c4)modN1N2N3N4
invite为未知数,使用Coppersmith方法求解以上有限域方程即得到flag
sage exp:
#sage
# fix some problems
from Crypto.Util.number import long_to_bytes
def linearPaddingHastads(cArray,nArray,aArray,bArray,eArray,eps):
if(len(cArray) == len(nArray) == len(aArray) == len(bArray) == len(eArray)):
for i in range(4):
cArray[i] = Integer(cArray[i])
nArray[i] = Integer(nArray[i])
aArray[i] = Integer(aArray[i])
bArray[i] = Integer(bArray[i])
eArray[i] = Integer(eArray[i])
TArray = [-1]*4
for i in range(4):
arrayToCRT = [0]*4
arrayToCRT[i] = 1
TArray[i] = crt(arrayToCRT,nArray)
P.<x> = PolynomialRing(Zmod(prod(nArray)))
gArray = [-1]*4
for i in range(4):
gArray[i] = TArray[i]*(pow(aArray[i]*x**2 + bArray[i],eArray[i]) - cArray[i])
g = sum(gArray)
g = g.monic()
roots = g.small_roots(epsilon=eps)
if(len(roots)== 0):
print("No Solutions found!")
return -1
return roots
else:
print("Input error!")
def LinearPadding():
eArr = [3 for i in range(4)]
nArr = [
146694460234280339612721415368435987068740712812770728817136582256341063038147863645902264969297892447333024201649306207442798919845916187823646745721109151386096190207317810424580842120750075213595282979568495342617919336417068886973047979116994072272482630372638964064972815256237040541007947708358680368391,
65031485534704406281490718325237831433086480239135617407356760819741796565231283220528137697949585150709734732370203390254643835828984376427852793969716489016520923272675090536677771074867975287284694860155903327351119710765174437247599498342292671117884858621418276613385329637307269711179183430246951756029,
126172075578367446151297289668746433680600889845504078949758568698284471307000358407453139846282095477016675769468273204536898117467559575203458221600341760844973676129445394999861380625435418853474246813202182316736885441120197888145039130477114127079444939102267586634051045795627433724810346460217871661901,
75691424835079457343374072990750986689075078863640186724151061449621926239051140991748483370587430224317778303489124525034113533087612981452189061743589227565099659070008017454957304620495920813121234552401715857719372861565651204968408267740732475458128601061676264465241188491988485848198323410127587280471
]
cArr = [
129274519334082165644106292383763271862424981496822335330342328217347928093592453953990448827969549377883054831490973006383371688359344675312001881631556371220779971357039899721241880304156884612458373310254854821837978876725801047977081900824202659636258168216028784656056334358157381820784576207338479493823,
8140023566779187828652447593867705813386781164538611122714708931585587727699213769519135028841126072130625547328311301696554048174772606261707345115571968105138543476580875347239912760797035694220505996377127309341770427102697008350472060971360460756799310951343070384766137332401117333917901167639276168214,
25434511525127530194830986592289179576070740435049947678930286998924519588985583799757299734846614343604661534391991096353170465467791358514448923161460366596251448937540153262731348684727026598527904328268639060306102090278287818149679940661579357649191023269947102746200467430583428889484549034314463114080,
9435583236354598287661880148272717764447540972316605192855157484524753847806158586224733743434644389385148450722945845355791145016665856388503878165725148745517696840251674049929524448078129458846254866804153080766917319923905682824180976106679633180818527967145571143203594244851742143986040226240019541346
]
aArr = [1 for i in range(4)]
bArr = [i * 3 ** 431 for i in [3,8,10,11]]
msg = linearPaddingHastads(cArr,nArr,aArr,bArr,eArr,eps=1/20)
for i in msg:
print(long_to_bytes(i))
if __name__ == '__main__':
LinearPadding()