WHUCTF2023

Lattice

题面

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
from random import randint

from gmpy2 import gcd, invert

from Crypto.Util.number import bytes_to_long, long_to_bytes

from flag import flag




def genKey(_n):

    _privKey = [randint(1, pow(4, _n))]

    s = _privKey[0]

    for i in range(1, _n):

        _privKey.append(randint(s + 1, pow(4, _n + i)))

        s += _privKey[i]



    _q = randint(_privKey[_n - 1] + 1, 2 * _privKey[_n - 1])



    _r = randint(1, _q)

    while gcd(_r, _q) != 1:

        _r = randint(1, _q)



    _pubKey = [_r * _ % _q for _ in _privKey]

    return _privKey, _q, _r, _pubKey




def encrypt(_msg, _pubKey):

    cipher = 0

    cnt = 0

    for bit in _msg:

        cipher += int(bit) * _pubKey[cnt]

        cnt += 1

    return bin(cipher)[2:]




def decrypt(_c, _privKey, _q, _r):

    s = invert(_r, _q)

    _msg = int(_c, 2) * s % _q



    res = ''

    for i in range(len(_privKey) - 1, -1, -1):

        if _msg >= _privKey[i]:

            res = '1' + res

            _msg -= _privKey[i]

        else:

            res = '0' + res

    return res




bin_msg = bin(bytes_to_long(flag))[2:]

private_key, q, r, public_key = genKey(len(bin_msg))

enc = encrypt(bin_msg, public_key)

print(f'pubKey = {public_key}')

print(f'enc = {int(enc, 2)}')

一个背包格,应该…
Lattice入门题,打格子

(a0,a1,,an1,1)(100key0010key1000enc)=(a0,a1,,an1,0)(a_{0},a_{1},\dots,a_{n-1},1)\begin{pmatrix}1&0&0&\dots&key_{0}\\0&1&0&\dots&key_1\\\vdots&&&\dots&\vdots\\0&0&0&\dots&-enc\end{pmatrix}=(a_{0},a_{1},\dots,a_{n-1},0)

不用配系数直接打就ok
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
pubKey = [...]
enc = ...

k = 1

M = matrix(ZZ,len(pubKey)+1,len(pubKey)+1)

for i in range(len(pubKey)):

    M[i,i] = 1

    M[i,len(pubKey)] = pubKey[i] * k

M[len(pubKey),len(pubKey)] = -int(enc)

# print(M)

L = M.LLL()

for i in range(len(pubKey)+1):

    line = L.row(i).list()

    tag = 0

    for i in line:

        if i != 0 and i != 1:

            tag = 1

            break

    if tag == 0:

        res = ''.join(map(str, line[:-1]))

        print(long_to_bytes(int(res,2)))

# NOCTF{Merkl3_H3llman_Att4cks_1s_4_lattic3_go0d_st4rt}