红明谷 RSA Attack 源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 from gmpy2 import *from Crypto.Util.number import *import sympyimport randomfrom secret import flagp1 = getPrime(1024 ) print (p1)p2 = p1 - random(999 ,99999 ) print (p2)p_1=1 for i in range (1 ,p1+1 ): p_1*=i p3 = sympy.nextPrime(p_1 % p2 ) p4 = p3 >> 50 << 50 p = p4 while (isPrime(P)!=1 ): P = p + random.randint(0 ,2 **50 ) Q = getPrime(1024 ) e = 1 +1 +1 N = P * Q print (N)flag=bytes_to_long(flag) c = pow (flag,e,N) print (c)
小明文攻击,明文的e次方应该还是小于n的。e=3,我就直接开立方了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from gmpy2 import *from Crypto.Util.number import *import sympyimport randomc=15839981826831548396886036749682663273035548220969819480071392201237477433920362840542848967952612687163860026284987497137578272157113399130705412843449686711908583139117413 import binasciiimport gmpy2n=28592245028568852124815768977111125874262599260058745599820769758676575163359612268623240652811172009403854869932602124987089815595007954065785558682294503755479266935877152343298248656222514238984548734114192436817346633473367019138600818158715715935132231386478333980631609437639665255977026081124468935510279104246449817606049991764744352123119281766258347177186790624246492739368005511017524914036614317783472537220720739454744527197507751921840839876863945184171493740832516867733853656800209669179467244407710022070593053034488226101034106881990117738617496520445046561073310892360430531295027470929927226907793 e=0x3 c=15839981826831548396886036749682663273035548220969819480071392201237477433920362840542848967952612687163860026284987497137578272157113399130705412843449686711908583139117413 m=gmpy2.iroot(c,3 )[0 ] print (binascii.unhexlify(hex (m)[2 :].strip("L" )))
上面应该可能是非预期,如果e不是3的话,这样子应该无法出来。复现的时候,我又去看了这题,
应该是要p的高位攻击。
分解N,然后还原flag
p1,p2,得到p3 然后得到p4 ,然后就是已知P的高位攻击,分解N
从p3 到p4 应该是 用了威尔逊定理。
1 威尔逊定理的关键是对于q的阶乘模p,可以转化为q+1 到p-2的连续相乘的乘积,再模p。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 from gmpy2 import * from Crypto.Util.number import long_to_bytes def mod_wei(A,B): x = A-1 y = B+1 for i in range(y,A): x = x * invert(i,A) % A return x p1=172071201093945294154292240631809733545154559633386758234063824053438835958515543354911249971174172649606257936857627547311760174511316984409767738981247877005802155796623587461774104951797122995266217334158736848307655543970322950339988489801672160058805422153816950022590644650247595501280192205506649936031 p2=172071201093945294154292240631809733545154559633386758234063824053438835958515543354911249971174172649606257936857627547311760174511316984409767738981247877005802155796623587461774104951797122995266217334158736848307655543970322950339988489801672160058805422153816950022590644650247595501280192205506649902034 #p3= mod_wei(p1,p2) #print(p3) p3=160982581279105537186230949968010846334069661071385183704558558938383537788651229395962449002163226151233185856482914815662503177251193050871399494532428039118332505888442957982145678662895591402248999182594697979354004338008106874254484818121348413465427849474144720352989794604959912183767726559982548429793 p4 = p3 >> 50 << 50 print(p4) #160982581279105537186230949968010846334069661071385183704558558938383537788651229395962449002163226151233185856482914815662503177251193050871399494532428039118332505888442957982145678662895591402248999182594697979354004338008106874254484818121348413465427849474144720352989794604959912183767726080171538644992 n=28592245028568852124815768977111125874262599260058745599820769758676575163359612268623240652811172009403854869932602124987089815595007954065785558682294503755479266935877152343298248656222514238984548734114192436817346633473367019138600818158715715935132231386478333980631609437639665255977026081124468935510279104246449817606049991764744352123119281766258347177186790624246492739368005511017524914036614317783472537220720739454744527197507751921840839876863945184171493740832516867733853656800209669179467244407710022070593053034488226101034106881990117738617496520445046561073310892360430531295027470929927226907793 e=3 #pbits= P原本的位数 #kbits=50 #pbits - p4.nbits() #print (p4.nbits()) #p4 = p4 << kbits PR.<x> = PolynomialRing(Zmod(n)) f = x + p4 roots = f.small_roots(X=2^50,beta=0.4) # 经过以上一些函数处理后,n和p已经被转化为10进制 print(roots[0]) p = (p4 + int(roots[0])) q = n / p print(p,q) p=160982581279105537186230949968010846334069661071385183704558558938383537788651229395962449002163226151233185856482914815662503177251193050871399494532428039118332505888442957982145678662895591402248999182594697979354004338008106874254484818121348413465427849474144720352989794604959912183767727132253838484207 q=177610799885216739150033783146077389227466398992304797544722690728333710953487671530493258740965088305627405288824231917292714174121900818996934776913022138727504199805088260088131522902226168795919423586361902747010589234723472919051971498366624013144923656034967709726568992428063756766270448058244581455999 phi = (p-1)*(q-1) d = invert(3,phi) c=15839981826831548396886036749682663273035548220969819480071392201237477433920362840542848967952612687163860026284987497137578272157113399130705412843449686711908583139117413 flag = pow(c,d,n) print(flag) print(long_to_bytes(flag)) #b'flag{w0_x1hu1n_y0u_b5st}'
ezCRT 源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 from Crypto.Util.number import *import gmpy2from random import shuffleflag = b"flag is here" def shuffle_flag (s ): str_list = list (s) shuffle(str_list) return '' .join(str_list) nl = [] el = [] count = 0 while count != 5 : p = getPrime(512 ) q = getPrime(512 ) n = p * q phi = (p - 1 ) * (q - 1 ) d = gmpy2.next_prime(bytes_to_long(flag)) e = gmpy2.invert(d, phi) nl.append(n) el.append(int (e)) count += 1 print (nl)print (el)d=31698494962194579373261419409 c1=[706565317398633346290694952311166623770389747503953970254889622211015097472765489676349936599997109100148837713409666075736711752497174928509516666210124850782396573268200919345005742905131769799719677758163730270857245509037860252700476102090438501579886321486095767737006847692632649652528793934802014895 , 39976293505792731417500342473259466413746324373570160856607039564687056797068114044891309890160001547746290678089875953230720229396293686037539133378586045964793387433679304899158546834837314101138069400994334720071006048815998660691472991971598192116289517127819703723844842002711298154106615035755646791235 , 82622936948791971063481195310587447614375265630407688161651173440160941964839173273115526802240672776681580169092371677673709037579318090622040018030730165371997331146171751228791524747622285256591779419274845659567001522182995468819720594650389854677582186770321424062935881407083956991646633760500152137305 , 47924672523033740219454774309397006543851002473271747603676349322670782245519637286314088457132590816165876451615235937683074852920250584155682791595116359054889940842281324709426616771765312825842634237678243213350551342690870568516232078792788925700389762945955053433276153136302757700081859531596237286407 , 157462720644970256050843434459828247139256140406409429896418317109064365936294939244159292550184482469972819258184119865598346921909220060266145241164734603316978286567811044606538176157224828857158099074286931716459626013079677895357212211176535500327064375073662684801175545519382470886239209020257096407424 ] e1=[69312028009355287369151190914681978515224902099126626288106202481561083869512381976466800912049172557479956400189281179789850182367192324370292880508005951892909864237831856642160554901550928757105750738313195248541515727624216048436593804176317465366380022764459799506858495981817822670957526705611211712923 , 75652848678989239962391202584125835503829570694373189157636155436633908234362973839251550542975725789188895010096917574118924190081886365041870173203566890015476761857546914959928731140619341634983144909962106759048918025248827973161384045263311189477657141886093632791593341193393085433749877270828641736687 , 33787880341418355427411601538315129862488529656310145182009801227014512555036822623215545927750632031483856865027938518144081751233475248361490189179988637342429805607352670543555743822390555949569061340741015073482051059972283793490798701339277926430357560613555427570475360496737455291914090967005368044847 , 45894271603047945281790624112313938740541711331584775481261776728213544262108835859642003140814571796838418889270625806159755478669858113687476417240730385707171289922064965084283027730393146219788228689778873266618663473231744646293406030907691363263939114550226424730102211751706087680590823466426973879111 , 39462780066564051085365889083337472288277223628014907704844994419242541623368920096395581667207909872944692627394665038729398405841875334128211337544205143876652949004817962123951132753801707134333132359039376283331685997619531570270269964807335633423631078057345827010794671894948828680193958561375351954627 ] n1=[92568419674731290088321621356482160506897805615722568594108449347104924357404183476911642777855820991398881156764068184840768873749718093598712551142529474514837161712525386555067489900887826033760157015587905876891826276883359425048106383489316555600680137377034136599761900203863336332834524981581608546277 , 156396473818563541024482014372866929605198443382524196879362284224099117401220679011156723462510565131555949471059964179767945960498473012008220045105490122503438703770112687917922899337041421537937431868908340506324082719417747902320117904166584374628828367801012533926776313544525573302674702867896838756349 , 158394833243620345170313957479796081390446308753163267294427471181012679879060921676287361174926310080500003540773261012005682050743188110335872216992843352902160171999286576526304619756655278142788064189969927027027650043645613441449926633380809295720977302961310978360575684689811662689798196832145977450067 , 160088237013152996062303719345275590040820298863729670660621544625451638541931139026114480452748397901155923890465415946150076272684251867169893163248736673419035618274961179288085209456220719404244194802327491684233804878013160262798831738441790443743813368173495029170393018727204042599457829167334217403039 , 176125361422384852665447804150030174008849487020728296169340093618559367127086381778331613043595010796295772394708222184703701230685609172767761426620379001062695169120599393984950488304290958534830276649464003949555105491117656796777657620812669612752464591728873199832200616338112460100967288829163217253937 ] cl = [] flag = shuffle_flag(flag.decode()).encode() flag = '' for i in range (len (nl)): cl.append(pow (bytes_to_long(flag), el[i], nl[i])) print (cl)
私钥d是相同的,五组e,n,c,就是五组方程式m = c^d mod n
利用格做LLL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from gmpy2 import * from Crypto.Util.number import long_to_bytes c=[706565317398633346290694952311166623770389747503953970254889622211015097472765489676349936599997109100148837713409666075736711752497174928509516666210124850782396573268200919345005742905131769799719677758163730270857245509037860252700476102090438501579886321486095767737006847692632649652528793934802014895, 39976293505792731417500342473259466413746324373570160856607039564687056797068114044891309890160001547746290678089875953230720229396293686037539133378586045964793387433679304899158546834837314101138069400994334720071006048815998660691472991971598192116289517127819703723844842002711298154106615035755646791235, 82622936948791971063481195310587447614375265630407688161651173440160941964839173273115526802240672776681580169092371677673709037579318090622040018030730165371997331146171751228791524747622285256591779419274845659567001522182995468819720594650389854677582186770321424062935881407083956991646633760500152137305, 47924672523033740219454774309397006543851002473271747603676349322670782245519637286314088457132590816165876451615235937683074852920250584155682791595116359054889940842281324709426616771765312825842634237678243213350551342690870568516232078792788925700389762945955053433276153136302757700081859531596237286407, 157462720644970256050843434459828247139256140406409429896418317109064365936294939244159292550184482469972819258184119865598346921909220060266145241164734603316978286567811044606538176157224828857158099074286931716459626013079677895357212211176535500327064375073662684801175545519382470886239209020257096407424] e=[69312028009355287369151190914681978515224902099126626288106202481561083869512381976466800912049172557479956400189281179789850182367192324370292880508005951892909864237831856642160554901550928757105750738313195248541515727624216048436593804176317465366380022764459799506858495981817822670957526705611211712923, 75652848678989239962391202584125835503829570694373189157636155436633908234362973839251550542975725789188895010096917574118924190081886365041870173203566890015476761857546914959928731140619341634983144909962106759048918025248827973161384045263311189477657141886093632791593341193393085433749877270828641736687, 33787880341418355427411601538315129862488529656310145182009801227014512555036822623215545927750632031483856865027938518144081751233475248361490189179988637342429805607352670543555743822390555949569061340741015073482051059972283793490798701339277926430357560613555427570475360496737455291914090967005368044847, 45894271603047945281790624112313938740541711331584775481261776728213544262108835859642003140814571796838418889270625806159755478669858113687476417240730385707171289922064965084283027730393146219788228689778873266618663473231744646293406030907691363263939114550226424730102211751706087680590823466426973879111, 39462780066564051085365889083337472288277223628014907704844994419242541623368920096395581667207909872944692627394665038729398405841875334128211337544205143876652949004817962123951132753801707134333132359039376283331685997619531570270269964807335633423631078057345827010794671894948828680193958561375351954627] n=[92568419674731290088321621356482160506897805615722568594108449347104924357404183476911642777855820991398881156764068184840768873749718093598712551142529474514837161712525386555067489900887826033760157015587905876891826276883359425048106383489316555600680137377034136599761900203863336332834524981581608546277, 156396473818563541024482014372866929605198443382524196879362284224099117401220679011156723462510565131555949471059964179767945960498473012008220045105490122503438703770112687917922899337041421537937431868908340506324082719417747902320117904166584374628828367801012533926776313544525573302674702867896838756349, 158394833243620345170313957479796081390446308753163267294427471181012679879060921676287361174926310080500003540773261012005682050743188110335872216992843352902160171999286576526304619756655278142788064189969927027027650043645613441449926633380809295720977302961310978360575684689811662689798196832145977450067, 160088237013152996062303719345275590040820298863729670660621544625451638541931139026114480452748397901155923890465415946150076272684251867169893163248736673419035618274961179288085209456220719404244194802327491684233804878013160262798831738441790443743813368173495029170393018727204042599457829167334217403039, 176125361422384852665447804150030174008849487020728296169340093618559367127086381778331613043595010796295772394708222184703701230685609172767761426620379001062695169120599393984950488304290958534830276649464003949555105491117656796777657620812669612752464591728873199832200616338112460100967288829163217253937] a = [0]*6 a[0]=[0,e[0],e[1],e[2],e[3],e[4]] a[1]=[0,-n[0],0,0,0,0] a[2]=[0,0,-n[1],0,0,0] a[3]=[0,0,0,-n[2],0,0] a[4]=[0,0,0,0,-n[3],0] a[5]=[0,0,0,0,0,-n[4]] A =matrix(ZZ,a) A[0,0]= n[0]^0.5 A B = A.LLL() d = B[0][0]/ A[0][0] print(long_to_bytes(d)) # b'flag{9b73a84b-5e32-433a-bc8f-6f8a6d2793db}paddip\x0f'
babyForgery 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 import osimport stringimport randomimport socketserverimport signalfrom hashlib import sha256from ocb.aes import AES from ocb import OCBFLAG = BLOCKSIZE = 16 MENU = br""" [1] Encrypt [2] Decrypt [3] Get Flag [4] Exit """ class Task (socketserver.BaseRequestHandler ): def _recvall (self ): BUFF_SIZE = 2048 data = b'' while True : part = self.request.recv(BUFF_SIZE) data += part if len (part) < BUFF_SIZE: break return data.strip() def send (self, msg, newline=True ): try : if newline: msg += b'\n' self.request.sendall(msg) except : pass def recv (self, prompt=b'> ' ): self.send(prompt, newline=False ) return self._recvall() def recvhex (self, prompt=b'> ' ): return bytes .fromhex(self.recv(prompt=prompt).decode('latin-1' )) def proof_of_work (self ): random.seed(os.urandom(128 )) proof = '' .join(random.choices(string.ascii_letters+string.digits, k=20 )) _hexdigest = sha256(proof.encode()).hexdigest() self.send(str .encode("sha256(XXXX+%s) == %s" % (proof[4 :], _hexdigest))) x = self.recv(prompt=b'Give me XXXX: ' ) if len (x) != 4 or sha256(x+proof[4 :].encode()).hexdigest() != _hexdigest: return False return True def timeout_handler (self, signum, frame ): self.send(b"\n\nTIMEOUT!!!\n" ) raise TimeoutError def encrypt (self, nonce, message, associate_data=b'' ): assert nonce not in self.NONCEs self.NONCEs.add(nonce) self.ocb.setNonce(nonce) tag, cipher = self.ocb.encrypt(bytearray (message), bytearray (associate_data)) return (bytes (cipher), bytes (tag)) def decrypt (self, nonce, cipher, tag, associate_data=b'' ): self.ocb.setNonce(nonce) authenticated, message = self.ocb.decrypt( *map (bytearray , (associate_data, cipher, tag)) ) if not authenticated: raise ValueError('REJECT' ) return bytes (message) def handle (self ): signal.signal(signal.SIGALRM, self.timeout_handler) signal.alarm(60 ) if not self.proof_of_work(): return aes = AES(128 ) self.ocb = OCB(aes) KEY = os.urandom(BLOCKSIZE) self.ocb.setKey(KEY) self.NONCEs = set () while True : USERNAME = self.recv(prompt=b'Enter username > ' ) if len (USERNAME) > BLOCKSIZE: self.send(b"I can't remember long names" ) continue if USERNAME == b'Alice' : self.send(b'Name already used' ) continue break signal.alarm(60 ) while True : self.send(MENU, newline=False ) try : choice = int (self.recv(prompt=b'Enter option > ' )) if choice == 1 : nonce = self.recvhex(prompt=b'Enter nonce > ' ) message = self.recvhex(prompt=b'Enter message > ' ) associate_data = b'from ' + USERNAME ciphertext, tag = self.encrypt(nonce, message, associate_data) self.send(str .encode(f"ciphertext: {ciphertext.hex ()} " )) self.send(str .encode(f"tag: {tag.hex ()} " )) elif choice == 2 : nonce = self.recvhex(prompt=b'Enter nonce > ' ) ciphertext = self.recvhex(prompt=b'Enter ciphertext > ' ) tag = self.recvhex(prompt=b'Enter tag > ' ) associate_data = self.recvhex(prompt=b'Enter associate data > ' ) message = self.decrypt(nonce, ciphertext, tag, associate_data) self.send(str .encode(f"message: {message.hex ()} " )) elif choice == 3 : nonce = self.recvhex(prompt=b'Enter nonce > ' ) ciphertext = self.recvhex(prompt=b'Enter ciphertext > ' ) tag = self.recvhex(prompt=b'Enter tag > ' ) associate_data = b'from Alice' message = self.decrypt(nonce, ciphertext, tag, associate_data) if message == b'please_give_me_the_flag' : self.send(FLAG) elif choice == 4 : break else : break except : self.send(b'Error!' ) break signal.alarm(0 ) self.send(b'Bye!' ) self.request.close() class ForkedServer (socketserver.ForkingMixIn, socketserver.TCPServer ): pass if __name__ == "__main__" : HOST, PORT = '0.0.0.0' , 10000 print (HOST, PORT) server = ForkedServer((HOST, PORT), Task) server.allow_reuse_address = True server.serve_forever()
看着还好的样子。进去首先是遇到一个sha256,通过proof_is_work
然后键入username, 用户名长度小于BLoCKSIZE(16),并且不能等于Alice
choice==1:encrypt
choice==2:decrypt
choice==3:Get flag
我们重点先看choice==3
明文是b’please_give_me_the_flag’
随机的密钥associate_data是 b’from Alice’
现在也就是说我们需要tag 、ciphertext 和nonce。
我门可以利用choice==1 来拿到tag,ciphertext ,其实nonce很随意,想用啥用啥的
这里要注意的是choice==1 中的随机密钥associate_data 是和我们最初输入的username有关的。
但如果我们的username 不等于Alice,那我们得到的密文ciphertext 也就不能正确的解出原来的明文了。
到这里,我们似乎陷入了僵局。一方面,username 不等于Alice。另一方面username 又需要等于Alice。
突然想到之前做的一套题,有关AES_EBC的。就是通过将故意构造的密文体院原密文,从而篡改信息的一种攻击方法。
虽然现在还是不会,但好歹有了一点突破口。也就是这题的考点应该在于构造。至于如何构造,暂时我还不会。
另外,源码里告诉了我们flag的一部分东西
1 FLAG = #####REDACTED#####
另外还有题目的描述XE vs XEX
百谷了很久。找到了18年19年国外(似乎是俄罗斯)的几场比赛,有类似的,关于OBC2的攻击。
这是github上一个实现ocb模式的纯python库,应该有利于我们解题
CTF zone-quals-2019 的一道有关OCB2的题目
除了上面俄罗斯的那题,还有一个hxp CTF 2018 的oops2
这题暂时只能到这里。
呜呜
这道题相关的paper还没看完,待我撸完,看看能不能做吧。
呜呜