背包问题
有n个物品,重量分别为a1,a2,…an,每个物品仅能被装一次,选择哪些物品,可以理解为对应位为1,别的位为0,得到背包的重量W。因此,明文为0/1串,密文为背包重量。普通背包问题要还原明文,需要枚举所有的n个物品的组合,复杂度为2^n。
超递增
物品重量第i个值大于前面所有数的和时,可解密。解密时,逆序遍历所有物品,当重量W大于ai,则表示第i位为1,否则为0。
Merkle–Hellman加密算法
私钥
背包物品重量an
公钥
模数m,满足:m>所有an的和
乘数w,满足:gcd(w,m) = 1
公钥bi=w * ai mod m,bn和m组成公钥
加密
明文0/1串vi,依次乘公钥bi,相加模m \(c=\sum_{i=1}^nb_i*v_i\bmod m\)
解密
密文乘以乘数w的逆元w^-1可得明文 \(w^{-1}*c=\sum_{i=1}^nw^{-1}*b_i*v_i=\sum_{i=1}^nw^{-1}*w*a_i*v_i=\sum_{i=1}^na_i*v_i\bmod m\) 因为m>所有an的和,因此所有的ai*vi之和均小于m,通过私钥an,即可求得明文vi
LLL攻击,sample:archaic,ASIS-2014
构造矩阵乘法:KA=Y \(\left[x_1 x_2\dots 1\right]\left[ \begin{matrix} 1 & 0 & \dots & 0 & a_1 \\ 0 & 1 & \ddots & \vdots & \vdots \\ \vdots & \ddots & \ddots & 0 & \vdots \\ 0 & 0 & \dots & 1 & a_n \\ 0 & 0 & \dots & 0 & -c \end{matrix} \right]=\left[x_1 x_2\dots 0\right]\) A作为一个格的基向量组合,通过线性变换(左乘K),得到行向量Y,那么行向量Y,是在由基向量A组成的格上。成功构造出一个让有x_i的向量在已知的格上,那么这个向量还必须满足是该格的最短向量,也即是SVP问题的描述。
1 |
|
已知位数的乘数w小,已知等比数列的私钥加密明文,sample:knapsack,BJDctf-2020
乘数w小,则开始的几个bi = ai*w小于m,模m即为自身,因此,取前几个bi求最大公约数,当最大公约数位数匹配,则求得w。遍历公钥,当找到第一个模w不为0的值,表示其大于m,因为
prikey_i * A < B, prikey_i+1 = 2 * prikey_i * A < 2 * B
因此模m,即为减m,利用等比数列,2 * prikey_i * A - pubkey
即为m
公钥乘w的逆元invert(w, m)求得私钥