上周六(3.5)参加了NeSE乙升甲的升级赛,很幸运解出题通过了升级赛,正式成为NeSE主队队员。接触CTF一年多,从萌新到会一点点密码学,这算是参加CTF竞赛的又一个重要的节点。之后我参加国际赛的次数可能也就多了起来,博客看情况更,复盘解题过程有时候虽然收获很多,但太费时间了。虽然毕设还是云里雾里,但今天还是在忙着摸鱼之际(bushi)抽空细写了这道和线性代数相关的密码学题解。
源码
1 | #!/usr/bin/env sage |
分析
最初分析会发现这是一道容错学习的问题(Learning With Errors),进而会发现这是定义在多项式环上的Module-LWE问题,去找相关论文和攻击,发现这方面的研究和现实里具体的攻击很少,之后干脆源码分析:
其中password每一轮都是固定的。
常量定义如下
1 | P, n, t = 41, 64, 100 |
最主要的加密部分,已知r,m,b并且有如下关系:
注意到向量每个维度的error=[-1,-2,0,1,2]的概率分布是[1/8,1/8,1/2,1/8,1/8],我们得到的加密结果向量b里面有一百次不同随机error的加密,故统计数组b内对应位置的数字的出现次数,出现次数最多的就是原来不带误差的值(这个占比高达50%)。因此可以通过统计特征恢复出。虽然这一步是最简单的,但最终卡在这个地方很久,因为不注意到概率分布的话,单纯用LWE的格去归约是算不出来的:模数p和误差error的上限相差有点小。
恢复之后我们得到了一个多项式混合矩阵的乘法方程。当然我们可以先对b在Q上求逆得到,再转换一下系数,就变成了一个矩阵表示的线性方程。只是我们线性方程的个数只有32个,而未知数有64个(password不变,其他32位每次会变)。虽然模(非本原多项式)多项式环上的逆不一定存在,但这应该也是一种可行的思路。接下来介绍另一种思路:针对模多项式上的等价矩阵。
考虑题中上的运算,如果我们先不考虑模多项式,只在上运算,我们发现。也就是说如果我们在Q上计算,也就等价于下面矩阵相乘
注意到只有32维,也等价于是定义在Q(x)上的,从而利用在Q(x)上的乘法的矩阵形式转换到GF(p)上的矩阵运算,也就是:
到这里就又回到了线性代数里线性方程的求解,已知,和方程,其中M是32×64的矩阵,s是64维的向量:前面32维固定为password,后面32维为随机向量。由于前面32位password是固定的,我们将M拆开看:,其中A,B都是32×32的矩阵,原方程就拆分为下面问题:
其中我们每进行一次sample请求,可以得到一组,最多可以得到2048组:
如果B满秩,我们得不到任何有用信息。
如果B非满秩,也就是说存在非零向量,使得(B的左核空间,维数是32-rank(B)):
也就是如果B不满秩(非奇异),我们能得完全到password的个线性组合,一个线性组合就是一组方程!!!
不断收集这样的,直到所有向量构成的矩阵的秩达到32,也就可以通过解方程完全得到password。由此,整个问题得到解决。
解题脚本
1 | # sage 9.2 |