强网杯 2025 初赛 wp

check-little

N 和 c 有公因数
可直接将 N 分解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from sage.all import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.Util.number import long_to_bytes, inverse
import gmpy2
from tqdm import *
N = 18795243691459931102679430418438577487182868999316355192329142792373332586982081116157618183340526639820832594356060100434223256500692328397325525717520080923556460823312550686675855168462443732972471029248411895298194999914208659844399140111591879226279321744653193556611846787451047972910648795242491084639500678558330667893360111323258122486680221135246164012614985963764584815966847653119900209852482555918436454431153882157632072409074334094233788430465032930223125694295658614266389920401471772802803071627375280742728932143483927710162457745102593163282789292008750587642545379046283071314559771249725541879213
c = 10533300439600777643268954021939765793377776034841545127500272060105769355397400380934565940944293911825384343828681859639313880125620499839918040578655561456321389174383085564588456624238888480505180939435564595727140532113029361282409382333574306251485795629774577583957179093609859781367901165327940565735323086825447814974110726030148323680609961403138324646232852291416574755593047121480956947869087939071823527722768175903469966103381291413103667682997447846635505884329254225027757330301667560501132286709888787328511645949099996122044170859558132933579900575094757359623257652088436229324185557055090878651740
iv = b'\x91\x16\x04\xb9\xf0RJ\xdd\xf7}\x8cW\xe7n\x81\x8d'
ciphertext = "bf87027bc63e69d3096365703a6d47b559e0364b1605092b6473ecde6babeff2"

p = GCD(N, c)
print(p)
q = N//p
d = inverse(3, (p-1)*(q-1))
key = pow(c, d, N)
cipher= AES.new(key = long_to_bytes(key)[:16], iv = iv, mode = AES.MODE_CBC)
print(cipher.decrypt(bytes.fromhex(ciphertext)))

#flag{m_m4y_6e_divIS1b1e_by_p?!}

ezran

断点伪随机数预测
每次泄露 8 位,然后 3108 轮,完全足够来还原 state
之后根据伪随机数生成器的状态对 shuffle 求逆即可
考虑到存在多解,使用 gf2bv 将所有解遍历即可

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
from gf2bv import LinearSystem
from gf2bv.crypto.mt import MT19937
from pwn import *
import re
from tqdm import *
from Crypto.Util.number import long_to_bytes
def _randbelow_via_getrandbits(pyrand, n: int) -> int:
# 复刻 Python Random._randbelow(n) 的拒绝采样版本
if n <= 0:
raise ValueError("n must be > 0")
k = n.bit_length()
r = pyrand.getrandbits(k)
# 如果落在 [0, n) 之外,拒绝重取,保持一致的消耗模式
while r >= n:
r = pyrand.getrandbits(k)
return r

def build_perm_float(pyrand, n: int, rounds: int) -> list:
# 方案 F:shuffle 使用 random() * (i+1)
idx = list(range(n))
for _ in range(rounds):
# 不能直接用 pyrand.shuffle,因为你本机 Python 的实现
# 可能与出题环境不同(会走 randbelow 分支)
for i in range(n - 1, 0, -1):
j = int(pyrand.random() * (i + 1)) # 消耗 53 比特
if j != i:
idx[i], idx[j] = idx[j], idx[i]
return idx

def build_perm_randbelow(pyrand, n: int, rounds: int) -> list:
# 方案 R:shuffle 使用 _randbelow(i+1)(基于 getrandbits)
idx = list(range(n))
for _ in range(rounds):
for i in range(n - 1, 0, -1):
j = _randbelow_via_getrandbits(pyrand, i + 1) # 消耗 getrandbits(k)
if j != i:
idx[i], idx[j] = idx[j], idx[i]
return idx

def invert_perm(perm: list) -> list:
inv = [None] * len(perm)
for pos, src_i in enumerate(perm):
inv[src_i] = pos
return inv

def apply_inverse_to_ciphertext(cipher: str, inv: list) -> str:
# c[i] = src[perm[i]] => src[i] = c[inv[i]]
c_list = list(cipher)
out = [None] * len(c_list)
for i in range(len(c_list)):
out[i] = c_list[inv[i]]
return "".join(out)

with open("/home/qwb2025/gift_16bit_chunks.txt", "r") as f:
gift = f.read().strip().split(" ")
print(len(gift))
gift = [int(v) for v in gift]
print(gift[0:10])
c = ")9Lsu_4s_eb__otEli_nhe_tes5gii5sT@omamkn__ari{efm0__rmu_nt(0Eu3_En_og5rfoh}nkeoToy_bthguuEh7___u"

print(len(gift))
def mt19937(bs, out):

lin = LinearSystem([32] * 624)
mt = lin.gens()

rng = MT19937(mt)
zeros = []
for o in out:
rng.getrandbits(8)
zeros.append((rng.getrandbits(16)>>8) ^ o)
zeros +=[mt[0] ^ 0x80000000]
print("solving...")

sol = lin.solve_all(zeros)
all_solutions = []
for i in sol:
rng = MT19937(i)
pyrand = rng.to_python_random()
for i in trange(3108):
pyrand.getrandbits(8)
veri = pyrand.getrandbits(16)>>8
if veri != out[i]:
print("wrong!")
return

print("recovering the flag...")

n = len(c)
rounds = 2025

# 精确重放 CPython 的 shuffle:基于 randbelow(getrandbits) 的拒绝采样
perm = build_perm_randbelow(pyrand, n, rounds)

# invert perm -> 用 inv 把 c 复原到 src
inv = invert_perm(perm)
flag_plain = apply_inverse_to_ciphertext(c, inv)

print(flag_plain)

out=[]

for i in trange(3108):
out.append(int(gift[i]>>8))
mt19937(8, out)

# flag{7hE_numbEr_0f_biT5_i5_Enou9h_@L5o_ThE_r4nk_must_3n0ugh}(some_noise_to_make_sure_you_get_it)

sk

密钥生成元素

上面的都是

注意到题目的加密逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def encrypt(pk, pt):
P, Q, p = pk
pt = bytes_to_long(pt)

PP = 0
QQ = 0

for i in range(len(P)):
u = randint(1, p)
for j in range(len(P[0])):
PP = PP + P[i][j] * (u * pt**j % p)
QQ = QQ + Q[i][j] * (u * pt**j % p)

return PP, QQ

P, Q 里面的元素均为 520 bit,而 upt**j%p 为 256 bit
可以用 cuso 对 u
pt**j%p进行求解 (造格的话应该要想怎么用到 p ,因为 cuso 的 bound,不设到 p 是解不出来的)
解出后可以根据这六个值去确定 pt
若存在多解的情况,将六个值分成三三,分别解出 pt 进行验证即可
最后得到的解应该是唯一的
拿到 pt 后生成一组新的私钥即可
exp:

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
156
157
158
159
160
161
from random import randint
from Crypto.Util.number import getPrime, inverse, long_to_bytes, bytes_to_long
from math import gcd
import signal
from sage.all import *
from cuso import find_small_roots
from tqdm import *

ans = []

def gen_coprime_num(pbits):
lbits = 2 * pbits + 8
lb = 2**lbits
ub = 2**(lbits + 1)
while True:
r = randint(lb, ub)
s = randint(lb, ub)
if gcd(r, s) == 1:
return r, s

def mult_mod(A, B, p):
result = [0] * (len(A) + len(B) - 1)
for i in range(len(A)):
for j in range(len(B)):
result[i + j] = (result[i + j] + A[i] * B[j]) % p

return result

def gen_key(p):
f = [randint(1, 2**128) for i in ":)"]
h = [randint(1, 2**128) for i in ":("]

R1, S1 = gen_coprime_num(p.bit_length())
R2, S2 = gen_coprime_num(p.bit_length())

B = [[randint(1, p - 1) for i in ":("] for j in ":)"]

P = []
for b in B:
P.append(mult_mod(f, b, p))

Q = []
for b in B:
Q.append(mult_mod(h, b, p))

for i in range(len(P)):
for j in range(len(P[i])):
P[i][j] = P[i][j] * R1 % S1
Q[i][j] = Q[i][j] * R2 % S2

sk = [(R1, S1), (R2, S2), f, h, p]
pk = [P, Q, p]

return sk, pk

def encrypt(pk, pt):
P, Q, p = pk
pt = bytes_to_long(pt)

PP = 0
QQ = 0

for i in range(len(P)):
u = randint(1, p)
for j in range(len(P[0])):
PP = PP + P[i][j] * (u * pt**j % p)
QQ = QQ + Q[i][j] * (u * pt**j % p)
ans.append(u * pt**j % p)

return PP, QQ

P, Q, p = [[[3218776798633782763258343950840631301596464597259488804831812200809096510516837611693778258324728437813591188845254187557511511419412408085116550010592789870, 1895578921892791164219150768128437375112014649022011803400741232127422143763640827235188139308460351011781167234369420776680169488099872100028685583799150869, 5141546427666598028471348629781269831609697016146876435781308631670362283707156844872008409562266072879527302183483884359060859478866491307714118887367009160], [1455535396056514602781565870773568802403164000160425533803744264547497812294334721388270482510094029061769161376373214677212583685301268087324527935280976328, 3748160525917876885178367308298545346711169266194303792635868860551684965832909731901431090215767105132425623423791607146607000997460913105808656777369999823, 334544340646220191007845329966087541271726425901757840427389185654010114680670558722815496649361094575036211777881746723793264199361832030454269887771054040]], [[2368811954751786368493691787909305723566011477733750188362250386635536640731986953613920498758120644911499108356257024820681386241427640076765616015664733993, 3919789944823044559422563467726116305246882011452599778645628983443836712314243598989290692363607190423491993587134459856780623086077603311150632243422448348, 693536969358809316298144343883699755697892497503630583541643430138748526086111385631149475717085426852652954013154254103145899037969082011459735475411783190], [3014065519780926283105865004978530952254680112585612773189352760392390495197445588853112632224280208995588081648548436214204712001013383127125029466374224785, 1107523315901381120363588000513009759441707904112935715515381514078978560730174133031857303080270947161231439137468679549192121874332009153326449483107360711, 450469736732563685496607983037728055134292667724897068952094913603432865688292438759614072953961966889722747521952206141669443760236198450283935790969395574]], 73257055002963132558415740133442187409896784017391484820917597361714517443079]
enc = (837003663202771686762377589274627612315105809459171347778881364583989630029585437993819105689315321280993392285563475721670747032440692619528515632142880555897096761734578792480371717895292340167344745263637333120431339250399287897187, 583464259527786652604255446882870995901809148761666797582577757338848564147384451853060606175591160278184841474801310182391424642293713451190956291975334434064228193364511298726067677187408596438494282418598070587989199428082812387593)
u11, u12, u13, u21, u22, u23 = var('u11 u12 u13 u21 u22 u23')

v = [u11, u12, u13, u21, u22, u23]

PP = -enc[0]
QQ = -enc[1]

for i in range(len(v)):
PP+=P[i//3][i%3]*v[i]
QQ+=Q[i//3][i%3]*v[i]

bounds = {}
for i in v:
bounds[i] = (0, p)
print(p)

roots = find_small_roots([PP, QQ], bounds)
print(roots)
u11_list = [
61739833609778119378236047826282590058670598041359217908360668203386753414853,
49371088056833124739455805618986684111513485742695003616199631935242907977797,
34983400843843298437286276348189338734991702628895325721672716716962932007336,
61739833609778119378236047826282590058670598041359217908360668203386753414853,
49371088056833124739455805618986684111513485742695003616199631935242907977797,
34983400843843298437286276348189338734991702628895325721672716716962932007336,
]

u21_list = [
32809361452457482320207985223231627700334786855172933423922974355749785570157,
31234112865573050318229925195690310895636735218340317623712723195986882463129,
38410441497153048190094052558424486983616094215388670802657988200603966884892,
32809361452457482320207985223231627700334786855172933423922974355749785570157,
31234112865573050318229925195690310895636735218340317623712723195986882463129,
38410441497153048190094052558424486983616094215388670802657988200603966884892,
]

u12_list = [
58727483320282042561644741509118865406577745136086095333445577363053948504480,
62954448821603379880928067151081470496601649411281938950370192768419900707924,
71854497776597711020623079150265224370210992298241251507399932640307926727410,
58727483320282042561644741509118865406577745136086095333445577363053948504480,
62954448821603379880928067151081470496601649411281938950370192768419900707924,
71854497776597711020623079150265224370210992298241251507399932640307926727410,
]

u22_list = [
44193208289418931054774724183115604226584950790626348405317340952470193839907,
63165317203921134048172197531616991443121085115387243551301596646685247467703,
48024938212183532884201154501606385524987201867175349721660033919843848980647,
44193208289418931054774724183115604226584950790626348405317340952470193839907,
63165317203921134048172197531616991443121085115387243551301596646685247467703,
48024938212183532884201154501606385524987201867175349721660033919843848980647,
]

u13_list = [
58274311805462684647438246332969198451554862496989668836803199474091399364608,
50840237881469273053637179758753437137622998313894810596853931770596771426959,
68121433392443049631171237720132922383349000485692234646852314764181968773464,
58274311805462684647438246332969198451554862496989668836803199474091399364608,
50840237881469273053637179758753437137622998313894810596853931770596771426959,
68121433392443049631171237720132922383349000485692234646852314764181968773464,
]

u23_list = [
41656165084767462073283666273338979284684082192854421973988996581577277441343,
45257006395634301750273083150577316592630229651746879786669272372225038826788,
6072694120632115648680228070003632328784518702200770484744330303711636609282,
41656165084767462073283666273338979284684082192854421973988996581577277441343,
45257006395634301750273083150577316592630229651746879786669272372225038826788,
6072694120632115648680228070003632328784518702200770484744330303711636609282,
]

for i in trange(len(u11_list)):
u1_inv = inverse(u11_list[i], p)
pt1 = (u12_list[i] * u1_inv) % p
u2_inv = inverse(u21_list[i], p)
pt2 = (u22_list[i] * u2_inv) % p
if pt1 == pt2:
print("Found pt:", pt1)


pt = 33017761099216922338277478995616619263308379125138230278329744781095530785266

sk, pk = gen_key(p)
ticket = long_to_bytes(pt)
enc_ticket = encrypt(pk, ticket)
print("Flag ticket ciphertext:", enc_ticket)
print(sk)

Blurred

参考 NTRU 的生成逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def sample(rand):
return (rand.getrandbits(1) - rand.getrandbits(1)) * (rand.getrandbits(1) * rand.getrandbits(1))

def GenNTRU():
f = [sample(prandom) for _ in range(n)]
g1 = [sample(prandom)for _ in range(n)]
g2 = [sample(prandom) for _ in range(n)]
g1x = Q(g1)
g2x = Q(g2)

while True:
fx = Q(f)
try:
h1 = g1x / fx
h2 = g2x / fx
return (h1.lift(), h2.lift(), fx)
except:
prandom.shuffle(f)
continue

首先会发现 f, g1, g2 都是很小的,且比较关键的一点是选取到 0 的概率更大,这会导致它们更趋近于 0
在商环上,有多项式

发现将 x=-1 代入后

其中 都是很小的量
而且后来题目将 q 增大,使得随机情况的 f、g 极大概率不会这么小
可以通过这个性质枚举 f ,通过计算出来的 g 是否很小来进行判断
成功判断 20000 多次后,就可以根据 coins 打 MT19937
最终成功恢复 key, 解得 flag

exp1:(接收信息)

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
from gf2bv import LinearSystem
from gf2bv.crypto.mt import MT19937
from pwn import *
import re
from tqdm import *
from Crypto.Util.number import long_to_bytes
from sage.all import *
import re, ast
io = remote("39.106.40.37", 20488)
def center_lift(l):
return [x - q if x > q//2 else x for x in l]

def lift_mod(x):
return x-q if x > q//2 else x

def parse_int_list_bytes(b: bytes):
# b 形如 b'[123, 456, -789]'
b = b.strip()
assert b[:1] == b'[' and b[-1:] == b']'
if len(b) <= 2:
return []
parts = b[1:-1].split(b',')
out = []
for p in parts:
p = p.strip()
if p:
out.append(int(p)) # 直接把 bytes 转 int
return out

def mt19937(bs, out):

lin = LinearSystem([32] * 624)
mt = lin.gens()

rng = MT19937(mt)
zeros = []
for o in out:
rng.getrandbits(8)
zeros.append((rng.getrandbits(16)>>8) ^ o)
zeros +=[mt[0] ^ 0x80000000]
print("solving...")

sol = lin.solve_all(zeros)

q = 1342261
n = 1031
PR = PolynomialRing(Zmod(q), "x")
x = PR.gens()[0]
Q = PR.quotient(x**n + 1)
f = x**n + 1
out = []
pk_list = []
'''
for t in trange(20258):
io.sendlineafter(b"c :", b"1")

io.recvuntil(b'Hints:')

# 读第一个列表(先到 '[', 再到对应 ']')
io.recvuntil(b'[', drop=False)
lst1_bytes = b'[' + io.recvuntil(b']', drop=False)

# 读第二个列表
io.recvuntil(b'[', drop=False)
lst2_bytes = b'[' + io.recvuntil(b']', drop=False)

pk1 = parse_int_list_bytes(lst1_bytes)
pk2 = parse_int_list_bytes(lst2_bytes)
pk1_list.append(pk1)
pk2_list.append(pk2)
'''

out = []

for i in trange(20251):
if i % 100 == 0:
for j in range(min(100, 20251-i)):
io.sendline(b"1")
tmp = io.recvuntil(b'Hints:')
pk1, pk2 = io.recvline().split(b'] [')
pk1, pk2 = eval(pk1+b']'), eval(b'['+pk2)

bound = 160
ans = 1

h1 = lift_mod(int((Q(pk1)).lift()(x = -1)))
h2 = lift_mod(int((Q(pk2)).lift()(x = -1)))
for f in range(-bound, bound):
if f == 0:
continue
g1 = f*h1 %q
g2 = f*h2 %q
if abs(lift_mod(g1)) <= bound and abs(lift_mod(g2)) <= bound and (h1*lift_mod(g2) - h2*lift_mod(g1)) % q == 0:
ans = 0
out.append(0)
break

if ans == 1:
out.append(1)
'''
bound = 120
tmp = 1
dif = 1

h1 = lift_mod(int((Q(pk1)).lift()(x = -1)))
h2 = lift_mod(int((Q(pk2)).lift()(x = -1)))
for f in range(-bound, bound):
if f == 0:
continue
g1 = f*h1 %q
g2 = f*h2 %q
if abs(lift_mod(g1)) <= bound and abs(lift_mod(g2)) <= bound and (h1*lift_mod(g2) - h2*lift_mod(g1)) % q == 0:
tmp = 0
out.append(0)
break
if tmp == 1:
out.append(1)
'''
print(str(out))
io.sendlineafter(b"c :", b"2")
io.recvuntil(b'Flag:')
enc_flag = eval(io.recvline()[:-1])
print(enc_flag)

'''
with open("/home/qwb2025/ntru_out.txt", "w") as f:
for pk in pk_list:
f.write(pk.decode())
f.write("\n")
'''

exp2:(打 MT19937)

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
from gf2bv import LinearSystem
from gf2bv.crypto.mt import MT19937
from pwn import *
import re
from tqdm import *
from Crypto.Util.number import long_to_bytes
from sage.all import *
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto.Util.Padding import pad, unpad
from tqdm import *
#c = b'm\x07y\xda\xddDy5\xd717\xc7Sm_z\xee!^\x1d\xce\x04\xd6Y\xf0\x1a<\xb75q\x08Q\xcf\xf0\xa4\xc8ht?S&\x8a\x92,\xf6\x9f@5'
c = b'>he=\x83\x08\xde\xf1s\x94\x17\xae\x9c69\t\xed\xb5\x8f\xbd9\x8c\xa4\xce\x9e\xfaO\xca\x17\xb2x&\xfb\x91\xbf\x85\xab(\xe9\xbf\t\x04\xe6\x0e\xfc\xfaI\xed'
import ast
import numpy as np
'''
rows, cols = 20255, 1031
dtype = np.int32 # 若数值可能超32位,改为 np.int64

pk1_list = np.memmap('data.int32.memmap', dtype=dtype, mode='w+', shape=(rows, cols))

pk2_list = np.memmap('data.int32.memmap', dtype=dtype, mode='w+', shape=(rows, cols))
pat = re.compile(r'\[([^\]]*)\]\s+\[([^\]]*)\]')
with open('/home/qwb2025/ntru_out.txt', 'r', encoding='utf-8') as f:
for i, line in enumerate(f):
if i % 2 == 0:
continue # 只处理奇数行(从0开始计数)


s = line.strip()
if not s:
raise ValueError(f'第 {i} 行是空行')

m = pat.search(s)
if not m:
raise ValueError(f'第 {i} 行未匹配到两个列表:{s[:120]}...')

left_txt, right_txt = m.group(1), m.group(2)
# 以逗号分隔解析为数值(矢量化、很快),允许空格
a = np.fromstring(left_txt, sep=',', dtype=dtype)
b = np.fromstring(right_txt, sep=',', dtype=dtype)

if a.size != cols or b.size != cols:
raise ValueError(f'第 {i} 行列数不符:got ({a.size}, {b.size}), expected ({cols}, {cols})')

pk1_list[i//2, :] = a
pk2_list[i//2, :] = b

print(len(pk1_list), len(pk2_list))
'''
def mt19937(bs, out):

lin = LinearSystem([32] * 624)
mt = lin.gens()

rng = MT19937(mt)
zeros = []
for o in out:
zeros.append((rng.getrandbits(1)) ^ int(o))
zeros +=[mt[0] ^ 0x80000000]
print("solving...")

sol = lin.solve_one(zeros)

rng = MT19937(sol)
pyrand = rng.to_python_random()
for j in trange(20251):
veri = pyrand.getrandbits(1)
if veri != out[j]:
print("wrong!")
return

print("recovering the flag...")
key = pyrand.getrandbits(256)
SHA = SHA256.new()
SHA.update(str(key).encode())
KEY = SHA.digest()
cipher = AES.new(KEY, AES.MODE_ECB)
flag = unpad(cipher.decrypt(c), 16)
print(flag)

def center_lift(l):
return [x - q if x > q//2 else x for x in l]

def lift_mod(x):
return x-q if x > q//2 else x

def change(a):
if a == 1:
return 0
else:
return 1
q = 1342261
n = 1031
PR = PolynomialRing(Zmod(q), "x")
x = PR.gens()[0]
Q = PR.quotient(x**n + 1)
f = x**n + 1
out = ''
'''
for pk1, pk2 in tqdm(zip(pk1_list, pk2_list)):
bound = 150
tmp = 1
pk1 = pk1.tolist()
pk2 = pk2.tolist()
h1 = lift_mod(int((Q(pk1)).lift()(x = -1)))
h2 = lift_mod(int((Q(pk2)).lift()(x = -1)))
for f in range(-bound, bound):
if f == 0:
continue
g1 = f*h1 %q
g2 = f*h2 %q
if abs(lift_mod(g1)) <= bound and abs(lift_mod(g2)) <= bound and (h1*lift_mod(g2) - h2*lift_mod(g1)) % q == 0:
tmp = 0
out.append(0)
break
if tmp == 1:
out.append(1)
'''
'''
for pk1, pk2 in tqdm(zip(pk1_list, pk2_list)):
out.append(distinct(pk1.tolist(), pk2.tolist()))
'''

with open("/home/qwb2025/exp2_out.txt", "w") as f:
for v in out:
f.write(str(v) + ",")
print(len(out))
mt19937(1, out)

#flag{b3c8e1c4-6f4b-4d7e-bf6f-7e4030e9d8fd}

总结

这次强网杯除了零解题都打出来了,相比去年来说有了些进步,继续加油 ☝️🤓☝️