HECTF2022 Crypto 部分题解
本次HECTF,由于学业繁忙,挑了些题目做一做。
流动的音符:♭♭♫♭♭§‖♭∮♭♯♩‖♭♪‖♩♫‖♭‖♭‖§♭‖♩‖♬♫♭‖‖‖♬∮‖¶♩♭‖♪‖♬♯♭♯♪‖¶¶‖♬♭♭‖♪‖♬♫§=
直接网页在线解密,得到EA>N?s:WZgTdPYbMSaYg
古典密码无非移位和替换,分析前面字母与HECTF的关系可以发现是变异凯撒,初始密钥=3,后面依次+1.最后得出flag。
ezrsa:
from Crypto.Util.number import * from secret import flag flag = b'xxx' e = 114 m = bytes_to_long(flag) p = getPrime(1024) q = getPrime(1024) t = getPrime(1024) n = p * q * t p_=pow(p,2,n) q_=pow(q,2,n) c = pow(m,e,n) print('p_=',p_) print('q_=',q_) print('c=',c) print('n=',n) #p_= 10660749010264526666955869622200514149424664070021154725214604278423033834800955315638637946982741577976025615843487738805576629855459529381681679497064453109727962183277768658053394103348827822686515016677449953958986089293779870089604784750116267441026319440135025236091029928565442799040007751858012409498271852333017388486644053877238274838173771344350870565886676055860728949042361028753924290647753862707042472944714140635484722345522648010064713004854479094986010632316750770118044301903260988074471243247031854872785324506292730778884664223412372663828159205320038546293395502275887356885181013870536857351801 #q_= 24900409366873586425973971191854411152048453357438215578406168704445779543895031579176888535442469919297663892450230816720758414920791049333275007446412352293152157437672026001378469357187698312455020558413101033543700131403373834030395855212901673914686297701313223697181049265286011127188695284002470629178098454764536315245968458622929902214839704674718996340182311301099900271312644919770585429288043854743210617868761990329037081770477261306489047429460937057125193231432195877922731165870197358946683698077175950756482605399815830687563398277515452842563143685190688865084064679712177247354049377034394880941369 #c= 946358882688806235743551077996671406469185038565566907261383734984318844703303437873183869084536703835433988817350857866089668970925835657856975155167500190428922521871327955274363186305180350899397478897928581580727458938934640786146518171503388507311655160765881370401217708135845031083189007308497775864484758699096082815479602777639307812516934937183952478316508418895341680335172973583094238147073379957772209947376051520041093030641369536800448737539973770258342422560893630082723217759837690008955748444973711508371077927468399703456466637348191192859278206925769696645636969358967735037470196395844215361527039288120664704552775460536654859848091685928057224735031528303041212702445718384890182474053295656578327780048497422707815820736647212902522526653039676698263673166412650104420869762547385554961873764933774143297622712766521201037469301912471740996998228799841957283759679784569638149555093498363791420486340 #n= 1677924010415009671349677258549532467848510897335579570922114838282842960143799964694977371357046837674443739542407516581076865550606801686170400793463690366665534118961173768008603133641864003317727610676872685077700753537755254540591236871020140458419596610210236431401477173114522177145982007059709616618279936170223104755776796458682957656555154039384483954754660803554302451221585280396378564648495919069459351016010016636012245082009946238467068412198769348889950331295680906811430325690102055808865038151762131291269197341984605959088829226733422023970618165958725486675321766767430347929319621215891165857544847088373700410007500868721335483070938971597851859953792409442485301373327127595552457801719192824050415833073999094005750868115932130442747899994421453654008731830580286370350900523295205445599466666709544075950517531382971246869745425091317996973135364990272852701046046315136273893166361180330563013617843
阅读代码,第一步无非就是通过开方得出p,q,然后得到t,从而得到phi(n)
先看p_=pow(p,2,n),展开便是p**2=p_+i*n,我们可以通过爆破得出p的值,q同理。
下面丢出脚本:
i = 0 while True: if gmpy2.iroot((p_ + i * n), 2)[1] == True: p =gmpy2.iroot((p_ + i * n), 2)[0] break i += 1 i = 0 while True: if gmpy2.iroot((q_ + i * n), 2)[1] == True: q =gmpy2.iroot((q_ + i * n), 2)[0] break i += 1 t=n//(p*q)
下面求出phi(n),本人的想法是这题直接顺利成章的出来。但发现逆元不存在。因此下面应该处理逆元不存在的问题。
phii=(t-1)*(q-1) if p%(q*t)==0: phi=phii*p else: phi=phii*(p-1) b=math.gcd(e,phi) #求出公约数 bb=e//b a=gmpy2.invert(bb,phi) #由于bb和phi互素,逆元可求 mm=pow(c,a,n) #c=m**e mod n 可知c**a=m**(b*bb*a)modn 由于bb*a=1 mod phi所以m**b=c**a mod n
下面对mm开方就行
给出完整脚本:
import math import gmpy2 from Crypto.Util.number import * p_= 10660749010264526666955869622200514149424664070021154725214604278423033834800955315638637946982741577976025615843487738805576629855459529381681679497064453109727962183277768658053394103348827822686515016677449953958986089293779870089604784750116267441026319440135025236091029928565442799040007751858012409498271852333017388486644053877238274838173771344350870565886676055860728949042361028753924290647753862707042472944714140635484722345522648010064713004854479094986010632316750770118044301903260988074471243247031854872785324506292730778884664223412372663828159205320038546293395502275887356885181013870536857351801 q_= 24900409366873586425973971191854411152048453357438215578406168704445779543895031579176888535442469919297663892450230816720758414920791049333275007446412352293152157437672026001378469357187698312455020558413101033543700131403373834030395855212901673914686297701313223697181049265286011127188695284002470629178098454764536315245968458622929902214839704674718996340182311301099900271312644919770585429288043854743210617868761990329037081770477261306489047429460937057125193231432195877922731165870197358946683698077175950756482605399815830687563398277515452842563143685190688865084064679712177247354049377034394880941369 c= 946358882688806235743551077996671406469185038565566907261383734984318844703303437873183869084536703835433988817350857866089668970925835657856975155167500190428922521871327955274363186305180350899397478897928581580727458938934640786146518171503388507311655160765881370401217708135845031083189007308497775864484758699096082815479602777639307812516934937183952478316508418895341680335172973583094238147073379957772209947376051520041093030641369536800448737539973770258342422560893630082723217759837690008955748444973711508371077927468399703456466637348191192859278206925769696645636969358967735037470196395844215361527039288120664704552775460536654859848091685928057224735031528303041212702445718384890182474053295656578327780048497422707815820736647212902522526653039676698263673166412650104420869762547385554961873764933774143297622712766521201037469301912471740996998228799841957283759679784569638149555093498363791420486340 n= 1677924010415009671349677258549532467848510897335579570922114838282842960143799964694977371357046837674443739542407516581076865550606801686170400793463690366665534118961173768008603133641864003317727610676872685077700753537755254540591236871020140458419596610210236431401477173114522177145982007059709616618279936170223104755776796458682957656555154039384483954754660803554302451221585280396378564648495919069459351016010016636012245082009946238467068412198769348889950331295680906811430325690102055808865038151762131291269197341984605959088829226733422023970618165958725486675321766767430347929319621215891165857544847088373700410007500868721335483070938971597851859953792409442485301373327127595552457801719192824050415833073999094005750868115932130442747899994421453654008731830580286370350900523295205445599466666709544075950517531382971246869745425091317996973135364990272852701046046315136273893166361180330563013617843 e = 114 i = 0 while True: if gmpy2.iroot((p_ + i * n), 2)[1] == True: p =gmpy2.iroot((p_ + i * n), 2)[0] break i += 1 i = 0 while True: if gmpy2.iroot((q_ + i * n), 2)[1] == True: q =gmpy2.iroot((q_ + i * n), 2)[0] break i += 1 t=n//(p*q) phii=(t-1)*(q-1) if p%(q*t)==0: phi=phii*p else: phi=phii*(p-1) b=math.gcd(e,phi) #求出公约数 bb=e//b a=gmpy2.invert(bb,phi) #由于bb和phi互素,逆元可求 mm=pow(c,a,n) #c=m**e mod n 可知c**a=m**(b*bb*a)modn 由于bb*a=1 mod phi所以m**b=c**a mod n m=gmpy2.iroot(mm,b)[0] print(long_to_bytes(m))
#sage p=235322474717419 a=0 b=8856682 k= E = EllipticCurve(GF(p), [a, b]) P = E.random_point() P.order()==p Q=k*P aes_key=k print("P:",P) print("Q:",Q) #P=E(180571547161769,227820272156445) #Q=E(76765539897460,69715189045993)
从python脚本可以看出是aes ecb解密
key通过sagemath计算获取
我们知道,Q=kP,想要直接求k是很难的。但这题规定了P.order==p所以可以通过smart‘s attack
#sagemath def SmartAttack(P,Q,p): E = P.curve() Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + randint(0,p)*p for t in E.a_invariants() ]) P_Qps = Eqp.lift_x(ZZ(P.xy()[0]), all=True) for P_Qp in P_Qps: if GF(p)(P_Qp.xy()[1]) == P.xy()[1]: break Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True) for Q_Qp in Q_Qps: if GF(p)(Q_Qp.xy()[1]) == Q.xy()[1]: break p_times_P = p*P_Qp p_times_Q = p*Q_Qp x_P,y_P = p_times_P.xy() x_Q,y_Q = p_times_Q.xy() phi_P = -(x_P/y_P) phi_Q = -(x_Q/y_Q) k = phi_Q/phi_P return ZZ(k) p=235322474717419 a=0 b=8856682 E = EllipticCurve(GF(p), [a, b]) P=E(180571547161769,227820272156445) Q=E(76765539897460,69715189045993) n = SmartAttack(P, Q, p) n
得到的n就是我们key
下面直接简简单单的解密就ok了
给出解密脚本
from Crypto.Cipher import AES import base64 from Crypto.Util.number import * def pad(text): while len(text) % 16 != 0: text += b' ' return text def pad_key(key): while len(key) % 16 != 0: key += b' ' return key aes_key=b'152675955744921' aes = AES.new(pad_key(aes_key), AES.MODE_ECB) enc='bXaw/g8fD7taMjlL/OyqUJluD6dZI5GkZb9RrE5GQk8=' dec=base64.b64decode(enc) flag=aes.decrypt(pad(dec)) print(flag)
over,由于比较忙,其他题目没怎么看,有机会再看吧,毕竟孩子只是个大一密码新手,呜呜~