第1个题是个LCG问题,通过一堆参数生成两个序列,如果flag位为1则输出x序列为0则输出 y序列
from random import randint
xcoeff=[2220881165502059873403292638352563283672047788097000474246472547036149880673794935190953317495413822516051735501183996484673938426874803787946897055911986,3780868071235160215367199770952656972709510983146503211692869296836254519620768737356081836837102329626660962468333562050121427935761471039362287802941597,4902413424318450578332022710023815992030030940432088134156375736636296016273860394626141407089100644225364129305706233708267009976783719598126300552264686]
ycoeff=[10133630993576627916260025550504106878405253409844193620608338129978685236278362029266353690006955194818074387390350472504283291952199370441443295790407675,3364000239596805500788439152587586988694473612770420810400457954622820421525205173981972752548906690775960238564395459369815397933405749174182967563999094, 5184466564604150683447715719961919989718796968566745874607480183961791804239357212974694797397047787503590843234526492414458478882622032364603797888695699]
p=10369539704979520345376943788090457296701518777268113122376443474930073612795297691185597789473973789467303121639140064504782927997022419913721978857764263
class LCG:
def __init__(self,p,xcoeffs,ycoeffs):
self.p=p
self.xcoeffs=xcoeffs
self.ycoeffs=ycoeffs
self.xstate =randint(1,p-1)
self.ystate =randint(1,p-1)
for i in range(randint(1,1337)):
self.next()
def next(self):
self.xstate=pow(self.xcoeffs[0]+self.xcoeffs[1]*self.xstate+self.xcoeffs[2]*self.xstate**2,1,self.p)
self.ystate=pow(self.ycoeffs[0]+self.ycoeffs[1]*self.ystate+self.ycoeffs[2]*self.ystate**2,1,self.p)
def encrypt(self,msg):
bin_msg=list(map(int, list(f"{msg:0512b}")))
encrypted=[]
for i in bin_msg:
self.next()
if i==1:
encrypted.append(self.xstate)
else:
encrypted.append(self.ystate)
return encrypted
flag=b"Securinets{???????????????????????????????????????}"
flag=int.from_bytes(flag,"big")
lcgCipher=LCG(p,xcoeff,ycoeff)
encrypted_flag=lcgCipher.encrypt(flag)
print("encrypted_flag=",encrypted_flag)
当第1个给定后这人LCG就能算出来,只需要其中一个序列即可。
from output import encrypted_flag
xcoeff=[...]
ycoeffs=[...]
p=...
v = '0'
ystate = encrypted_flag[0]
for i in range(1, len( encrypted_flag )):
ystate=( ycoeffs[0]+ycoeffs[1]*ystate+ycoeffs[2]*ystate**2 ) %p
if encrypted_flag[i] == ystate:
v += '0'
else:
v += '1'
print(v)
m = ''.join([chr(int(v[i:i+8],2)) for i in range(0, 512, 8)])
print(m)
#Securinets{1e9Endre_5ymBO1s_goEs_brrrrrrrrrrrrrrrrrrrrrrrrrr}
这题犯了个低级错误一直没作出来,后来发现写反了。
用椭圆曲线的签名,但使用了一个有明显问题的pub_hash函数。
先把名字用json打包后转整型再模O,当输入40个字符发生碰撞后即可生成相同的pub_hash值。pub_hash相同签名也就相同了。
from fastecdsa.curve import P192
from fastecdsa.point import Point
from secrets import randbelow,flag,banner,menu
from Crypto.Util.number import bytes_to_long,inverse
from string import ascii_uppercase
import json
#P192 Order
O=6277101735386680763835789423176059013767194773182842284081
d=randbelow(O)
G=Point(0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811,curve=P192)
P=d*G
def pub_hash(m):
return (bytes_to_long(m.encode())%O)>>60
def ecdsa_sign(m):
h = pub_hash(m)
k = randbelow(O)
r = (k * G).x % O
s = (inverse(k, O) * (h + r * d)) % O
return json.dumps({"r":r,"s":s})
def verify(msg,r,s):
h=pub_hash(msg)
if r > 0 and r < O and s > 0 and s < O:
u1=(h*inverse(s,O))%O
u2=(r*inverse(s,O))%O
V=u1*G+u2*P
if r==V.x:
return True
return False
print(banner)
print(menu)
normal_user=["JAKC","YASSINE"]
for i in range(2):
try:
choice=json.loads(input())
if "option" not in choice or "name" not in choice:
print("Give me a option and a message next time")
continue
if choice["option"]=="sign":
name=choice["name"]
if any(i not in ascii_uppercase for i in name) or len(name)!=40:
print("give me a strong and long name next time")
normal_user.append(name)
payload=json.dumps({"username":name,"admin":"false"})
print(ecdsa_sign(payload))
if choice["option"]=="verify_admin":
if "r" not in choice or 's' not in choice :
print("Remember to return with the admin signature next time")
continue
if choice["name"] in normal_user:
print("Dont Try to cheat your way through!")
continue
payload=json.dumps({"username":choice["name"],"admin":"truee"})
if verify(payload,choice['r'],choice['s']):
print("Welcome back admin",flag)
else:
print("You seemed to send something wrong try again")
continue
except:
pass
40个字符去碰撞,第个变化的int值作为参数求一个与中间值的差。
当输入N*40时会产生一个hash值h0,与目的值h1的差作为变更目标,就变成了一个背包问题。用格求解。
行求差值
O=6277101735386680763835789423176059013767194773182842284081
def pub_hash(m):
return (bytes_to_long(m.encode())%O)>>60
v1 = json.dumps({"username":"NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","admin":"truee"})
#'{"username": "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", "admin": "truee"}'
h1 = bytes_to_long(v1.encode())%O
v2 = json.dumps({"username":"YASSINE","admin":"truee"})
#v2 = '{"username": "YASSINE", "admin": "truee"}' #normal_user=["JAKC","YASSINE"]
h2 = bytes_to_long(v2.encode())%O
hx = (((h2-h1))%O)
print('h1:',h1>>60)
print('h2:',h2>>60)
print(hx)
再求背包问题。这里直接用>>60可能会有误差,所以少移几位,并从结果中找到一个最接近的值,恰好这个相等。
O = 6277101735386680763835789423176059013767194773182842284081
x = 3302636172704920594268150250909543749562995783341298138374
#x>>60 = 2187014057453355045706725449238469327308
nbit = 40
M = matrix(ZZ, nbit+1,nbit+1)
for i in range(nbit+1):
M[i,i] = 1
M[i,nbit] = (2**(160+i*8)%O)>>56
M[-1,-1] = x>>56
res = M.LLL()
for i in range(nbit+1):
if all(abs(v)<13 for v in res[i]) :
s = 0
for j in range(nbit):
s += res[i][j]*M[j,-1]
print(res[i])
print(s)
#----check---
k = (2, -8, 4, -1, -3, -6, 1, -6, 5, 0, -8, -10, 3, -6, 0, 6, 3, 4, 1, -5, 2, 5, -6, 5, -1, -1, -4, -4, 3, 2, -4, 2, -6, 0, -1, 1, -1, 3, 7, 2, 0)
生成 name并验证
name = ''
for i in range(nbit):
name += chr(ord('N')+k[i])
print(name)
v0 = json.dumps({"username":"NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","admin":"truee"})
h0 = bytes_to_long(v0.encode())%O
v1 = json.dumps({"username":name[::-1],"admin":"false"})
h1 = bytes_to_long(v1.encode())%O
v2 = json.dumps({"username":"YASSINE","admin":"truee"})
h2 = bytes_to_long(v2.encode())%O
print(v1,v2,'\n',h0>>60,'\n',h1>>60,'\n',h2>>60)
'''
{"username": "PUQMOMNHPJPQJJMMSHSPIORQTNHQDFNSHOHKMRFP", "admin": "false"} {"username": "YASSINE", "admin": "truee"}
3669927246502793964990422003272902381467
1089989626468487772900189775859714399277
1089989626468487772900189775859714399277
'''