京麒杯 2025- Onelinercrypto 时间侧信道问题
题目
题目要求 flag 满足正则表达式 “flag{[!-z]{11}}”,也就是 flag 的花括号中包含 11 个 ASCII 字符:
1 | flag{xxxxxxxxxxx} |
题目代码使用 Sage 语法:将 flag 转换为整数后,与输入值进行按位异或,并重复进行 $7^7$ 次素性判断。由于判断结果组成的列表非空,断言条件可以通过;程序不会直接输出每次素性判断的结果。
1 | assert ( |
思路
设 flag 转换成的整数为
$$
m=\operatorname{int}(\text{flag.hex()},16).
$$
程序实际判断的是 $m\oplus x$ 是否为素数,其中 $x$ 是输入值。这里使用的是 Sage 语法:^ 表示幂运算,^^ 表示按位异或。
时间侧信道: 题目不会直接输出素性判断结果,但可以利用素性判断所需的时间差异,逐步求出 $m$ 模各个小素数的值,再使用中国剩余定理(CRT)恢复 flag。
求 $m\bmod 3$
记
$$
y=m\oplus x.
$$
由于 $m<2^{256}$ 且 $m$ 为奇数,构造 $x$ 为 $2^{256}$ 的倍数时,可以将 $m\oplus x$ 看作 $m+x$。分别构造三组输入,使 $y\bmod 3$ 遍历 ${0,1,2}$。当 $y\bmod 3=0$ 时,素性判断会更快返回。
可以构造输入
$$
x_{k,j}=(k+3j)2^{256},
\qquad
k\in{1,2,3},
\quad
j\in{1,2,3,\ldots}.
$$
求 $m\bmod 5$
为了观察 $m\bmod 5$,需要避免 $y$ 被 2 和 3 整除,否则这些较小素数会影响时间侧信道。
不能直接使用
$$
x=(k+5j)2^{256}
\qquad\text{或}\qquad
x=(k+15j)2^{256},
\quad
k\in{1,2,3,4,5}.
$$
这是因为还需要同时控制 $y\bmod 3$。例如,若已知 $m\bmod 3$,可以令 $k=3t+k’$,再让 $t$ 遍历 ${0,1,2,3,4}$,从而在保证不被 3 整除的同时遍历 $m\bmod 5$ 的所有可能值。
一般情形与 CRT
依次处理素数 $p_i$。设已经求出的素数乘积为
$$
P=\prod_{r<i}p_r,
\qquad
m\equiv f_i\pmod P.
$$
取 $a_i$ 使得
$$
a_i\cdot 2^{256}+f_i\equiv 1\pmod P.
$$
然后构造输入
$$
x_{i,k,j}=(a_i+kP+jPp_i)2^{256},
\qquad
k\in{0,1,\ldots,p_i-1}.
$$
此时
$$
m+x_{i,k,j}
\equiv (a_i+kP)2^{256}+f_i
\equiv a_i\cdot 2^{256}+f_i
\equiv 1\pmod P,
$$
同时,随着 $k$ 遍历 $0,1,\ldots,p_i-1$,$m+x_{i,k,j}$ 模 $p_i$ 的值也会遍历所有可能结果。通过时间最短的一组输入即可判断 $m\bmod p_i$,再使用 CRT 合并当前结果。
依次求出足够多的模数后,即可恢复整数 $m$,最后将其转换回字节串得到 flag。实际实现中,每求出一个新的素数模数,就进行一次 CRT。
解答
下面的脚本使用 Sage 运行,server.sage 为题目服务端脚本:
1 | from Crypto.Util.number import * |