defgen_key(): p = random_prime(2^512, lbound=2^511) q = random_prime(2^512, lbound=2^511) n = p * q
a11, a12, a21 = [random_prime(2^100) for _ inrange(3)] a22 = random_prime(2^100) while a11 * a22 == a12 * a21: a22 = random_prime(2^100) A = Matrix(ZZ, [[a11, a12], [a21, a22]])
a1 = crt([a11, a21], [p, q]) a2 = crt([a12, a22], [p, q]) b = a1 * inverse_mod(a2, n) % n
PK = PublicKey(n, b) SK = SecretKey(p, q, A)
return (PK, SK)
defencrypt(m, pk): assert0 < m < 2^400 r = randint(0, 2^400-1) c = (pk.b*m + r) % pk.n return c
defdecrypt(c, sk): a2 = crt([sk.A[0,1], sk.A[1,1]], [sk.p, sk.q]) s1 = a2 * c % sk.p s2 = a2 * c % sk.q m, r = sk.A.solve_right(vector([s1, s2])) return m
deftest(pk, sk, num=3): for _ inrange(num): m = randint(0, 2^400-1) c = encrypt(m, pk) mm = decrypt(c, sk) assert m == mm
if __name__ == '__main__': from hashlib import sha256 from secret import m, FLAG
assert FLAG == 'd3ctf{%s}' % sha256(int(m).to_bytes(50, 'big')).hexdigest()
PK, SK = gen_key() test(PK, SK)
c = encrypt(m, PK)
print(f"PK = {PK}") print(f"c = {c}")
我们重点看看加密函数
也就是
那么我们可以得到
这样就可以通过LLL算法还原出m了
EXP
1 2 3 4 5 6 7 8 9 10
from hashlib import sha256 n = 69804507328197961654128697510310109608046244030437362639637009184945533884294737870524186521509776189989451383438084507903660182212556466321058025788319193059894825570785105388123718921480698851551024108844782091117408753782599961943040695892323702361910107399806150571836786642746371968124465646209366215361 b = 65473938578022920848984901484624361251869406821863616908777213906525858437236185832214198627510663632409869363143982594947164139220013904654196960829350642413348771918422220404777505345053202159200378935309593802916875681436442734667249049535670986673774487031873808527230023029662915806344014429627710399196 c = 64666354938466194052720591810783769030566504653409465121173331362654665231573809234913985758725048071311571549777481776826624728742086174609897160897118750243192791021577348181130302572185911750797457793921069473730039225991755755340927506766395262125949939309337338656431876690470938261261164556850871338570
A = Matrix(ZZ,[[1,0,b],[0,2^400,c],[0,0,n]]) A = A.LLL() m = int(A[0][0]) flag = 'd3ctf{%s}' % sha256(int(m).to_bytes(50, 'big')).hexdigest() print(flag)
simpleGroup
题目分析
这道题的题目如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
from random import randint from secret import FLAG
# A gift for key recovery in challenge [babyLattice] n = 69804507328197961654128697510310109608046244030437362639637009184945533884294737870524186521509776189989451383438084507903660182212556466321058025788319193059894825570785105388123718921480698851551024108844782091117408753782599961943040695892323702361910107399806150571836786642746371968124465646209366215361 y = 12064801545723347322936991186738560311049061235541031580807549422258814170771738262264930441670708308259694588963224372530498305648578520552038029773849342206125074212912788823834152785756697757209804475031974445963691941515756901268376267360542656449669715367587909233618109269372332127072063171947435639328 e = 1928983487
M = int.from_bytes(FLAG, 'big') C = [] while M != 0: m = M % e M //= e r = randint(0, n-1) c = power_mod(y, m, n) * power_mod(r, e, n) C.append(c % n)
n = 69804507328197961654128697510310109608046244030437362639637009184945533884294737870524186521509776189989451383438084507903660182212556466321058025788319193059894825570785105388123718921480698851551024108844782091117408753782599961943040695892323702361910107399806150571836786642746371968124465646209366215361 b = 65473938578022920848984901484624361251869406821863616908777213906525858437236185832214198627510663632409869363143982594947164139220013904654196960829350642413348771918422220404777505345053202159200378935309593802916875681436442734667249049535670986673774487031873808527230023029662915806344014429627710399196 c = 64666354938466194052720591810783769030566504653409465121173331362654665231573809234913985758725048071311571549777481776826624728742086174609897160897118750243192791021577348181130302572185911750797457793921069473730039225991755755340927506766395262125949939309337338656431876690470938261261164556850871338570
A = Matrix(ZZ,[[1,0,b^2],[0,1,b],[0,0,n]]) A = A.LLL()
#!/usr/bin/env python from Crypto.Util.number import * import gmpy2
p = 7669036313101194621345265255994200133006921565596653797956940811601516306410232120057637504305295677357422367597831138570269733177579895994340511712373309 q = 9102122415165681824420871673621781250311822805618731863628192549895693024247220594372897360668046264863189831887100676431439200352775676467952192600956629 n = 69804507328197961654128697510310109608046244030437362639637009184945533884294737870524186521509776189989451383438084507903660182212556466321058025788319193059894825570785105388123718921480698851551024108844782091117408753782599961943040695892323702361910107399806150571836786642746371968124465646209366215361 y = 12064801545723347322936991186738560311049061235541031580807549422258814170771738262264930441670708308259694588963224372530498305648578520552038029773849342206125074212912788823834152785756697757209804475031974445963691941515756901268376267360542656449669715367587909233618109269372332127072063171947435639328 e = 1928983487 e1 = 36493 e2 = 52859
defGCRT(mi, ai): assert (isinstance(mi, list) andisinstance(ai, list)) curm, cura = mi[0], ai[0] for (m, a) inzip(mi[1:], ai[1:]): d = gmpy2.gcd(curm, m) c = a - cura assert (c % d == 0) K = c // d * gmpy2.invert(curm // d, m // d) cura += curm * K curm = curm * m // d cura %= curm return (cura % curm, curm)
defcheck(d,p,n): if((p - 1) % n == 0): returnpow(d,(p - 1) // n,p) == 1 else: k = gmpy2.gcd(n, p - 1) returnpow(d,(p - 1) // k,p) == 1
defgetM(c,e,p): for i inrange(2,e): tmpc = (c * gmpy2.invert(pow(y,i,p),p)) % p if check(tmpc,p,e): return i exit(0)
C = [63173987757788284988620600191109581820396865828379773315280703314093571300861961873159324234626635582246705378908610341772657840682572386153960342976445563045427986000105931341168525422286612417662391801508953619857648844420751306271090777865836201978470895906780036112804110135446130976275516908136806153488, 9763526786754236516067080717710975805995955013877681492195771779269768465872108434027813610978940562101906769209984501196515248675767910499405415921162131390513502065270491854965819776080041506584540996447044249409209699608342257964093713589580983775580171905489797513718769578177025063630080394722500351718, 37602000735227732258462226884765737048138920479521815995321941033382094711120810035265327876995207117707635304728511052367297062940325564085193593024741832905771507189762521426736369667607865137900432117426385504101413622851293642219573920971637080154905579082646915297543490131171875075081464735374022745371, 1072671768043618032698040622345664216689606325179075270470875647188092538287671951027561894188700732117175202207361845034630743422559130952899064461493359903596018309221581071025635286144053941851624510600383725195476917014535032481197737938329722082022363122585603600777143850326268988298415885565240343957, 27796821408982345007197248748277202310092789604135169328103109167649193262824176309353412519763498156841477483757818317945381469765077400076181689745139555466187324921460327576193198145058918081061285618767976454153221256648341316332169223400180283361166887912012807743326710962143011946929516083281306203120, 27578857139265869760149251280906035333246393024444009493717159606257881466594628022512140403127178174789296810502616834123420723261733024810610501421455454191654733275226507268803879479462533730695515454997186867769363797096196096976825300792616487723840475500246639213793315097434400920355043141319680299224, 29771574667682104634602808909981269404867338382394257360936831559517858873826664867201410081659799334286847985842898792091629138292008512383903137248343194156307703071975381090326280520578349920827357328925184297610245746674712939135025013001878893129144027068837197196517160934998930493581708256039240833145, 33576194603243117173665354646070700520263517823066685882273435337247665798346350495639466826097821472152582124503891668755684596123245873216775681469053052037610568862670212856073776960384038120245095140019195900547005026888186973915360493993404372991791346105083429461661784366706770467146420310246467262823, 5843375768465467361166168452576092245582688894123491517095586796557653258335684018047406320846455642101431751502161722135934408574660609773328141061123577914919960794180555848119813522996120885320995386856042271846703291295871836092712205058173403525430851695443361660808933971009396237274706384697230238104, 61258574367240969784057122450219123953816453759807167817741267194076389100252707986788076240792732730306129067314036402554937862139293741371969020708475839483175856346263848768229357814022084723576192520349994310793246498385086373753553311071932502861084141758640546428958475211765697766922596613007928849964, 13558124437758868592198924133563305430225927636261069774349770018130041045454468021737709434182703704611453555980636131119350668691330635012675418568518296882257236341035371057355328669188453984172750580977924222375208440790994249194313841200024395796760938258751149376135149958855550611392962977597279393428] m = 0 for c in C[::-1]: cp = c % p cq = c % q m1 = getM(cp,e1,p) m2 = getM(cq,e2,q) mm,lcm = GCRT([e1,e2],[m1,m2]) print("Get mm: " + hex(mm)) m *= e m += mm
import socketserver from Crypto.PublicKey import RSA from Crypto.Util.number import getPrime , bytes_to_long from Curve import MyCurve from hashlib import sha256 import os import string import random import signal from secret import flag
BIT = 2048 p = 9688074905643914060390149833064012354277254244638141162997888145741631958242340092013958501673928921327767591959476890238698855704376126231923819603296257
classTask(socketserver.BaseRequestHandler):
defproof_of_work(self): random.seed(os.urandom(8)) proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ inrange(20)]) _hexdigest = sha256(proof.encode()).hexdigest() self.send(f"sha256(XXXX+{proof[4:]}) == {_hexdigest}".encode()) self.send(b'Give me XXXX: ') x = self.recv() iflen(x) != 4or sha256(x+proof[4:].encode()).hexdigest() != _hexdigest: self.send('wrong') returnFalse returnTrue
defrecv(self): data = self.request.recv(1024) return data.strip()
#!/usr/bin/env python import string, gmpy2 from hashlib import sha256 from pwn import * context.log_level = "debug"
dic = string.ascii_letters + string.digits
defsolvePow(prefix,h): for a1 in dic: for a2 in dic: for a3 in dic: for a4 in dic: x = a1 + a2 + a3 + a4 proof = x + prefix.decode("utf-8") _hexdigest = sha256(proof.encode()).hexdigest() if _hexdigest == h.decode("utf-8"): return x
defgetData(): r.recvuntil("n = ") n = int(r.recvuntil("\n", drop = True)) r.recvuntil("e = ") e = int(r.recvuntil("\n", drop = True)) r.recvuntil("x0 = ") x0 = int(r.recvuntil("\n", drop = True)) r.recvuntil("x1 = ") x1 = int(r.recvuntil("\n", drop = True)) offset = 2 << 1024 offset_e = int(pow(offset, e, n)) v = ((offset_e * x0 - x1) * gmpy2.invert(offset_e - 1, n)) % n r.sendlineafter("v = ",str(v)) r.recvuntil("m0_ = ") m0 = int(r.recvuntil("\n", drop = True)) r.recvuntil("m1_ = ") m1 = int(r.recvuntil("\n", drop = True)) m = (m0 * offset - m1) % n x = m // offset + 1 y = x * offset - m return x,y
r = remote("47.100.50.252",10000) r.recvuntil("sha256(XXXX+") prefix = r.recvuntil(") == ", drop = True) h = r.recvuntil("\n", drop = True) result = solvePow(prefix,h) r.sendlineafter("Give me XXXX: \n",result)
r.recvuntil("p = ") r.recvuntil("\n", drop = True) r.recvuntil("D = ") D = int(r.recvuntil("\n", drop = True))
# exp.sage load("Curve.sage") import os, random from Crypto.Util.number import *
p = 9688074905643914060390149833064012354277254244638141162997888145741631958242340092013958501673928921327767591959476890238698855704376126231923819603296257 F = GF(p) fac = [2^21,3^10,7^4,11,13^2,17,19,29,31,37,43^3,47,71,83,89,97,223,293,587,631,709,761,1327,1433,1733,1889,2503,3121,6043,6301,49523,98429,140683,205589,1277369,1635649,5062909,45698189,67111151,226584089,342469397]
defbsgs(g, y, p): m = int(ceil(sqrt(p - 1))) S = {} point = (u,0) for i inrange(m): point = curve.add(point,g) pointg = point[0] << 800 | point[1] S[pointg] = i
gs = curve.mul(m,g) for i inrange(m): pointy = y[0] << 800 | y[1] if pointy in S: return S[pointy] - i * m + 1 y = curve.add(y,gs) returnNone
defPohlig_Hellman(G,P): ea = [] na = [] for i inrange(len(fac)): c = fac[i] n = (p - 1) // c gi = curve.mul(n, G) yi = curve.mul(n, P) ei = bsgs(gi,yi,c) ea.append(ei%c) na.append(c) ee = crt(ea,na) return ee
data = open("data.txt","rb").read().decode("utf-8") data = data.split("\n")
from elgamal import elgamal import socketserver from prikey import server_prikey , AlicePasswd from pubkey import Alice_pubkey from secret import Alice_flag , ctfer_flag import random import signal from os import urandom from Crypto.Util.number import long_to_bytes , bytes_to_long from Crypto.Cipher import AES
MENU = "1. signup 2.signin" XOR = lambda s1,s2 :bytes([x1^x2 for x1 , x2 inzip(s1,s2)]) defpad(m): m += bytes([16 - len(m) % 16] * (16 - len(m) % 16)) return m
defenc_send(self, msg , usrid , enc_key = b''): if enc_key == b'': pubenc = self.pubkey[usrid] y1 , y2 = pubenc.encrypt(bytes_to_long(msg)) self._send(str(y1) + ', ' + str(y2)) else: assertlen(enc_key) == 16 aes = AES.new(enc_key , AES.MODE_ECB) self._send(aes.encrypt(pad(msg))) defdec_recv(self, enc_key = b''): msg = self._recv() if enc_key == b'': c = [int(i) for i in msg.split(b', ')] m = self.prikey.decrypt(c) print(long_to_bytes(m)) return long_to_bytes(m) else: assertlen(enc_key) == 16 aes = AES.new(enc_key , AES.MODE_ECB) return unpad(aes.decrypt(msg)) defsignup(self): iflen(self.passwd) > 5: self._send('sorry, the number of users is out of limit') return0 self._send('please give me your name') userid = self._recv() iflen(userid) > 20: self._send('your id can\'t be too long') return0 elif userid in self.passwd: self._send('the name has been used') return0 else: self._send('please give me your passwd(encrypted)') userpasswd = self.dec_recv() iflen(userpasswd) > 11: self._send('your password can\'t be too long') return0 else: self.passwd[userid] = userpasswd self._send('please give me your publickey') userpubkey = self._recv() try: userpubkey = [int(i) for i in userpubkey[1:-1].split(', ')] except: self._send('publickey format error') self.passwd.pop(userid) return0 self.pubkey[userid] = elgamal(userpubkey) self._send('sign up success') return1
defsignin(self): self._send('please give me your name') userid = self._recv() if userid notin self.passwd: self._send('sorry the userid is not existed') return0 while1: random.seed(urandom(8)) r = random.getrandbits(8 * 11) self._send('please give me your passwd(encrypted and xored by r)') self._send(str(r)) userdata = self.dec_recv() if bytes_to_long(userdata) == r ^ bytes_to_long(self.passwd[userid]): self._send('signin success') break else: self._send('password error') endkey = urandom(5) key = userdata + endkey self._send('now let\'s communicate with this key') self.enc_send(endkey , userid) return userid , key
defhandle(self): signal.alarm(240) key = b'' userid = '' while1: self._send(MENU) choice = self._recv() if choice == b'1': self.signup() elif choice == b'2': temp = self.signin() if temp != 0: userid , key = temp break else: self._send('error') msg = self.dec_recv(enc_key = key) if msg == b'I am a ctfer.Please give me flag': self.enc_send(b'ok, your flag is here ' + ctfer_flag , userid , enc_key= key) elif msg == b'I am Alice, Please give me true flag'and userid == b'Alice': self.enc_send(b'Hi Alice, your flag is ' + Alice_flag , userid , enc_key= key) return0
self._send(str(y1) + ', ' + str(y2)) else: assertlen(enc_key) == 16 aes = AES.new(enc_key , AES.MODE_ECB) self._send(aes.encrypt(pad(msg))) defdec_recv(self, enc_key = b''): msg = self._recv() if enc_key == b'': c = [int(i) for i in msg.split(b', ')] m = self.pridec.decrypt(c) return long_to_bytes(m) else: assertlen(enc_key) == 16 aes = AES.new(enc_key , AES.MODE_ECB) return unpad(aes.decrypt(msg))
defmain(self): firstmsg = self._recv() if firstmsg != b'1. signup 2.signin': return0 self._send('2') self._recv() self._send('Alice') self._recv() r = int(self._recv()) userdata = long_to_bytes(bytes_to_long(AlicePasswd) ^ r) self.enc_send(userdata) self._recv() self._recv() endkey = self.dec_recv() key = userdata + endkey self.enc_send(b'I am a ctfer.Please give me flag' , enc_key = key) return self.dec_recv(enc_key = key)
classTask(socketserver.BaseRequestHandler): def_recv(self): data = self.request.recv(1024) return data.strip()
def_send(self, msg, newline=True): ifisinstance(msg , bytes): msg += b'\n' else: msg += '\n' msg = msg.encode() self.request.sendall(msg) defhandle(self): signal.alarm(60) self._send('Hello, I am Alice, can you tell me the address of the server?\nIn return, I will give you the ctf_flag') try: addr = self._recv() ip, port = [x.strip() for x in addr.split(b':')] port = int(port) except: ip, port = '0.0.0.0', 10001 a = Alice(ip , port) msg = a.main() self._send(b'Thanks, here is your flag') self._send(msg)
Sign Up: S -> U : 'please give me your name' U -> S : userid S : assertlen(userid) < 20and userid notin passwd S -> U : 'please give me your passwd(encrypted)' U -> S : c = elgamal.enc(UserPasswd,ServerPublicKey) S : passwd[userid] = elgamal.dec(c,ServerPrivateKey) S -> U : 'sign up success'
Sign In: S -> U : 'please give me your name' U -> S : userid S : assert userid in passwd S -> U : 'please give me your passwd(encrypted and xored by r)' S -> U : r U -> S : c = elgamal.enc(UserPassWord ^ r,ServerPublicKey) S : assert elgamal.dec(c,ServerPrivateKey) == passwd[userid] ^ r S : key = userdata + endkey, userdata = passwd[userid] ^ r, endkey = urandom(5) S -> U : 'now let\'s communicate with this key' S -> U : k = elgamal.enc(key,UserPasswd) U -> S : m = AES.enc(key,msg) S : dm = AES.dec(key,m) S : if dm == 'I am a ctfer.Please give me flag': S -> U : r1 = AES.enc(key,ctfer_flag) S : if dm == 'I am Alice, Please give me true flag'and userid == 'Alice' S -> U : r2 = AES.enc(key,Alice_flag)
#!/usr/bin/env python from elgamal import elgamal from os import urandom from Crypto.Util.number import * from pwn import * from time import * import random #context.log_level = 'debug'
defattackAlice(rr,m): try: middle_shell = listen(8888) alice_shell = remote("47.100.0.15",10003) alice_shell.recvuntil(b"Hello, I am Alice, can you tell me the address of the server?\nIn return, I will give you the ctf_flag\n") alice_shell.sendline("xxxx:8888") # xxxx -> your vps's ip middle_shell.sendline(b'1. signup 2.signin') middle_shell.recv() middle_shell.sendline(b'please give me your name') middle_shell.recv() middle_shell.sendline(b'please give me your passwd(encrypted and xored by r)') middle_shell.sendline(str(rr)) middle_shell.recv() middle_shell.sendline(b'signin success') middle_shell.sendline(b'now let\'s communicate with this key') middle_shell.sendline(str(m[0]) + ', ' + str(m[1])) sleep(0.3) result = middle_shell.recv() if result != b"": middle_shell.close() alice_shell.close() returnTrue except: if middle_shell: middle_shell.close() if alice_shell: alice_shell.close() returnFalse
known_pwd = b""
# 0x35343764643163636333xx for i inrange(11): for r inrange(0,256): rr = ((bytes_to_long(known_pwd) << 8) + r) << ((11 - i - 1) * 8) print("try:" + hex(rr)) msg = b"A" * (5 + i) c = enc(msg) ifnot attackAlice(rr,c): known_pwd += long_to_bytes(r) print(known_pwd.hex()) break
#!/usr/bin/env python from elgamal import elgamal from os import urandom from Crypto.Util.number import * from pwn import * from time import * import random #context.log_level = 'debug'
known_pwd = "547dd1ccc3" server_shell = remote("47.100.0.15",10001) server_shell.sendlineafter("\n","2") server_shell.recvuntil("please give me your name\n") server_shell.sendline("Alice") for c in dic: server_shell.recvuntil("please give me your passwd(encrypted and xored by r)\n") rr = int(server_shell.recvline()) pwd = bytes_to_long((known_pwd + c).encode()) prefix = long_to_bytes(pwd ^ rr) assert(len(prefix) == 11) y1 , y2 = pubenc.encrypt(pwd ^ rr) server_shell.sendline(str(y1) + ', ' + str(y2)) result = server_shell.recv() ifb"success"in result: print(known_pwd + c) break
defcombineKey(m,rr): for i inrange(3): sleep(0.3) try: middle_shell = listen(8888) alice_shell = remote("47.100.0.15",10003) alice_shell.recvuntil(b"Hello, I am Alice, can you tell me the address of the server?\nIn return, I will give you the ctf_flag\n") alice_shell.sendline("xxxx:8888") # xxxx -> your vps's ip middle_shell.sendline(b'1. signup 2.signin') middle_shell.recv() middle_shell.sendline(b'please give me your name') middle_shell.recv() middle_shell.sendline(b'please give me your passwd(encrypted and xored by r)') middle_shell.sendline(str(rr)) middle_shell.recv() middle_shell.sendline(b'signin success') middle_shell.sendline(b'now let\'s communicate with this key') middle_shell.sendline(str(m[0]) + ', ' + str(m[1])) sleep(0.5) result = middle_shell.recv() print(result) if result != b"": middle_shell.close() alice_shell.close() returnTrue except: if middle_shell: middle_shell.close() if alice_shell: alice_shell.close() returnFalse
server_shell = remote("47.100.0.15",10001) server_shell.sendlineafter("\n","2") server_shell.recvuntil("please give me your name\n") server_shell.sendline("Alice") server_shell.recvuntil("please give me your passwd(encrypted and xored by r)\n") rr = int(server_shell.recvline()) prefix = long_to_bytes(pwd ^ rr) assert(len(prefix) == 11) y1 , y2 = pubenc.encrypt(pwd ^ rr) server_shell.sendline(str(y1) + ', ' + str(y2)) server_shell.recvuntil("now let's communicate with this key\n") y1,y2 = [int(i) for i in server_shell.recvuntil("\n", drop = True).decode("utf-8").split(", ")] print(y1,y2) success("Get communicate key:" + str(y1) + "," + str(y2))
l = 0 h = 2**40 idx = 0 prefix_length = 0 bound = 2**40 count = 0 flag = False