2025强网杯
记录2025强网杯——Crypto题解(除0解题外)
最后排名 40,有过高光,但最后还是太遗憾了,从Blurred这题重新上线后一直到比赛结束没能肝出来,赛后尝试了一下赛中没尝试过的思路一下就出了。
check-little
task.py
1 | from Crypto.Util.number import * |
学弟用AI尝试各种方法,发现p = gcd(N,c),解密即可
exp.py
1 | from Crypto.Util.number import * |
ezran
task.py
1 | from Crypto.Util.number import * |
x=(pow(r1, 2*i, 257) & 0xff) ^ r2由于进行了 &ff,所以这个值小于256,那么异或就不影响r2的高8bit,3108 * 8 > 19968,足够恢复state,这里没用造矩阵的形式做,用的是gf2bv,存在多解的可能,所以用的是solve_all(),恢复state之后找一下shuffle2025次的映射即可求出
exp.py
1 | from sage.all import * |

sk
task.py
1 | from random import randint |
先生成两个 $2\times 3$的矩阵 P,Q,加密的数学逻辑为
$$
PP = P_{0,0}\cdot (u_0 \mod p) + P_{0,1}\cdot (u_0m\mod p) + P_{0,2}\cdot (u_0m^2\mod p) + P_{1,0}\cdot (u_1 \mod p) + P_{1,1}\cdot (u_1m\mod p) + P_{1,2}\cdot (u_1m^2 \mod p)
$$
$$
QQ = Q_{0,0}\cdot (u_0\mod p) + Q_{0,1}\cdot (u_0m\mod p) + Q_{0,2}\cdot (u_0m^2\mod p) + Q_{1,0}\cdot (u_1\mod p) + Q_{1,1}\cdot (u_1m \mod p) + Q_{1,2}\cdot (u_1m^2 \mod p)
$$
记$r_{0,0} = u_0 \mod p$,$r_{0,1} = u_0m \mod p$,$r_{0,2} = u_0m^2 \mod p$
$r_{1,0} = u_1 \mod p$,$r_{1,1} = u_1m \mod p$,$r_{1,2} = u_1m^2 \mod p$
于是有
$$
PP = P_{0,0}r_{0,0} + P_{0,1}r_{0,1} + P_{0,2}r_{0,2} + P_{1,0}r_{1,0} + P_{1,1}r_{1,1} + P_{1,2}r_{1,2}\mod p
$$
$$
QQ = Q_{0,0}r_{0,0} + Q_{0,1}r_{0,1} + Q_{0,2}r_{0,2} + Q_{1,0}r_{1,0} + Q_{1,1}r_{1,1} + Q_{1,2}r_{1,2} \mod p
$$
$r_{i,j}$都是小量,用cuso可以求出所有 $r_{i,j}$,求出来之后就能得到 m,然后用 p再生成私钥和公钥,自己走一遍加密流程,向服务器发送这些值。
解法1:cuso
exp.py
1 | from cuso import find_small_roots |

解法2:造格
根据上面的等式造这样的格
$$
\begin{bmatrix}
r_{0,0} & r_{0,1} & r_{0,2} & r_{1,0} & r_{1,1} & r_{1,2} & -1 & -1
\end{bmatrix}
\begin{bmatrix}
1 & 0 & 0 & 0 & 0 & 0 & P_{0,0} & Q_{0,0}\\
0 & 1 & 0 & 0 & 0 & 0 & P_{0,1} & Q_{0,1}\\
0 & 0 & 1 & 0 & 0 & 0 & P_{0,2} & Q_{0,2}\\
0 & 0 & 0 & 1 & 0 & 0 & P_{1,0} & Q_{1,0}\\
0 & 0 & 0& 0 & 1 & 0 & P_{1,1} & Q_{1,1}\\
0 & 0 & 0 & 0& 0 & 1 & P_{1,2} & Q_{1,2}\\
0 & 0 & 0& 0& 0& 0& PP & 0\\
0&0 & 0& 0 &0&0 &0 & QQ
\end{bmatrix} =
\begin{bmatrix}
r_{0,0} & r_{0,1} & r_{0,2} & r_{1,0} & r_{1,1} & r_{1,2} & 0 & 0
\end{bmatrix}
$$
1 | from Crypto.Util.number import * |
Blurred——复现
task.py
1 | from sage.all import * |
思路很清晰,区分出尽可能多的coin,然后打MT19937。
如果样本来自GenNTRU,那么有
$$
h_1(x) \equiv g_1(x)f^{-1}(x)
$$
$$
h_2(x) \equiv g_2(x)f^{-1}(x)
$$
当$x = -1$的时候,可以把环映射到整数域,也就是
$$
h_1(-1) \equiv g_1(-1)f^{-1}(-1) \mod q
$$
$$
h_2(-1) \equiv g_2(-1)f^{-1}(-1) \mod q
$$
这时候就可以当作格入门的题来做,即$fh \equiv g \mod p$,我们造这样的格
$$
\begin{bmatrix}
f & k_1 & k_2
\end{bmatrix}
\begin{bmatrix}
1 & h_1 & h_2\\
0 & q & 0\\
0 & 0 & q
\end{bmatrix}
= \begin{bmatrix}
f & g_1 & g_2
\end{bmatrix}
$$
这时候我本地测试发现,$f$会比较小,基本落在$[-20,20]$,另外一个随机的样本就没有这样的结果,所以我将区分的阈值设为20
以$n = 211$测试发现,错误率为$\frac{26}{20258}$,打远程似乎错误率高了不少,导致打MT19937没出
其实赛中的时候就想到用向量的长度做区分,但是一直以为自己的正确率足以,但事实证明正确率不够。赛后测了一下,来自GenNTRU的样本,规约出的向量长度不会很大,阈值选100就能完美区分coin
exp.py
1 | from sage.all import * |

好奇为什么给这么多交互机会,一开始以为20258次出现部分bit错误也能求解——也就是MT19937的20258个bit里面存在少部分随机位置的bit翻转可以求解,赛后实验发现,存在一个bit错误都无法求解,所以当时思路错了,应该想办法得到100%正确的coin,而不是允许部分差错。