2024-CISCN/铁人三项初赛-wp-Crypto

2024-CISCN-铁人三项初赛-wp-Crypto

现在是2024年12月19日下午,我在复习马原。

马原东西真的很多,我根本背不下来。

概率论也是一坨屎。

其实我还挺犹豫的,要不要写这个wp,大部分(所有)题目都是依靠搜索得到的,真的让我讲原理需要一点时间把他给理一理,期末就在眼前,所以我其实不是很想写,感觉不如复习。

但是吧,ciscn两千个队,这要是写个ak密码的博客,岂不是引了波大的。

所以选取一个折中方案,先贴exp,期末之后再写wp,嘻嘻。

其实别人应该也更新了,鸡块爹和中山大学的大爹他们应该写的很清楚,在这里献献丑吧。

有很多wp都没有贴出来,比如强网杯,hitctf,sctf,和若干小比赛等等,感觉引流不到人,随便吧,可能就不写了,要是有人看我就写(qwq

祝我们方寸不乱。

1839d2988d18ffa627c9225ece90e092

ffffhash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import os
from Crypto.Util.number import *
def giaogiao(hex_string):
base_num = 0x6c62272e07bb014262b821756295c58d
x = 0x0000000001000000000000000000013b
MOD = 2**128
for i in hex_string:
base_num = (base_num * x) & (MOD - 1)
base_num ^= i
return base_num


giao=201431453607244229943761366749810895688

print("1geiwoligiaogiao")
hex_string = int(input(),16)
s = long_to_bytes(hex_string)

if giaogiao(s) == giao:
print(os.getenv('FLAG'))
else:
print("error")

fnv,downunderCTF2023原题,修改格的大小即可。

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
TARGET = 201431453607244229943761366749810895688
h0 = 0x6c62272e07bb014262b821756295c58d
p = 0x0000000001000000000000000000013b
MOD = 2^128

n = 21
M = Matrix.column([p^(n - i - 1) for i in range(n)] + [-(TARGET - h0*p^n), MOD])
M = M.augment(identity_matrix(n+1).stack(vector([0] * (n+1))))
Q = Matrix.diagonal([2^256] + [2^4] * n + [2^16])
M *= Q
M = M.BKZ()
M /= Q
for r in M:
if r[0] == 0 and abs(r[-1]) == 1:
r *= r[-1]
good = r[1:-1]
print(good)
break
inp = []
y = int(h0*p)
t = (h0*p^n + good[0] * p^(n-1)) % MOD
for i in range(n):
for x in range(256):
y_ = (int(y) ^^ int(x)) * p^(n-i-1) % MOD
if y_ == t:
print('good', i, x)
inp.append(x)
if i < n-1:
t = (t + good[i+1] * p^(n-i-2)) % MOD
y = ((int(y) ^^ int(x)) * p) % MOD
break
else:
print('bad', i)
print(bytes(inp).hex())
f7d210031a28123358f217313d0f1d070d043a2215
flag{78a439b3-40a3-4411-a642-e54bef59db2d}

rasnd

简单的同余题目,也是原题

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
from Crypto.Util.number import getPrime, bytes_to_long
from random import randint
import os

FLAG = os.getenv("FLAG").encode()
flag1 = FLAG[:15]
flag2 = FLAG[15:]

def crypto1():
p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = 0x10001
x1=randint(0,2**11)
y1=randint(0,2**114)
x2=randint(0,2**11)
y2=randint(0,2**514)
hint1=x1*p+y1*q-0x114
hint2=x2*p+y2*q-0x514
c = pow(bytes_to_long(flag1), e, n)
print(n)
print(c)
print(hint1)
print(hint2)


def crypto2():
p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = 0x10001
hint = pow(514*p - 114*q, n - p - q, n)
c = pow(bytes_to_long(flag2),e,n)
print(n)
print(c)
print(hint)
print("==================================================================")
crypto1()
print("==================================================================")
crypto2()
print("==================================================================")

后续补上公式。

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
'''
16281287146415244515710688823751547709858173201685468957747536670208962039507944403216778605003868404406096278489333122602219174074224497059786590530531777743256300914337306006693333531042755602903896726948503427118612087418442171541082255720308064272919125315154801568477355066334513675284285629902320889520742417233270112925983042391627441703527842885223077980330547647812328063425005357574816347670317744620051708370325529556688231463202029426214086369712174290514984214213834257551930484214133784093189397234131168354119662936437137951238566835793811429769286347523286432311204945707942564796315386828294214170123
12086196629534493227968677403278660961796075717640291587747846667634594270905491484910344964996466541082890595125812927321291135782604869559780307228077673817725114268516232319635959427597118008223168174492754079179094467536794662406024887131911079210605873973907120069786418431697687648058579366670407954407718493805793543187969723922998593669272069615236791969413224667920576969608815867662029592745740649259479920899838081901142065643040437673770301613090814528711110336008484037385602832880764654935192618499900120089221822335786622807798546984262969286709706101915294748095971810989047919596881317050120317696760
339725605923159774552456884473495886248354247262770709626334709201876034709674798789160151238991959320032570659102586499870397258055037240657300385783742906696179303246523671498532415812052058398980657380981489917881857226113490045744688136473451589176693546398039139142066186105523933986645566765229603669465229867387035800285727827076742925
537464336876823615924305659326747937813957629764171533449079263021501965450782845009647995811756725729035665987896137536899231398922926242147310876313366539676892832941943774951054160099444146152978671879431383260874141742022607785452569076406725585854601694199524682772149728403645860969120937623054462662697135815140087055597360181394511013713883829186455196072205257084022783328455828324928265334330592153957176729515569834677524736641060275387709486848550662
==================================================================
15377144927329715525268479479571697739020241918062529385734847541901885083644027131048254818027262750525314295399787928876222943844512069617136444361097912000888884572297115408668047525976873697185826288325823271339909319371969813473837578000181437137469824654688011281915176920783131010423875661323762204860479114018935898466358085241519969686749109878306940625141986020728858434018790628966876240688278141347010648538302433167637113114312116732782585538757527979683472832466027566184102739671013319156079970050355080901591512902555726050156259314123683115380553698655516270069670921611706391820513290721920880635611
10060172113108041956217512929240432549324498688993289535458395908721315957735098896080343702241247766137707663696550717506537858189809332961283409210436515027057007790745639037616943814565068569930677451882586852691614875588977562873592426912465017064925418126404436532797526772303056664033803329763658533043515098379186687596502104115974355478888948795279730681389623132802796316160075033115785725995474478308594670226993338598551363554070303577664092320498374522935984788851484024286997559607458219169036406510629797529959774987108852827385027426290570063570753402232824534377940940603474521374778238822191832080651
1365452044971115100899256436781172709248606321348288940710426907743354277597849360643340056206339377661118187490723079600269577632217831867702005193980779623599156058086926449070580571549195481571319135111911180074258447600433458201826132600928518018754846056823602398312862039585196929747961576688149170631991725934373760426550739159386322237485016975443769479976441091939374879359143918708739351154287254521649557701876909191467188688395123859942579183492595147824538490204003042181564698130895568376314123616288715661511258051299143669290116951091799243176968458546991453691225956346070726565440246937182549652737
==================================================================
'''
from Crypto.Util.number import *
from tqdm import trange
n = 16281287146415244515710688823751547709858173201685468957747536670208962039507944403216778605003868404406096278489333122602219174074224497059786590530531777743256300914337306006693333531042755602903896726948503427118612087418442171541082255720308064272919125315154801568477355066334513675284285629902320889520742417233270112925983042391627441703527842885223077980330547647812328063425005357574816347670317744620051708370325529556688231463202029426214086369712174290514984214213834257551930484214133784093189397234131168354119662936437137951238566835793811429769286347523286432311204945707942564796315386828294214170123
c = 12086196629534493227968677403278660961796075717640291587747846667634594270905491484910344964996466541082890595125812927321291135782604869559780307228077673817725114268516232319635959427597118008223168174492754079179094467536794662406024887131911079210605873973907120069786418431697687648058579366670407954407718493805793543187969723922998593669272069615236791969413224667920576969608815867662029592745740649259479920899838081901142065643040437673770301613090814528711110336008484037385602832880764654935192618499900120089221822335786622807798546984262969286709706101915294748095971810989047919596881317050120317696760
hint1 = 339725605923159774552456884473495886248354247262770709626334709201876034709674798789160151238991959320032570659102586499870397258055037240657300385783742906696179303246523671498532415812052058398980657380981489917881857226113490045744688136473451589176693546398039139142066186105523933986645566765229603669465229867387035800285727827076742925
hint2 = 537464336876823615924305659326747937813957629764171533449079263021501965450782845009647995811756725729035665987896137536899231398922926242147310876313366539676892832941943774951054160099444146152978671879431383260874141742022607785452569076406725585854601694199524682772149728403645860969120937623054462662697135815140087055597360181394511013713883829186455196072205257084022783328455828324928265334330592153957176729515569834677524736641060275387709486848550662
# hint1 = hint1+0x114
# hint2 = hint2+0x514
# for i in trange(1,2**12):
# for j in range(1,2**12):
# if(GCD(hint1*i-hint2*j,n)!=1):
# print(GCD(hint1*i-hint2*j,n))
# print(i,j)
q = 92550838148342975698186686611753596474232518772512056202164179171751456986775823431775065714565654023011314414715225948985285600677270147985261890158007391751040981899190513791191802867694298019388915374947985403906268433674262676618148215540642106384816552941214842483465739872731887585210036938936884772687
p = n//q
phi = (p-1)*(q-1)
d = inverse(65537,phi)
m = pow(c,d,n)
# print(long_to_bytes(m))
# #b'flag{c9b4a893-5b87-4f3e-bc0b-5e16f4b3d016}'
from Crypto.Util.number import *
n = 15377144927329715525268479479571697739020241918062529385734847541901885083644027131048254818027262750525314295399787928876222943844512069617136444361097912000888884572297115408668047525976873697185826288325823271339909319371969813473837578000181437137469824654688011281915176920783131010423875661323762204860479114018935898466358085241519969686749109878306940625141986020728858434018790628966876240688278141347010648538302433167637113114312116732782585538757527979683472832466027566184102739671013319156079970050355080901591512902555726050156259314123683115380553698655516270069670921611706391820513290721920880635611
c = 10060172113108041956217512929240432549324498688993289535458395908721315957735098896080343702241247766137707663696550717506537858189809332961283409210436515027057007790745639037616943814565068569930677451882586852691614875588977562873592426912465017064925418126404436532797526772303056664033803329763658533043515098379186687596502104115974355478888948795279730681389623132802796316160075033115785725995474478308594670226993338598551363554070303577664092320498374522935984788851484024286997559607458219169036406510629797529959774987108852827385027426290570063570753402232824534377940940603474521374778238822191832080651
s = 1365452044971115100899256436781172709248606321348288940710426907743354277597849360643340056206339377661118187490723079600269577632217831867702005193980779623599156058086926449070580571549195481571319135111911180074258447600433458201826132600928518018754846056823602398312862039585196929747961576688149170631991725934373760426550739159386322237485016975443769479976441091939374879359143918708739351154287254521649557701876909191467188688395123859942579183492595147824538490204003042181564698130895568376314123616288715661511258051299143669290116951091799243176968458546991453691225956346070726565440246937182549652737


R.<x> = ZZ[]
poly = 514*114*x^2 + inverse_mod(s, n)*x - n
p = poly.factor()[0][0][0]
q = n//p
e = 0x10001
d = inverse_mod(e, (p-1)*(q-1))
m = pow(c, d, n)
flag = long_to_bytes(int(m))
print(flag.decode())

LWEWL

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
from Crypto.Util.number import *
from random import randint
from secret import flag

assert flag.startswith(b'flag{') and flag.endswith(b'}')
flag = flag[5:-1]
flag1 = flag[:len(flag)//2]
flag2 = flag[len(flag)//2:]

class LWE:
def __init__(self, lwe_dim, lwe_num_samples, lwe_plaintext_modulus, lwe_ciphertext_modulus, rlwe_dim, rlwe_modulus):
self.lwe_dim = lwe_dim
self.lwe_num_samples = lwe_num_samples
self.lwe_plaintext_modulus = lwe_plaintext_modulus
self.lwe_ciphertext_modulus = lwe_ciphertext_modulus
self.lwe_secret_key = self.distribution(0, self.lwe_ciphertext_modulus - 1, self.lwe_dim)
self.rlwe_dim = rlwe_dim
self.rlwe_modulus = rlwe_modulus

def distribution(self, lbound, rbound, dim):
return [randint(lbound, rbound) for _ in range(dim)]

def lwe_encrypt(self, message):
a = self.distribution(0, lwe_ciphertext_modulus - 1, self.lwe_dim)
e = self.distribution(-15, 15, 1)[0]
return a, sum([a[i] * self.lwe_secret_key[i] for i in range(self.lwe_dim)]) + message + e * lwe_plaintext_modulus

def lwe_keygen(self):
A = []
B = []
for _ in range(self.lwe_num_samples):
sample = self.lwe_encrypt(0)
A.append(sample[0])
B.append(sample[1])
return A, B

def encrypt(self, message, lwe_pubkey1, lwe_pubkey2):
const = vector(ZZ, self.distribution(-1, 1, self.lwe_num_samples))
e = self.distribution(-15, 15, 1)[0]
return const * matrix(GF(lwe_ciphertext_modulus), lwe_pubkey1), const * vector(GF(lwe_ciphertext_modulus), lwe_pubkey2) + message + e * lwe_plaintext_modulus

def rlwe_sample(self, flag):
P.<x> = PolynomialRing(Zmod(self.rlwe_modulus))

while True:
monomials = [x^i for i in range(self.rlwe_dim + 1)]
c = self.distribution(0, self.rlwe_modulus - 1, self.rlwe_dim) + [1]
f = sum([c[i] * monomials[i] for i in range(self.rlwe_dim + 1)])
PR = P.quo(f)
if f.is_irreducible():
break
a = self.distribution(0, self.rlwe_modulus - 1, self.rlwe_dim)
e = self.distribution(-5, 5, self.rlwe_dim)
s = [flag[i] for i in range(len(flag))]
b = PR(a) * PR(s) + PR(e)
return a, b, f, self.rlwe_modulus

lwe_dimension = 2**9
lwe_num_samples = 2**9 + 2**6 + 2**5 + 2**2
lwe_plaintext_modulus = next_prime(256)
lwe_ciphertext_modulus = next_prime(1048576)
rlwe_dim = 64
rlwe_modulus = getPrime(128)

lwe = LWE(lwe_dimension, lwe_num_samples, lwe_plaintext_modulus, lwe_ciphertext_modulus, rlwe_dim, rlwe_modulus)
lwe_pubkey1, lwe_pubkey2 = lwe.lwe_keygen()
lwe_public_key = [lwe_pubkey1, lwe_pubkey2]
lwe_cipher1 = []
lwe_cipher2 = []
for flag_char in flag1:
tmp1, tmp2 = lwe.encrypt(flag_char, lwe_pubkey1, lwe_pubkey2)
lwe_cipher1.append(tmp1)
lwe_cipher2.append(tmp2)

lwe_ciphertext = [lwe_cipher1, lwe_cipher2]
save(lwe_public_key, "lwe_public_key")
save(lwe_ciphertext, "lwe_ciphertext")

rlwe_ciphertext = lwe.rlwe_sample(flag2)
save(rlwe_ciphertext, "rlwe_ciphertext")

屎一样的长

但是其实可以发现,两部分都是原题,一个是鸡块给nss round18出的rlwe原题,一个好像是diceCTF的。

https://r3kapig.com/writeup/20230206-DiceCTF2023-CN/

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
lwe_public_key = load("lwe_public_key.sobj")
lwe_ciphertext = load("lwe_ciphertext.sobj")

lwe_dimension = 2**9
lwe_num_samples = 2**9 + 2**6 + 2**5 + 2**2
lwe_plaintext_modulus = next_prime(256)
lwe_ciphertext_modulus = next_prime(1048576)

lwe_pubkey1, lwe_pubkey2 = lwe_public_key
lwe_cipher1, lwe_cipher2 = lwe_ciphertext

from sage.all import *
import numpy as np
from time import time
n = 512
# number of public key samples
m = n + 100
# plaintext modulus
p = 257
# ciphertext modulus
q = 1048583

pk_A=Matrix(GF(q),lwe_pubkey1)
pk_b=vector(GF(q),lwe_pubkey2)
encrypt_A=lwe_cipher1
encrypt_b=lwe_cipher2

def pk_Aexpress(pk_A):
pkA_1 = pk_A[:512,:]
pkA_2 = pk_A[512:,:]
ks = []
for row in pkA_2:
ks.append(pkA_1.solve_left(row))
return Matrix(ZZ,ks)

def fuck(A,pk_A):
c_tmp = pk_A.solve_left(A)[:-100]
print("\nstart to express")
tmpks = pk_Aexpress(pk_A)
ks = tmpks[:,:100]
print(" express done ")
ks = ks.stack(Matrix(ZZ,[c_tmp[:100]]))
M = Matrix(ZZ,100 + 100 + 1,100 + 100 + 1)
M[:101,:101] = identity_matrix(101)
M[:101,101:] = ks
M[101:,101:] = q * identity_matrix(100)
start_time = time()
print("start to LLL")
ML = M.LLL()
rows = ML[0]
print(f"LLL done at {time()-start_time}")
c_new = [0 for i in range(612)]
c_list = Matrix(ZZ,Matrix(GF(q),rows[:100]*tmpks) + Integer(rows[100]) * Matrix(GF(q),c_tmp))[0]
for _ in range(512):
if c_list[_] == q-1:
c_new[_] = -1
else:
c_new[_] = int(c_list[_])
for _ in range(100):
if rows[_] == q-1:
c_new[_+512] = -1
else:
c_new[_+512] = int(rows[_])

return c_new

flag_bytes = []
from tqdm import trange
for _ in trange(len(encrypt_A)):
A = vector(GF(q),encrypt_A[_])
b = encrypt_b[_]
c_new = fuck(A,pk_A)

c_first = c_new[:512]
c_secon = c_new[512:]

c = vector(ZZ, c_first+c_secon)
if c*pk_A != A:
c_first = [-i for i in c_first]
c = vector(ZZ, c_first+c_secon)

if c*pk_A != A:
c_first = [-i for i in c_first]
c_secon = [-i for i in c_secon]
c = vector(ZZ, c_first+c_secon)

if c*pk_A != A:
c_first = [-i for i in c_first]
c = vector(ZZ, c_first+c_secon)

print(c*pk_A == A)

msg = int(b - c * pk_b )
if msg > q//2:
msg -= q
m = ZZ(msg % p)
flag_bytes.append(int(m))
print(_,flag_bytes)
# flag{a3bc5491-fa53-4f47-8819-856a8fe5ada0}
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
lwe_public_key = load("lwe_public_key.sobj")
lwe_ciphertext = load("lwe_ciphertext.sobj")
rlwe_ciphertext = load("rlwe_ciphertext.sobj")

# flag2
a, b, f, rlwe_modulus = rlwe_ciphertext
n = 64

A = a
B = b.list()
p = rlwe_modulus
n = 64

#part1 construct matrix of poly_mul

#n:The highest degree of a modular polynomial
#v:vector of modular polynomial
#a:vector of a polynomial multiplier

#aim to construct a matrix of c=a*b%v
def construct_poly_mul_mat(n,v,b):
assert v[-1] == 1 #use this after monic

#step1 construct a matrix of d=a*b
mat1 = Matrix(ZZ,n,2*n-1)
for i in range(n):
for j in range(n):
mat1[i,j+i] = b[j]

#step2 construct a matrix of c=d%v
mat2 = Matrix(ZZ,2*n-1,n)
for i in range(n):
mat2[i,i] = 1
for i in range(n,2*n-1):
for j in range(i-n,n):
mat2[i,j] = -v[j-(i-n)]

init_row = vector(ZZ,n*[0])
for j in range(i-n):
temp = -v[n-1-j]*vector(ZZ,mat2[i-j-1])
init_row += temp
for j in range(n):
mat2[i,j] += init_row[j]

#step3 multiply them and return
return(mat1*mat2)

v = f.list()
poly_mul_mat = construct_poly_mul_mat(n,v,A)

I = identity_matrix(n)
B_mat = Matrix(ZZ,B)
O = diagonal_matrix([0]*n)
O_vec = Matrix(ZZ,1,n)
O_vec_T = Matrix(ZZ,n,1)
L = block_matrix(ZZ,[[p*I,O,0],[poly_mul_mat,I,O_vec_T],[B_mat,O_vec,1]])


#part3 LLL to get s and get flag
res = L.LLL()[0]
s = res[n:2*n]
from Crypto.Util.number import *
for i in s:
print(long_to_bytes(abs(i)).decode(),end = "")
# -8819-856a8fe5ada0

babypqc

未找到正解,我是非预期,直接传的空签名。

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
import ctypes
from random import getrandbits
import signal
import socketserver
from sympy import nextprime
import numpy as np
from Crypto.Util.number import *
import ast


def ll_to_polylist(l):
return list(map(list, list(l)))

class Dilithium:
def __init__(self):
self.dilithium_lib = ctypes.CDLL("./dilithium/libpqcrystals_dilithium2_ref.so")
self.pk_buf = ctypes.c_buffer(1312)
self.sk_buf = ctypes.c_buffer(2560)
self.Q = 8380417
self.N = 256
self.dilithium_lib.pqcrystals_dilithium2_ref_keypair(self.pk_buf, self.sk_buf)

def sign_message(self, message: bytes) -> bytes:
SIGNLEN = 2420
MLEN = len(message)
sm_buf = ctypes.create_string_buffer(SIGNLEN + MLEN)
m_buf = ctypes.create_string_buffer(message)
smlen_buf = ctypes.c_size_t()
self.dilithium_lib.pqcrystals_dilithium2_ref(sm_buf, ctypes.byref(smlen_buf), m_buf, MLEN, self.sk_buf)
return sm_buf.raw[:smlen_buf.value]

def verify_sign(self, message: bytes, signature: bytes) -> bool:
msg_buf = ctypes.create_string_buffer(len(signature))
msg_len = ctypes.c_size_t()
sm_buf = ctypes.create_string_buffer(signature)
result = self.dilithium_lib.pqcrystals_dilithium2_ref_open(msg_buf, ctypes.byref(msg_len), sm_buf, len(signature), self.pk_buf)
return result == 0 and message == msg_buf.raw[:msg_len.value]


class Task(socketserver.BaseRequestHandler):
def __init__(self, *args, **kargs):
super().__init__(*args, **kargs)


def timeout_handler(self, signum, frame):
raise TimeoutError


def dosend(self, msg):
try:
self.request.sendall(msg.encode('latin-1') + b'\n')
except:
pass


def recvline(self, msg = None):
if msg:
self.request.sendall(msg.encode('latin-1'))
try:
data = b""
while True:
chunk = self.request.recv(1)
if not chunk:
break
data += chunk
if chunk == b'\n':
break
except:
pass

line = data.strip().decode()
return line


def generate_prime(self, BITS):
a = getrandbits(BITS)
b = a << 282
c = nextprime(b)
return c


def generate_coefs(self, BITS, LEN):
return [getrandbits(BITS) for _ in range(LEN)]


def get_sk(self):
poly_t = ctypes.c_int32 * self.dilithium.N
polyvec_t = poly_t * 4
rho = ctypes.c_buffer(32)
tr = ctypes.c_buffer(64)
key = ctypes.c_buffer(32)
t0 = polyvec_t()
s1 = polyvec_t()
s2 = polyvec_t()
self.dilithium.dilithium_lib.pqcrystals_dilithium2_ref_unpack_sk(rho, tr, key, t0, s1, s2, self.dilithium.sk_buf)
return ll_to_polylist(s1), ll_to_polylist(s2)


def handle(self):
signal.signal(signal.SIGALRM, self.timeout_handler)
signal.alarm(40)
self.dosend("welcome to my crypto system!")
delta = 1184
beta = 256
tau = 704
self.m = getrandbits(beta)
self.dilithium = Dilithium()

p = self.generate_prime(delta)
q = self.generate_prime(delta)
N = [p * q]
ROUND = 25
for _ in range(ROUND):
d = getrandbits(704)
N.append((p + d) * (q + d))
self.dosend("N = " + str(N))
s1, s2 = self.get_sk()
s1 = np.array([i for j in s1 for i in j])
s2 = np.array([i for j in s2 for i in j])
H = []
for i in range(ROUND * ROUND):
tmp = np.array(self.generate_coefs(32, 1024))
H.append(int(tmp.dot(s1) % self.dilithium.Q ))
tmp = np.array(self.generate_coefs(32, 1024))
H.append(int(tmp.dot(s2) % self.dilithium.Q))

self.dosend("this is your hint!")
self.dosend("H = " + str(H))
self.dosend("another gift: you can choose one message to sign")
m = int(self.recvline("m: "))
signature = self.dilithium.sign_message(long_to_bytes(m))
assert self.dilithium.verify_sign(long_to_bytes(m), signature)
self.dosend("this is your signature")
self.dosend("sinature = " + signature.hex())
num = self.generate_coefs(4, 1)[0]
self.dosend("you need to give me some signatures in hex format!")
signatures = ast.literal_eval(self.recvline("signatures: "))
assert len(list(set(signatures))) == len(signatures)
answers = sum([self.dilithium.verify_sign(long_to_bytes(self.m), bytes.fromhex(sinature.zfill(len(signature) + len(signature)%2))) for sinature in signatures])
if answers == num:
self.dosend("congrats! you got the flag!")
with open("flag.txt") as f:
self.dosend(f.read())
else:
self.dosend("sorry, you failed!")
exit()



class ThreadedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
pass


if __name__ == "__main__":
HOST, PORT = '0.0.0.0', 13337
server = ThreadedServer((HOST, PORT), Task)
server.allow_reuse_address = True
server.serve_forever()



不会做。

b42d2a4b-b349-4ea8-b08b-e170ddc6b3aa

后续等一波鸡块博客了((

总结

怎么说呢,题其实不好,以至于我听说很多水平特别高的师傅都没有做的很好,挺抽象的。

运气挺好,大家都很给力!

继续加油吧。


2024-CISCN/铁人三项初赛-wp-Crypto
https://py-thok.github.io/2024/12/19/2024-CISCN-铁人三项初赛-wp-Crypto/
作者
PYthok-Ptk
发布于
2024年12月19日
许可协议