Description
DSA can be hacked if you have access to the size of the random key k.
Flag
flag{25903ADB-15B6-44D7-A027-CAE500675EA5}
File
已上传至Mega网盘: https://mega.nz/file/efAzRabC#ZxXtUbcHwAA7jpcU0H6V7rAMRfiS_rboH9H9ZN9S2-U
Writeup
在上次i春秋的那个比赛里,有一道LCG,在找资料的过程中发现了一个神奇的东西:
https://grocid.net/2019/11/15/tpm-fail-tldr/ 。
然后跟着去搜了下TPM Fail
,找了 https://tpm.fail/
,感觉很有意思就把那道LCG
改了下拿过来出题了。
(2020.03.14更新) 推荐阅读: https://eprint.iacr.org/2015/839.pdf
TLDR:有人利用Timing-information Leakage和Lattice Attacks攻击了ECDSA
研究人员在TPM(Trusted Platform Module)中发现了漏洞,能够让攻击者利用Timing-information leakage和Lattice attacks获取到存储于TPM中用于ECDSA数字签名算法的私钥。
随后研究人员申请了两个CVE编号:CVE-2019-11090 、CVE-2019-16863 。
关于攻击的细节部分,可以参考研究人员发表的paper: https://tpm.fail/tpmfail.pdf
在这里简单(很不严谨)地复述一下。
1996年,Boneh和Venkatesan在Hardness of Computing the Most Significant Bits of Secret Keys in Diffie-Hellman and Related Schemes
中第一次提出了hidden number problem(HNP),并在Rounding in lattices and its cryptographic applications
中提供了一个lattice rounding technique
来解决这个难题。随后,许多研究者利用这个思路分析了很多数字签名算法,发现了很多问题。
这一次,研究人员研究的是ECDSA数字签名,其密钥生成和签名的流程如下:
如果我们知道了$k$的LZB(leading zero bits),那么我们就可以利用HNP里的思路来攻击ECDSA签名算法。
研究人员就是利用在签名时会计算
$$ r = (kQ)_x $$
其中$k$的大小会使得这一步耗时不同来攻击的:
$k$越大,这一步所需的时间就越长;相反,$k$越小,这一步所需的时间就越短。
因此,可以根据签名的耗时长短,来判断$k$的大小。
签名时间越短,就说明$k$越小,也就是说,$k$的有较多位LZB。
这就是Timing-imformation Leakage。
获取到足够多的由比较小的$k$(从中可以知道$k$的有较多位LZB)生成的签名后,我们就可以利用Lattice Attacks来求解出$k$和私钥$d$。
我们先获取$t$组签名$(r_i, s_i)$。
观察签名中的这一步: $$ s_i \equiv k_i^{-1} (\mathcal{H}(m_i) + dr_i) \pmod {n} $$ 我们将其变形一下: $$ k_i - s_i^{-1}r_id - s_i^{-1}\mathcal{H}(m_i) \equiv 0 \pmod{n} $$ 其中仅有$k_i$和私钥$d$未知。
令 $$ A_i \equiv -s_i^{-1} r_i \pmod{n} ,\quad B_i \equiv -s_i^{-1}H(m_i) \pmod{n} $$ 进而转化为: $$ k_i + A_id + B_i \equiv 0 \pmod{n} $$ 可以针对这一个式子来构建lattice。
令$K$是$k_i$的一个上限(upper bound),我们现在考虑由下面这个矩阵所形成的lattice: $$ M = \begin{bmatrix} n & & & & & & \newline & n & & & & & \newline & &\ddots& & & & \newline & & & n & & & \newline A_1&A_2&\dots & A_t&K/n& & \newline B_1&B_2&\dots & B_t& & K & \newline \end{bmatrix} $$ 不难发现向量$v_k = (k_1, k_2, \cdots, k_t, Kx/n, K)$就在这个lattice中,且$v_k$是一个长度相当小的向量。
这个$v_k$就是倒数第二行乘上$d$再加上最后一行,最后再加上$n$的某个倍数
因而,我们可以使用LLL算法来找到这个$v_k$,进而获取到密钥$x$。
LLL能够在多项式时间内找到一个长度$|v| \le 2^{(\dim{L}-1)/4}(\det{L})^{1/\dim{L}}$的向量
研究人员利用这个思路,先在本地上做了一些测试。
简单地摘录一些测试的结果:
$n$是一个256-bit的数,$k$是区间$[1,n-1]$中随机分布的一个数。
如果$k$的前4bit都是0,即$k < 2^{256-4} = 2^{252}$,那么这样的$k$出现的概率大概是$2^{252}/2^{256} = 1/2^4=1/16$,研究人员通过计算发现大概选取78组由这样的$k$形成的签名就可以100%利用LLL算法找到$v_k$,因此平均需要获取$16 * 78 = 1248$组签名。
如果$k$的前8bit都是0时,概率大概为$1/256$,$t=35$,需要8784组签名。
随后研究人员在真实世界中进行了分析,研究了一个开源VPN软件服务器,并成功地获取到了相关的密钥。
考虑到CTF比赛的原因,很难通过Timing-imformation leakage来判断出$k$的大小,因此本题中就直接给出了相应的$k$的位数。
此外由于ECDSA实现起来过于麻烦(懒),所以本题改用DSA来实现,但原理实际上都是一样的。
本题中$q$为128位,$k$是一个在区间$[1, q-1]$中的一个数。
可以不断地与服务器交互,得到若干组签名。设定一个阈值,比如说121,扔去位数比121大的$k$,保留位数小于等于121的k。直到获取到$t$组这样的签名。
然后就可以开始Lattice Attacks:
通过 $$ \begin{aligned} r &\equiv g^k \pmod{q} \newline s &\equiv k^{-1}(\mathcal{H}(m) + xr) \pmod{q} \end{aligned} $$
可以推得
$$ \begin{aligned} k_i &\equiv s_i^{-1}r_i \cdot x + s_i^{-1}\mathcal{H}(m_i) \pmod{q} \newline k_i &\equiv A_i x + B_i \pmod{q} \newline k_i &= A_i x + B_i + l_i q \end{aligned} $$
其中,$A_i = s_i^{-1}r , \quad B_i = s_i^{-1}\mathcal{H}(m)$
构建lattice: $$ M = \begin{bmatrix} q & & & & & & \newline & q & & & & & \newline & &\ddots& & & & \newline & & & q & & & \newline A_1&A_2&\dots & A_t&K/q& & \newline B_1&B_2&\dots & B_t& & K & \newline \end{bmatrix} $$
(其中$K$是$k$的上界,例如$k$的位数小于等于121时,那么$K = 2^{122}$)
不难发现,存在一个$M$的整系数线性组合$v$,可以得到我们想要的$v_k$。
$$ vM = \begin{bmatrix} l_1 & l_2 & \cdots & l_t & x & 1 \end{bmatrix} \begin{bmatrix} q & & & & & & \newline & q & & & & & \newline & &\ddots& & & & \newline & & & q & & & \newline A_1&A_2&\dots & A_t&K/q& & \newline B_1&B_2&\dots & B_t& & K & \newline \end{bmatrix} = \begin{bmatrix} k_1 & k_2 & \cdots & k_t & Kx/q & K \end{bmatrix} = v_k $$ 因此$v_k$即为$M$上的一个格点,且长度很短,可以用LLL算法求出。
我们可以大致估量一下$t$和阈值的取值范围:
Lattice的determinant为: $$ \det{L} = q^t K/q K = q^{t-1} K^2 $$ LLL算法可以找到这样一个向量: $$ |v| < 2^{(\dim{L}-1)/4} (det{L})^{1/dim{L}} = 2^{(t+1)/4} q^{\frac{t-1}{t+2}} K^{\frac{2}{t+2}} $$ 而$v_k$的长度为: $$ K < |v_k| = (k_1^2 + k_2^2 + \cdots + k_t^2 + (Kx/q)^2 + K^2)^{1/2} < ((t+2)K^2)^{1/2} = \sqrt{t+2}K $$ 因此只需要 $$ |v_k| < |v| \Rightarrow \sqrt{t+2}K < 2^{(t+1)/4} q^{\frac{t-1}{t+2}} K^{\frac{2}{t+2}} $$ 后面的不太好算。。
但是可以本地自己测试一下:
|
|
在$t \ge 34$的时候,成功率就是100%。
解释下倒数第四行为什么取LLL后的第二行。因为(不难验证)有另一个短向量$v = (0, 0, \cdots, K, 0)$也在lattice上,且这个短向量比$(k_1, k_2, \cdots, k_t, Kx/n, K)$还要短。此外,多次测试发现,$v_k$总会出现在LLL后的第二行。
一些测试的数据:
LZB | K | 成功率 | 成功率 | 成功率 | 需要的交互次数 |
---|---|---|---|---|---|
5bit | 2^123 | 55% (t=40) | 93% (t=50) | 100% (t=65) | 2080 |
6bit | 2^122 | 76% (t=29) | 99% (t=32) | 100% (t=34) | 2176 |
7bit | 2^121 | 17% (t=22) | 68% (t=23) | 99.5% (t=25) | 3200 |
这里,我们选择6bit的LZB和$t=40$组签名。
exp.py如下:
|
|
其中用来求解私钥$x$的solver.sage如下:
|
|
考虑到网络延迟,可能需要几分钟的交互时间。
不过选手可以选择在本地上搭建环境,先本地跑好exp,再选择远程交互。
最终可以得到flag:flag{25903ADB-15B6-44D7-A027-CAE500675EA5}
Summary
主办方应该把我的题目名字搞错了,应该是HNP
,而非NHP
。。。
这个攻击应该算是利用LLL算法进行cryptanalysis的一个典型案例了。之前也有一些题目涉及到这一知识点:
最后一共有17支队伍做出了这一题,师傅们都tql!!!
2020.07.12 Update:
-
2020年的一篇paper:LadderLeak: Breaking ECDSA With Less Than One Bit Of Nonce Leakage 以及一篇blog post