文章目录
easy_mod
task.py
python
from Crypto.Util.number import *
from random import *
table = "01234567"
p = getPrime(328)
flag = b"NSSCTF{" + "".join([choice(table) for i in range(70)]).encode() + b"}"
c = bytes_to_long(flag) % p
print("p =",p)
print("c =",c)
'''
p = ...
c = ...
'''
analysis
- 初始构建格
c = m ( m o d p ) → m = k p + c → L = [ 0 1 p c ] → L ⋅ [ k 1 ] = [ 1 m ] = v ⃗ c=m\pmod{p}\rightarrow m=kp+c\rightarrow L=\left[ \begin{matrix} 0 & 1\\ p & c \end{matrix} \right]\rightarrow L\cdot \left[ \begin{matrix} k\\ 1 \end{matrix} \right]=\left[ \begin{matrix} 1\\ m \end{matrix} \right]=\vec{v} c=m(modp)→m=kp+c→L=[0p1c]→L⋅[k1]=[1m]=v
∣ ∣ v ⃗ ∣ ∣ = 1 + m 2 ≈ 2 623 ∧ 2 ⋅ d e t ( L ) = 2 ⋅ p 1 2 ≈ 2 164 ||\vec{v}||=\sqrt{1+m^2}≈2^{623}\land \sqrt{2}\cdot det(L)=\sqrt{2}\cdot p^{1\over2}≈2^{164} ∣∣v ∣∣=1+m2 ≈2623∧2 ⋅det(L)=2 ⋅p21≈2164 - 尝试优化格
L = [ 0 2 623 p c ] → L ⋅ [ k 1 ] = [ 2 623 m ] = v ⃗ → ∣ ∣ v ⃗ ∣ ∣ ≈ 2 ⋅ 2 623 > b o u n d = 2 ⋅ ( 2 623 ⋅ p ) 1 2 ≈ 2 ⋅ 2 475 L=\left[ \begin{matrix} 0 & 2 ^{623}\\ p & c \end{matrix} \right]\rightarrow L\cdot \left[ \begin{matrix} k\\ 1 \end{matrix} \right]=\left[ \begin{matrix} 2^{623}\\ m \end{matrix} \right]=\vec{v}\rightarrow ||\vec{v}||≈\sqrt{2}\cdot2^{623}>bound=\sqrt{2}\cdot(2^{623}\cdot p)^{1\over2}≈\sqrt{2}\cdot 2^{475} L=[0p2623c]→L⋅[k1]=[2623m]=v →∣∣v ∣∣≈2 ⋅2623>bound=2 ⋅(2623⋅p)21≈2 ⋅2475 - 这里想到 m m m是很大的,能否将 m m m移出目标向量 v ⃗ \vec{v} v ,采用间接求解的方式
L = [ 0 0 1 0 1 0 1 − p − c ] , b ⃗ = [ m k 1 ] , L ⋅ b ⃗ = [ 1 k 0 ] = v ⃗ L=\left[ \begin{matrix} 0 & 0 & 1\\ 0 & 1 & 0\\ 1 & -p & -c \end{matrix} \right],\vec{b}=\left[ \begin{matrix} m\\ k\\ 1 \end{matrix} \right],L\cdot\vec{b}=\left[ \begin{matrix} 1\\ k\\ 0 \end{matrix} \right]=\vec{v} L= 00101−p10−c ,b = mk1 ,L⋅b = 1k0 =v
L = [ 0 0 2 295 0 1 0 1 − p − c ] → L ⋅ b ⃗ = v 2 ⃗ → ∣ ∣ v ⃗ ∣ ∣ ≈ 2 ⋅ 2 295 > b o u n d = 3 ⋅ ( 2 295 ) 1 3 ≈ 3 ⋅ 2 98 L = \left[ \begin{matrix} 0 & 0 & 2^{295}\\ 0 & 1 & 0\\ 1 & -p & -c \end{matrix} \right]\rightarrow L\cdot\vec{b}=\vec{v_2}\rightarrow||\vec{v}||≈\sqrt{2}\cdot2^{295}>bound=\sqrt{3}\cdot (2^{295})^{1\over3}≈\sqrt{3}\cdot2^{98} L= 00101−p22950−c →L⋅b =v2 →∣∣v ∣∣≈2 ⋅2295>bound=3 ⋅(2295)31≈3 ⋅298 - 方法依旧行不通,这道题目另外一个特别的地方就在于 f l a g flag flag的生成方式为
b"NSSCTF{" + "".join([choice(table) for i in range(70)]).encode() + b"}",因此可以用类似于多项式的形式表示出 m m m,另 t = 2 8 t=2^8 t=28,则
m = t 0 ⋅ o r d ( ′ } ′ ) + t 1 ⋅ o r d ( m 70 ) + ⋯ + t 70 ⋅ o r d ( m 0 ) + t 71 ⋅ l o n g _ t o _ b y t e s ( b ′ N S S C T F { ′ ) m=t^0\cdot ord('\}')+t^1\cdot ord(m_{70})+\cdots+t^{70}\cdot ord(m_{0})+t^{71}\cdot long\_to\_bytes(b'NSSCTF\{') m=t0⋅ord(′}′)+t1⋅ord(m70)+⋯+t70⋅ord(m0)+t71⋅long_to_bytes(b′NSSCTF{′) - 于此同时, f l a g flag flag的字符集也来自于 0 − 7 0-7 0−7之间,则 o r d ( m i ) ∈ [ 48 , 55 ] ord(m_i)\in[48,55] ord(mi)∈[48,55],则 i n t ( m i ) = o r d ( m i ) − 48 int(m_i)=ord(m_i)-48 int(mi)=ord(mi)−48可以进一步减小待求解值的取值范围。起初我构建的格修正如下:
t e m p = o r d ( ′ } ′ ) + t 1 ⋅ 48 + t 2 ⋅ 48 + ⋯ + t 71 ⋅ l o n g _ t o _ b y t e s ( b ′ N S S C T F { ′ ) temp=ord('\}')+t^1\cdot48+t^{2}\cdot 48+\cdots+t^{71}\cdot long\to\bytes(b'NSSCTF\{') temp=ord(′}′)+t1⋅48+t2⋅48+⋯+t71⋅long_to_bytes(b′NSSCTF{′)
→ m = t e m p + t 1 ⋅ m 70 ′ + ⋯ + t 70 ⋅ m 0 ′ \rightarrow m=temp+t^1\cdot m{70}'+\cdots+t^{70}\cdot m_0' →m=temp+t1⋅m70′+⋯+t70⋅m0′
L = [ 0 0 0 ⋯ 0 1 0 0 0 ⋯ 1 0 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ t e m p t 1 t 2 ⋯ t 69 t 70 ] , b ⃗ = [ 1 m 70 ′ ⋮ m 0 ′ ] → L ⋅ b ⃗ = [ m 0 ′ m 1 ′ ⋮ m ] = v ⃗ L=\left[ \begin{matrix} 0 & 0 & 0 & \cdots & 0 & 1\\ 0 & 0 & 0 & \cdots & 1 & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots\\ temp & t^1 & t^2 & \cdots & t^{69} & t^{70} \end{matrix} \right],\vec{b}=\left[ \begin{matrix} 1\\ m{70}'\\ \vdots\\ m_{0}' \end{matrix} \right]\rightarrow L\cdot \vec{b}=\left[ \begin{matrix} m_0'\\ m_1'\\ \vdots\\ m \end{matrix} \right]=\vec{v} L= 00⋮temp00⋮t100⋮t2⋯⋯⋱⋯01⋮t6910⋮t70 ,b = 1m70′⋮m0′ →L⋅b = m0′m1′⋮m =v - 这个时候发现 ∣ ∣ v ⃗ ∣ ∣ ||\vec{v}|| ∣∣v ∣∣还是由 m m m的大小主导,而 L L L本身是可以调整的,但是最终调整之后的结果应该就是 b o u n d ≈ 71 ⋅ ( t e m p ⋅ ( 2 623 ) 70 ) 1 71 bound≈\sqrt{71}\cdot(temp\cdot(2^{623})^{70})^{1\over71} bound≈71 ⋅(temp⋅(2623)70)711,而目标向量长度 ∣ ∣ v ⃗ ∣ ∣ ≈ 71 ⋅ m ≈ 71 ⋅ 2 623 ||\vec{v}||≈\sqrt{71}\cdot m≈ \sqrt{71}\cdot2^{623} ∣∣v ∣∣≈71 ⋅m≈71 ⋅2623, v ⃗ \vec{v} v 还是没有落在最短向量的区间内,这里发现我们并没有用到 c ≡ m ( m o d p ) → m − k p − c = 0 c\equiv m\pmod{p}\rightarrow m-kp-c=0 c≡m(modp)→m−kp−c=0的条件,如果加上的话,此时 v ⃗ \vec{v} v 中就不再有 m m m了,是剩下 m i ′ ∈ [ 0 , 7 ] m_{i}'\in[0,7] mi′∈[0,7]了,就会变得非常短。
L = [ 0 0 0 ⋯ 0 0 1 0 0 0 ⋯ 0 1 0 0 0 0 ⋯ 1 0 0 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ ⋮ 0 0 1 ⋯ 0 0 0 0 1 0 ⋯ 0 0 0 − p − c t e m p ⋯ t 68 t 69 t 70 ] , b ⃗ = [ k 1 1 ⋮ m 2 ′ m 1 ′ m 0 ′ ] → L ⋅ b ⃗ = [ m 0 ′ m 1 ′ m 2 ′ ⋮ 1 1 0 ] = v ⃗ L=\left[ \begin{matrix} 0 & 0 & 0 & \cdots &0 & 0 & 1\\ 0 & 0 & 0 & \cdots & 0 & 1 & 0\\ 0 & 0 & 0 & \cdots & 1 & 0 & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots\\ 0 & 0 & 1 & \cdots & 0 & 0 & 0\\ 0 & 1 & 0 & \cdots & 0 & 0 & 0\\ -p & -c & temp & \cdots & t^{68}& t^{69} & t^{70} \end{matrix} \right],\vec{b}=\left[ \begin{matrix} k\\ 1\\ 1\\ \vdots\\ m_{2}'\\ m_1'\\ m_{0}' \end{matrix} \right]\rightarrow L\cdot \vec{b}=\left[ \begin{matrix} m_0'\\ m_1'\\ m_2'\\ \vdots\\ 1\\ 1\\ 0 \end{matrix} \right]=\vec{v} L= 000⋮00−p000⋮01−c000⋮10temp⋯⋯⋯⋱⋯⋯⋯001⋮00t68010⋮00t69100⋮00t70 ,b = k11⋮m2′m1′m0′ →L⋅b = m0′m1′m2′⋮110 =v
∣ ∣ v ⃗ ∣ ∣ ≤ 70 × 7 + 2 , b o u n d = 73 ⋅ p 1 73 ≈ 73 ⋅ 2 4 ||\vec{v}||≤\sqrt{70× 7 + 2},bound=\sqrt{73}\cdot p^{1\over73}≈\sqrt{73}\cdot 2^4 ∣∣v ∣∣≤70×7+2 ,bound=73 ⋅p731≈73 ⋅24 - 注意到 70 × 7 + 2 = 492 > 2 8 70×7+2=492>2^8 70×7+2=492>28,所以为了保险起见,可以对 v ⃗ \vec{v} v 后面的两个 1 1 1进行一下参数调整。为什么要调整这两个参数而不是其他参数,其一是因为其不是主导项( 1 < 7 1<7 1<7),其二是因为其他参数在 L L L中调整的话,就会影响到 v ⃗ \vec{v} v 中的 m i ′ m_i' mi′变为 a ⋅ m i ′ a\cdot m_i' a⋅mi′。最终确定的格为:
L = [ 0 0 0 ⋯ 0 0 1 0 0 0 ⋯ 0 1 0 0 0 0 ⋯ 1 0 0 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ ⋮ 0 0 2 ⋯ 0 0 0 0 2 0 ⋯ 0 0 0 − p − c t e m p ⋯ t 68 t 69 t 70 ] L=\left[ \begin{matrix} 0 & 0 & 0 & \cdots &0 & 0 & 1\\ 0 & 0 & 0 & \cdots & 0 & 1 & 0\\ 0 & 0 & 0 & \cdots & 1 & 0 & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots\\ 0 & 0 & 2 & \cdots & 0 & 0 & 0\\ 0 & 2 & 0 & \cdots & 0 & 0 & 0\\ -p & -c & temp & \cdots & t^{68}& t^{69} & t^{70} \end{matrix} \right] L= 000⋮00−p000⋮02−c000⋮20temp⋯⋯⋯⋱⋯⋯⋯001⋮00t68010⋮00t69100⋮00t70 - 这里后面想了想,我们在计算 ∣ ∣ v ⃗ ∣ ∣ ||\vec{v}|| ∣∣v ∣∣的时候是取 m i = 7 m_i=7 mi=7计算的,如果视作均匀分布的情况下,应该视作 m i = 4 m_i=4 mi=4计算,并且参数调整的方式有很多,为了保险起见,别的参数调整方案也是可以的,目的就是想让 ∣ ∣ v ⃗ ∣ ∣ ||\vec{v}|| ∣∣v ∣∣落在最短向量的可能范围内。
exp.sage
python
from Crypto.Util.number import long_to_bytes, bytes_to_long
p = 501785758961383005891491265699612686883993041794260611346802080899615437298977076093878384543577171
c = 327005346153237517234971706274055111857447948791422192829214537757745905845319188257204611848165263
n = 70
t = 2 ** 8
Sn = t * (1 - t ** 70) // (1 - t)
temp = ord('}') + 48 * Sn + t ** 71 * bytes_to_long(b'NSSCTF{')
M = []
for i in range(n + 3):
v = [0] * (n + 3)
v[n + 3 - 1 - i] = 1
M.append(v)
M[n + 3 - 1 - 2][2] = 2
M[n + 3 - 1 - 1][1] = 2
M[n + 3 - 1][0] = -p
M[n + 3 - 1][1] = -c
M[n + 3 - 1][2] = temp
for i in range(70):
M[n + 3 - 1][3 + i] = t ** (i + 1)
M = Matrix(ZZ, M)
L = M.transpose().BKZ(block_size=20)
for row in L:
if row[-1] == 0 and all(0 <= int(mi) <= 7 for mi in row[:70]):
flag = 'NSSCTF{' + ''.join([str(abs(mi)) for mi in row[:n]]) + '}'
print(flag)
break
# NSSCTF{5036541772751046406531362142757356307107252723754051320011253505562041}
easy_mod2
task.py
python
from Crypto.Util.number import *
from random import *
table = "01234567"
p = getPrime(328)
flag = b"NSSCTF{" + "".join([choice(table) for i in range(80)]).encode() + b"}"
m = bytes_to_long(flag)
print(m.bit_length()) # 703
c = m % p
print("p =",p)
print("c =",c)
# print(flag)
'''
p = ...
c = ...
'''
analysis
c ≡ m ( m o d p ) → m = k p + c → m − k p − c = 0 c\equiv m\pmod{p}\rightarrow m=kp+c\rightarrow m-kp-c=0 c≡m(modp)→m=kp+c→m−kp−c=0
- 根据上面的一道题目的思想, m m m是很大的,我们要充分利用信息来进行表示 m m m,使得 m m m的未知比特数尽可能地少:
m = m 80 ∣ ∣ m 79 ∣ ∣ ⋯ ∣ ∣ m 2 ∣ ∣ m 1 m=m_{80}||m_{79}||\cdots||m_{2}||m_{1} m=m80∣∣m79∣∣⋯∣∣m2∣∣m1
t = 2 8 ; m = t 0 ⋅ o r d ( ′ } ′ ) + t 1 ⋅ m 1 + ⋯ + t 80 ⋅ m 80 + t 81 ⋅ b y t e s _ t o _ l o n g ( b ′ N S S C T F { ′ ) t=2^8;m=t^0\cdot ord('\}')+t^1\cdot m_1+\cdots + t^{80}\cdot m_{80}+t^{81}\cdot bytes\_to\_long(b'NSSCTF\{') t=28;m=t0⋅ord(′}′)+t1⋅m1+⋯+t80⋅m80+t81⋅bytes_to_long(b′NSSCTF{′)
m i = i n t ( m i ) + 48 ; t e m p = t 0 ⋅ o r d ( ′ } ′ ) + t 1 ⋅ 48 + ⋯ t 80 ⋅ 48 + t 81 ⋅ b y t e s _ t o _ l o n g ( b ′ N S S C T F { ′ ) m_i=int(m_i)+48;temp=t^0\cdot ord('\}')+t^1\cdot 48+\cdots t^{80}\cdot 48+t^{81}\cdot bytes\_to\long(b'NSSCTF\{') mi=int(mi)+48;temp=t0⋅ord(′}′)+t1⋅48+⋯t80⋅48+t81⋅bytes_to_long(b′NSSCTF{′)
m = t e m p + t 1 ⋅ i n t ( m 1 ) + t 2 ⋅ i n t ( m 2 ) + ⋯ + t 80 ⋅ i n t ( m 80 ) m=temp+t^1\cdot int(m_1)+t^2\cdot int(m_2)+\cdots + t^{80}\cdot int(m{80}) m=temp+t1⋅int(m1)+t2⋅int(m2)+⋯+t80⋅int(m80)
L = [ 0 0 0 ⋯ 0 0 1 0 0 0 ⋯ 0 1 0 0 0 0 ⋯ 1 0 0 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ ⋮ 0 0 3 ⋯ 0 0 0 0 3 0 ⋯ 0 0 0 − p − c t e m p ⋯ t 78 t 79 t 80 ] ; b ⃗ = [ k 1 1 ⋮ i n t ( m 78 ) i n t ( m 79 ) i n t ( m 80 ) ] → L ⋅ b ⃗ = [ i n t ( m 80 ) i n t ( m 79 ) i n t ( m 78 ) ⋮ 3 3 0 ] = v ⃗ L=\left[ \begin{matrix} 0 & 0 & 0 & \cdots & 0 & 0 & 1\\ 0 & 0 & 0 & \cdots & 0 & 1 & 0\\ 0 & 0 & 0 & \cdots & 1 & 0 & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots\\ 0 & 0 & 3 & \cdots & 0 & 0 & 0\\ 0 & 3 & 0 & \cdots & 0 & 0 & 0\\ -p & -c & temp & \cdots & t^{78} & t^{79} & t^{80} \end{matrix} \right];\vec{b}=\left[ \begin{matrix} k\\ 1\\ 1\\ \vdots\\ int(m_{78})\\ int(m_{79})\\ int(m_{80}) \end{matrix} \right]\rightarrow L\cdot \vec{b}=\left[ \begin{matrix} int(m_{80})\\ int(m_{79})\\ int(m_{78})\\ \vdots\\ 3\\ 3\\ 0 \end{matrix} \right]=\vec{v} L= 000⋮00−p000⋮03−c000⋮30temp⋯⋯⋯⋱⋯⋯⋯001⋮00t78010⋮00t79100⋮00t80 ;b = k11⋮int(m78)int(m79)int(m80) →L⋅b = int(m80)int(m79)int(m78)⋮330 =v
∣ ∣ v ⃗ ∣ ∣ ≤ 9 + 80 × 7 2 ≈ 2 6 ≈ b o u n d = 83 ⋅ ( 9 p ) 1 83 > 2 6 ||\vec{v}||≤\sqrt{9+80×7^2}≈2^6≈bound=\sqrt{83}\cdot(9p)^{1\over83}>2^6 ∣∣v ∣∣≤9+80×72 ≈26≈bound=83 ⋅(9p)831>26
- 这里发现边界条件满足 ∣ ∣ v ⃗ ∣ ∣ < b o u n d ||\vec{v}||<bound ∣∣v ∣∣<bound很极限,尝试像第一道题目一样编写解题脚本发现并不能找到我们想要的目标向量,这里需要的知识点就是中心化 了,我们目前已知 i n t ( m i ) ∈ { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 } int(m_i)\in\{0,1,2,3,4,5,6,7\} int(mi)∈{0,1,2,3,4,5,6,7},中心化 之后为 m i ′ ∈ { − 3 , − 2 , − 1 , 0 , 1 , 2 , 3 , 4 } m_i'\in\{-3,-2,-1,0,1,2,3,4\} mi′∈{−3,−2,−1,0,1,2,3,4},也就是我们进行了下述转换 m i = 51 + m i ′ m_i=51+m_i' mi=51+mi′,此时格的构建如下:
t e m p ′ = t 0 ⋅ o r d ( ′ } ′ ) + t 1 ⋅ 51 + ⋯ t 80 ⋅ 51 + t 81 ⋅ b y t e s _ t o _ l o n g ( b ′ N S S C T F { ′ ) temp'=t^0\cdot ord('\}')+t^1\cdot 51+\cdots t^{80}\cdot 51+t^{81}\cdot bytes\to\long(b'NSSCTF\{') temp′=t0⋅ord(′}′)+t1⋅51+⋯t80⋅51+t81⋅bytes_to_long(b′NSSCTF{′)
L = [ 0 0 0 ⋯ 0 0 1 0 0 0 ⋯ 0 1 0 0 0 0 ⋯ 1 0 0 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ ⋮ 0 0 3 ⋯ 0 0 0 0 3 0 ⋯ 0 0 0 − p − c t e m p ′ ⋯ t 78 t 79 t 80 ] ; b ⃗ = [ k 1 1 ⋮ m 78 ′ m 79 ′ m 80 ′ ] → L ⋅ b ⃗ = [ m 80 ′ m 79 ′ m 78 ′ ⋮ 3 3 0 ] = v ⃗ L=\left[ \begin{matrix} 0 & 0 & 0 & \cdots & 0 & 0 & 1\\ 0 & 0 & 0 & \cdots & 0 & 1 & 0\\ 0 & 0 & 0 & \cdots & 1 & 0 & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots\\ 0 & 0 & 3 & \cdots & 0 & 0 & 0\\ 0 & 3 & 0 & \cdots & 0 & 0 & 0\\ -p & -c & temp' & \cdots & t^{78} & t^{79} & t^{80} \end{matrix} \right];\vec{b}=\left[ \begin{matrix} k\\ 1\\ 1\\ \vdots\\ m{78}'\\ m{79}'\\ m_{80}' \end{matrix} \right]\rightarrow L\cdot \vec{b}=\left[ \begin{matrix} m_{80}'\\ m_{79}'\\ m_{78}'\\ \vdots\\ 3\\ 3\\ 0 \end{matrix} \right]=\vec{v} L= 000⋮00−p000⋮03−c000⋮30temp′⋯⋯⋯⋱⋯⋯⋯001⋮00t78010⋮00t79100⋮00t80 ;b = k11⋮m78′m79′m80′ →L⋅b = m80′m79′m78′⋮330 =v
∣ ∣ v ⃗ ∣ ∣ ≤ 3 2 + 3 2 + 80 × 4 2 ≈ 2 5.5 ||\vec{v}||≤\sqrt{3^2+3^2+80×4^2}≈2^{5.5} ∣∣v ∣∣≤32+32+80×42 ≈25.5
exp.sage
python
from Crypto.Util.number import long_to_bytes, bytes_to_long
p = 324556397741108806830285502585098109678766437252172614832253074632331911859471735318636292671562523
c = 141624663734155235543198856069652171779130720945875442624943917912062658275440028763836569215230250
t = 2 ** 8
temp = ord('}') + (t ** 81) * bytes_to_long(b'NSSCTF{')
for i in range(1, 81):
temp += 51 * (t ** i)
M = []
for i in range(82):
v = vector(ZZ, 83)
v = list(v)
v[82 - i] = 1
M.append(v)
M[80][2] = 3
M[81][1] = 3
M.append([-p, -c, temp] + [t ** i for i in range(1, 81)])
M = Matrix(ZZ, M)
L = M.transpose().BKZ(block_size=20)
# print(L)
for row in L:
if row[-1] == 0 and abs(row[-2]) == 3 and abs(row[-3]) == 3 and all(0 <= abs(mi) <= 4 for mi in row[:80]):
print("NSSCTF{", end = "")
for i in range(80):
print(chr(row[i] + 51), end = "")
print("}")
break
# NSSCTF{25350625451533421162474265547571536103420331260232652121722452361537257541460235}
easy_mod3
task.py
python
from Crypto.Util.number import *
from random import *
table = "Nss"
p = getPrime(328)
flag = b"NSSCTF{" + "".join([choice(table) for i in range(100)]).encode() + b"}"
m = bytes_to_long(flag)
# print(m.bit_length()) # 863
c = m % p
print("p =",p)
print("c =",c)
'''
p = 421384892562377694077340767015240048728671794320496268132504965422627021346504549648945043590200571
c = 273111533929258227142700975315635731051782710899867431150541189647916512765137757827512121549727178
'''
analysis
- m . b i t _ l e n g t h ( ) = 863 m.bit\_length()=863 m.bit_length()=863,与前面两道题目类似, m i ∈ { 78 , 115 } m_i\in\{78,115\} mi∈{78,115},原本想要顺着
easy_mod2的思路进行中心化, m i = 96 + m i ′ ; m i ′ ∈ { − 18 , 19 } m_i=96+m_i';m_i'\in\{-18,19\} mi=96+mi′;mi′∈{−18,19},但是我们可以发现,在 f l a g flag flag长度更长的同时, m i ′ m_i' mi′的长度区间却变得更长,也就是 v ⃗ \vec{v} v 的长度会明显比 m i ′ ∈ { − 3 , − 2 , − 1 , 0 , 1 , 2 , 3 , 4 } m_i'\in\{-3,-2,-1,0,1,2,3,4\} mi′∈{−3,−2,−1,0,1,2,3,4}更长,因此大概率是要寻找新的思路了。 - m i = 78 + 37 ⋅ m i ′ ; m i ′ ∈ { 0 , 1 } m_i=78+37\cdot m_i';m_i'\in\{0,1\} mi=78+37⋅mi′;mi′∈{0,1},如果我们能建设出来一个基于 m i ′ m_i' mi′的格,我们可以发现此时的 v ⃗ \vec{v} v 长度就会大大缩短。
c ≡ m ( m o d p ) → m = k p + c → k p + c − m = 0 c\equiv m\pmod{p}\rightarrow m=kp+c\rightarrow kp+c-m=0 c≡m(modp)→m=kp+c→kp+c−m=0
t = 2 8 ; m = t 0 ⋅ o r d ( ′ } ′ ) + t 1 ⋅ m 1 + ⋯ + t 100 m 100 + t 101 ⋅ b y t e s _ t o _ l o n g ( b ′ N S S C T F { ′ ) t=2^8;m=t^0\cdot ord('\}')+t^1\cdot m_1+\cdots+t^{100}m_{100}+t^{101}\cdot bytes\to\long(b'NSSCTF\{') t=28;m=t0⋅ord(′}′)+t1⋅m1+⋯+t100m100+t101⋅bytes_to_long(b′NSSCTF{′)
m i = 78 + 37 ⋅ m i ′ ; t e m p = t 0 ⋅ o r d ( ′ } ′ ) + t 1 ⋅ 78 + ⋯ + t 100 ⋅ 78 + t 101 ⋅ b y t e s _ t o _ l o n g ( b ′ N S S C T F { ′ ) m_i=78+37\cdot m_i';temp=t^0\cdot ord('\}')+t^1\cdot78+\cdots + t^{100}\cdot 78+t^{101}\cdot bytes\to\long(b'NSSCTF\{') mi=78+37⋅mi′;temp=t0⋅ord(′}′)+t1⋅78+⋯+t100⋅78+t101⋅bytes_to_long(b′NSSCTF{′)
∑ i = 1 100 ( t i ⋅ 37 ⋅ m i ′ ) + t e m p − k p − c = 0 \sum{i=1}^{100}{(t^{i}\cdot 37\cdot m_i')}+temp-kp-c=0 i=1∑100(ti⋅37⋅mi′)+temp−kp−c=0
L = [ 0 0 0 ⋯ 0 0 1 0 0 0 ⋯ 0 1 0 0 0 0 ⋯ 1 0 0 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ ⋮ 0 0 1 ⋯ 0 0 0 0 1 0 ⋯ 0 0 0 − p − c t e m p ⋯ 37 ⋅ t 98 37 ⋅ t 99 37 ⋅ t 100 ] ; b ⃗ = [ k 1 1 ⋮ m 98 ′ m 99 ′ m 100 ′ ] → L ⋅ b ⃗ = [ m 100 ′ m 99 ′ m 98 ′ ⋮ 1 1 0 ] = v ⃗ L=\left[ \begin{matrix} 0 & 0 & 0 & \cdots & 0 & 0 & 1\\ 0 & 0 & 0 & \cdots & 0 & 1 & 0\\ 0 & 0 & 0 & \cdots & 1 & 0 & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots\\ 0 & 0 & 1 & \cdots & 0 & 0 & 0\\ 0 & 1 & 0 & \cdots & 0 & 0 & 0\\ -p & -c & temp & \cdots & 37\cdot t^{98} & 37\cdot t^{99} & 37\cdot t^{100} \end{matrix} \right];\vec{b}=\left[ \begin{matrix} k\\ 1\\ 1\\ \vdots\\ m{98}'\\ m{99}'\\ m{100}' \end{matrix} \right]\rightarrow L\cdot \vec{b}=\left[ \begin{matrix} m_{100}'\\ m_{99}'\\ m_{98}'\\ \vdots\\ 1\\ 1\\ 0 \end{matrix} \right]=\vec{v} L= 000⋮00−p000⋮01−c000⋮10temp⋯⋯⋯⋱⋯⋯⋯001⋮0037⋅t98010⋮0037⋅t99100⋮0037⋅t100 ;b = k11⋮m98′m99′m100′ →L⋅b = m100′m99′m98′⋮110 =v
m i ′ ∈ { 0 , 1 } → ( m i ′ ) 2 ‾ = 0.5 → ∣ ∣ v ⃗ ∣ ∣ ≈ 1 2 + 1 2 + 100 ⋅ 0.5 = 52 ≈ 7.211 < b o u n d = 103 ⋅ p 1 103 m_i'\in\{0,1\}\rightarrow \overline{(m_i')^2}=0.5\rightarrow||\vec{v}||≈\sqrt{1^2+1^2+100\cdot0.5}=\sqrt{52}≈7.211<bound=\sqrt{103}\cdot p^{1\over 103} mi′∈{0,1}→(mi′)2=0.5→∣∣v ∣∣≈12+12+100⋅0.5 =52 ≈7.211<bound=103 ⋅p1031
exp.sage
python
from Crypto.Util.number import long_to_bytes, bytes_to_long
p = 421384892562377694077340767015240048728671794320496268132504965422627021346504549648945043590200571
c = 273111533929258227142700975315635731051782710899867431150541189647916512765137757827512121549727178
t = 2 ** 8
temp = ord('}') + t ** 101 * bytes_to_long(b'NSSCTF{')
for i in range(1, 101):
temp += 78 * t ** i
M = []
for i in range(102):
v = [0] * 103
v[102 - i] = 1
M.append(v)
M.append([-p, -c, temp] + [37 * t ** i for i in range(1, 101)])
M = Matrix(ZZ, M)
L = M.transpose().BKZ(block_size=10)
for row in L:
if row[-1] == 0 and abs(row[-2]) == 1 and abs(row[-3]) == 1:
flag = ""
for i in range(100):
if abs(row[i]) == 1:
flag += 's'
else:
flag += 'N'
print('NSSCTF{' + flag + '}')
# NSSCTF{NNNssNsNNNNsNNNsNNNNNssNNNssNNNsNsNNsNsNNssNNNNNNsNNNssNsNNNNNssNssssNsNNsNsssNNNNssNNNssNsNNssNsNss}
summary
- 在解题的过程中发现
BKZ算法中的block_size=20运行很长时间都没有找到这个最短向量,但是LLL又没有满足我的筛选条件的向量,最后是在调整block_size的情况下找到了我设计的格所规约出来的目标向量。 - 在学习的过程中
Gemini提出最好进行中心化的处理操作,解释如下,在LLL/BKZ算法中,寻找的目标永远是寻找长度(欧几里得范数)最短的向量 ,在 m i ′ ∈ { 0 , 1 } m_i'\in\{0,1\} mi′∈{0,1}的构造中,意味着目标向量的坐标是由 ( 0 , 1 ) (0,1) (0,1)组成的,对于一个 n n n维向量而言,如果每个分量都是 ( 0 , 1 ) (0,1) (0,1),这个可能解会分布在一个顶点为 0 , 1 0,1 0,1的超立方体上,这个超立方体是"偏向"坐标系第一象限的,它没有以原点 ( 0 , 0 , ⋯ , 0 ) (0,0,\cdots,0) (0,0,⋯,0)为中心,由于LLL算法是从远点触发找最短距离,这种"偏心"会导致向量看起来比实际需要的更长。 - 而中心化的思想也是在上面将问题转化为 0 / 1 0/1 0/1背包问题的基础上进行的:
m i = 78 + 37 ⋅ m i ′ [ m i ′ ∈ { 0 , 1 } ] → m i = 78 + 37 ⋅ 1 + m i ′ ′ 2 [ m i ′ ′ ∈ { − 1 , 1 } ] m_i=78+37\cdot m_i'[m_i'\in\{0,1\}]\rightarrow m_i=78+37\cdot {1+m_i''\over 2}[m_i''\in\{-1,1\}] mi=78+37⋅mi′[mi′∈{0,1}]→mi=78+37⋅21+mi′′[mi′′∈{−1,1}] - 由于我们的格只处理整数,所以我们进行如下转化
∑ i = 1 100 ( t i ⋅ 37 ⋅ m i ′ ) + t e m p − k p − c = 0 → ∑ i = 1 100 ( 37 ⋅ t i ⋅ 1 + m i ′ ′ 2 ) + t e m p − k p − c = 0 \sum_{i=1}^{100}{(t^{i}\cdot 37\cdot m_i')}+temp-kp-c=0\rightarrow \sum_{i=1}^{100}{(37\cdot t^{i}\cdot {1+m_i''\over2})}+temp-kp-c=0 i=1∑100(ti⋅37⋅mi′)+temp−kp−c=0→i=1∑100(37⋅ti⋅21+mi′′)+temp−kp−c=0
→ ∑ i = 1 100 ( 37 ⋅ t i ⋅ m i ′ ′ ) + ∑ i = 1 100 ( 37 ⋅ t i ) + 2 ⋅ t e m p − 2 k p − 2 c = 0 [ m i ′ ′ ∈ { − 1 , 1 } ] \rightarrow \sum_{i=1}^{100}(37\cdot t^{i}\cdot m_i'')+\sum_{i=1}^{100}(37\cdot t^i)+2\cdot temp-2kp-2c=0[m_i''\in\{-1,1\}] →i=1∑100(37⋅ti⋅mi′′)+i=1∑100(37⋅ti)+2⋅temp−2kp−2c=0[mi′′∈{−1,1}]
t e m p ′ = ∑ i = 1 100 ( 37 ⋅ t i ) + 2 ⋅ t e m p temp'=\sum_{i=1}^{100}(37\cdot t^i)+2\cdot temp temp′=i=1∑100(37⋅ti)+2⋅temp
L = [ 0 0 0 ⋯ 0 0 1 0 0 0 ⋯ 0 1 0 0 0 0 ⋯ 1 0 0 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ ⋮ 0 0 1 ⋯ 0 0 0 0 1 0 ⋯ 0 0 0 − 2 p − 2 c t e m p ′ ⋯ 37 ⋅ t 98 37 ⋅ t 99 37 ⋅ t 100 ] ; b ⃗ = [ k 1 1 ⋮ m 98 ′ ′ m 99 ′ ′ m 100 ′ ′ ] → L ⋅ b ⃗ = [ m 100 ′ ′ m 99 ′ ′ m 98 ′ ′ ⋮ 1 1 0 ] = v ⃗ L = \left[ \begin{matrix} 0 & 0 & 0 & \cdots & 0 & 0 & 1\\ 0 & 0 & 0 & \cdots & 0 & 1 & 0\\ 0 & 0 & 0 & \cdots & 1 & 0 & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots\\ 0 & 0 & 1 & \cdots & 0 & 0 & 0\\ 0 & 1 & 0 & \cdots & 0 & 0 &0\\ -2p & -2c & temp' & \cdots & 37\cdot t^{98} & 37\cdot t^{99} & 37 \cdot t^{100} \end{matrix} \right];\vec{b}=\left[ \begin{matrix} k\\ 1\\ 1\\ \vdots\\ m_{98}''\\ m_{99}''\\ m_{100}'' \end{matrix} \right]\rightarrow L\cdot \vec{b}=\left[ \begin{matrix} m_{100}''\\ m_{99}''\\ m_{98}''\\ \vdots\\ 1\\ 1\\ 0 \end{matrix} \right]=\vec{v} L= 000⋮00−2p000⋮01−2c000⋮10temp′⋯⋯⋯⋱⋯⋯⋯001⋮0037⋅t98010⋮0037⋅t99100⋮0037⋅t100 ;b = k11⋮m98′′m99′′m100′′ →L⋅b = m100′′m99′′m98′′⋮110 =v
expp.sage
python
from Crypto.Util.number import long_to_bytes, bytes_to_long
p = 421384892562377694077340767015240048728671794320496268132504965422627021346504549648945043590200571
c = 273111533929258227142700975315635731051782710899867431150541189647916512765137757827512121549727178
t = 2 ** 8
temp = ord('}') + t ** 101 * bytes_to_long(b'NSSCTF{')
for i in range(1, 101):
temp += 78 * t ** i
temp *= 2
for i in range(1, 101):
temp += 37 * t ** i
M = []
for i in range(102):
v = [0] * 103
v[102 - i] = 1
M.append(v)
v = [-2 * p, -2 * c, temp] + [37 * t ** i for i in range(1, 101)]
W = 2 ** 256
M.append([x * W for x in v])
M = Matrix(ZZ, M)
L = M.transpose().BKZ(block_size=10)
for row in L:
if row[-1] == 0 and abs(row[-2]) == 1 and abs(row[-3]) == 1:
if row[-2] == -1:
row = -row
flag = ""
for i in range(100):
if row[i] == 1:
flag += 's'
else:
flag += 'N'
print('NSSCTF{' + flag + '}')
- 这里又有了新的发现,我们在中心化之后,如果我们不在最后一行中添加权重因子,由于在 103 103 103维的格中关系十分复杂,很有可能会有一些满足条件的,比 v ⃗ \vec{v} v 更短的向量,假设有一个 v b a d ⃗ \vec{v_{bad}} vbad ,它的前 102 102 102个元素都是 0 0 0,但最后一位算出来的等式结果 E = 2 E=2 E=2,那么这个 v b a d ⃗ \vec{v_{bad}} vbad 的长度可能是 ∣ ∣ v b a d ⃗ ∣ ∣ = 0 2 + 0 2 + ⋯ + 0 2 + 2 2 = 2 ||\vec{v_{bad}}||=\sqrt{0^2+0^2+\cdots + 0 ^2+2^2}=2 ∣∣vbad ∣∣=02+02+⋯+02+22 =2,而 ∣ ∣ v ⃗ ∣ ∣ ≈ 10 ||\vec{v}||≈10 ∣∣v ∣∣≈10,此时在算法看来 v b a d ⃗ \vec{v_{bad}} vbad 是比 v ⃗ \vec{v} v 更优的解,所以我们添加权重因此 W W W,这样计算的向量长度 ∣ ∣ v ⃗ ∣ ∣ = x 1 2 + x 2 2 + ⋯ + x 102 2 + ( W ⋅ E ) 2 ||\vec{v}||=\sqrt{x_1^2+x_2^2+\cdots+x_{102}^2+(W\cdot E)^2} ∣∣v ∣∣=x12+x22+⋯+x1022+(W⋅E)2 ,此时对于我们的目标向量而言 E = 0 E=0 E=0没有任何变动,但是对于上述的垃圾向量而言,算法就不会将其认为是更短的向量,更加有利于我们找到目标向量.
- 最终发现在中心化之后我们可以找到更多的满足我的筛选条件的向量,但是也为我们增加了筛选的步骤:
python
"""
LLL算法的结果:
NSSCTF{NNNNNNNNNNNNNNNNNsNNsNsNNNNNNNNNNNNNNNsNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNsNNNNNNsNNNNNNNNNNNN}
NSSCTF{NNNNNNNNNNNNNNNNsNsNsNNNNNNNsNNNNNNNNNNNsNNNNNNNNNNNNNNNsNNNNNNNNsNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN}
"""
"""
BKZ算法结果:
NSSCTF{NNNssNsNNNNsNNNsNNNNNssNNNssNNNsNsNNsNsNNssNNNNNNsNNNssNsNNNNNssNssssNsNNsNsssNNNNssNNNssNsNNssNsNss}
NSSCTF{NNNNNNNNsNNsNNNNNNNsNNNNNNNNNNNNNNNNNNNNNNNNNNsNNNNNNNNsNsNNNNNNssNNNNNsNNNNNNNNNNNNsNNNNNsNNNNNNssN}
NSSCTF{NNNNNNNNNNsNNNNNNNNNNNNNNNsNNNNNNNNNNNNNsNNNsNNNNNNNsNNNNNNNNNNNNNNNNNsNNNNNNNNNNNNNNNNNNNNNNNNNNNsN}
NSSCTF{NNNNNNNNNNNNNNNNNNNNNNNNNNNNNsNNNNNNNNNNNNsNsNNNNNNNNNssNNNNNsNNNNsNNsNNNNNNNNsNsNNNNNNNNNNNNNNNNNsN}
NSSCTF{NNNNNNNNNNNNsNNNNssNNNsNsNNNNNsNNNsNNNNNNNsNNNNNNsNNNNNNNNNNNNNNNNNNNNsNNNNNNNNsNNNNNsNNNsNNNNNNNNNN}
"""
- 其中
LLL算法虽然有筛选条件下的向量,但是并没有正确的向量,而BKZ算法下的第一个目标向量则规约出了正确的目标向量。
easy_mod_final
task.py
python
from Crypto.Util.number import *
from random import *
table = "GAME"
p = getPrime(440)
flag = b"NSSCTF{" + "".join([choice(table) for i in range(100)]).encode() + b"}"
c = bytes_to_long(flag) % p
print("p =",p)
print("c =",c)
print(flag)
'''
p = 2271129678202363707972156644097566224560370806295266873816026779022614695317611229903770390498322537051358521932851893609555063610221
c = 244176818026839545554951436126300508547217557099550914232243928051857553603712968234687200629719468115535825237511413058786560692170
'''
analysis
- 这道题目未知字符的长度依旧是 100 100 100,与
easy_mod3的区别就是 p p p的大小变大了,字符集变成了 m i ∈ { 65 , 69 , 71 , 77 } m_i\in\{65,69,71,77\} mi∈{65,69,71,77},先尝试一下中心化的思路: m i = 71 + m i ′ [ m i ′ ∈ { − 6 , − 2 , 0 , 6 } ] m_i=71+m_i'[m_i'\in\{-6,-2,0,6\}] mi=71+mi′[mi′∈{−6,−2,0,6}].在这个基础上,我们按照前面的思路计算一下目标向量的长度以及上界:
∣ ∣ v ⃗ ∣ ∣ ≤ 1 2 + 1 2 + 100 ⋅ 6 2 = 3602 ≈ 60.01 < 103 ⋅ ( 2 439 ) 1 103 ≈ 195 < b o u n d = 103 ⋅ p 1 103 ||\vec{v}||≤\sqrt{1^2+1^2+100\cdot 6^2}=\sqrt{3602}≈60.01<\sqrt{103}\cdot (2^{439})^{1\over103}≈195<bound=\sqrt{103}\cdot p^{1\over 103} ∣∣v ∣∣≤12+12+100⋅62 =3602 ≈60.01<103 ⋅(2439)1031≈195<bound=103 ⋅p1031 - 所以按照
easy_mod2的脚本带入尝试一下试试看,发现并不能很好地完成解题,但是这里我发现了一个比较有趣的点 m i ′ ∈ { − 6 , − 2 , 0 , 6 } m_i'\in\{-6,-2,0,6\} mi′∈{−6,−2,0,6},由于 m i ′ m_i' mi′一定是偶数,所以其实我们可以进一步转化为 m = 71 + 2 ⋅ m i ′ ′ [ m i ′ ′ ∈ { − 3 , − 1 , 0 , 3 } ] m=71+2\cdot m_i''[m_i''\in\{-3,-1,0,3\}] m=71+2⋅mi′′[mi′′∈{−3,−1,0,3}],这样的话 ∣ ∣ v ⃗ ∣ ∣ ||\vec{v}|| ∣∣v ∣∣的大小会更小,而 b o u n d bound bound并没有变化,在此基础上进行脚本修改便可以解题。
c ≡ m ( m o d p ) → m = k p + c → m − k p − c = 0 c\equiv m\pmod{p}\rightarrow m=kp+c\rightarrow m-kp-c=0 c≡m(modp)→m=kp+c→m−kp−c=0
t = 2 8 ; t e m p = t 0 ⋅ o r d ( ′ } ′ ) + t 1 ⋅ 71 + ⋯ + t 100 ⋅ 71 + t 101 ⋅ b y t e s _ t o _ l o n g ( b ′ N S S C T F { ′ ) t=2^8;temp=t^0\cdot ord('\}')+t^1\cdot 71+\cdots+t^{100}\cdot 71+t^{101}\cdot bytes\to\long(b'NSSCTF\{') t=28;temp=t0⋅ord(′}′)+t1⋅71+⋯+t100⋅71+t101⋅bytes_to_long(b′NSSCTF{′)
m = t e m p + ∑ i = 1 100 ( 2 ⋅ m i ′ ′ ) m=temp+\sum{i=1}^{100}(2\cdot m_i'') m=temp+i=1∑100(2⋅mi′′)
L = [ 0 0 0 ⋯ 0 0 1 0 0 0 ⋯ 0 1 0 0 0 0 ⋯ 1 0 0 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ ⋮ 0 0 1 ⋯ 0 0 0 0 1 0 ⋯ 0 0 0 − p − c t e m p ⋯ 2 ⋅ t 98 2 ⋅ t 99 2 ⋅ t 100 ] ; b ⃗ = [ k 1 1 ⋮ m 98 ′ ′ m 99 ′ ′ m 100 ′ ′ ] → L ⋅ b ⃗ = [ m 100 ′ ′ m 99 ′ ′ m 98 ′ ′ ⋮ 1 1 0 ] = v ⃗ L=\left[ \begin{matrix} 0 & 0 & 0 & \cdots & 0 & 0 & 1\\ 0 & 0 & 0 & \cdots & 0 & 1 & 0\\ 0 & 0 & 0 & \cdots & 1 & 0 & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots\\ 0 & 0 & 1 & \cdots & 0 & 0 & 0\\ 0 & 1 & 0 & \cdots & 0 & 0 & 0\\ -p & -c & temp & \cdots & 2\cdot t^{98} & 2\cdot t^{99} & 2\cdot t^{100} \end{matrix} \right];\vec{b}=\left[ \begin{matrix} k\\ 1\\ 1\\ \vdots\\ m{98}''\\ m_{99}''\\ m_{100}'' \end{matrix} \right]\rightarrow L\cdot \vec{b}=\left[ \begin{matrix} m_{100}''\\ m_{99}''\\ m_{98}''\\ \vdots\\ 1\\ 1\\ 0 \end{matrix} \right]=\vec{v} L= 000⋮00−p000⋮01−c000⋮10temp⋯⋯⋯⋱⋯⋯⋯001⋮002⋅t98010⋮002⋅t99100⋮002⋅t100 ;b = k11⋮m98′′m99′′m100′′ →L⋅b = m100′′m99′′m98′′⋮110 =v
exp.sage
python
from Crypto.Util.number import long_to_bytes, bytes_to_long
p = 2271129678202363707972156644097566224560370806295266873816026779022614695317611229903770390498322537051358521932851893609555063610221
c = 244176818026839545554951436126300508547217557099550914232243928051857553603712968234687200629719468115535825237511413058786560692170
t = 2 ** 8
temp = ord('}') + (t ** 101) * bytes_to_long(b'NSSCTF{')
for i in range(1, 101):
temp += 71 * (t ** i)
M = []
for i in range(102):
v = vector(ZZ, 103)
v = list(v)
v[102 - i] = 1
M.append(v)
M.append([-p, -c, temp] + [2 * t ** i for i in range(1, 101)])
M = Matrix(ZZ, M)
L = M.transpose().BKZ(block_size=20)
print("BKZ done.")
# print(L)
for row in L:
if row[-1] == 0 and abs(row[-2]) == 1 and abs(row[-3]) == 1:
if row[-2] == -1:
row = -row
print("NSSCTF{", end = "")
for i in range(100):
if row[i] == -3:
print("A", end = "")
elif row[i] == -1:
print("E", end = "")
elif row[i] == 0:
print("G", end = "")
else:
print("M", end = "")
print("}")
# NSSCTF{GEEGEEEMEEMMAAMGGGGEEGMMAMEGGEEEGAGGMEMEMMAMGGGEAAGMGEAAGEMMEEEMGMAAMMGEAAEEEEEGGEMMMMAEGAAAMEMEAEGE}
- 后续在阅读 N S S C T F NSSCTF NSSCTF上的 W r i t e U p WriteUp WriteUp的时候看到糖醋小鸡块师傅的相关解析[tangcuxiaojkuai]easy_mod_final - NSSCTF,找到一个线性变换,使得GAME四个字母均在这条直线上,并且纵坐标均很小,从而可以规约 。可能更加通用一些,不过这几道题目写下来我认为中心化与 0 / 1 0/1 0/1背包转化的思想是足够的,也就是找到一个线性表达式 m = a ⋅ m ′ + b m=a\cdot m'+b m=a⋅m′+b,我们要求 m ′ m' m′取值范围中的 ∣ m a x ∣ |max| ∣max∣最小即可,而中心化和我上述所说的中心化(提取出 b = 71 b=71 b=71)以及提取其中的公因数( a = 2 a=2 a=2)就是在找这么一个直线方程。