密码学学习笔记 之 knapsack
首发于安全客
ACM中的背包问题是一种组合优化的NP完全问题,而在密码学中,也有对背包问题的应用。
Subset-sum problems and knapsack cryptosystems
密码学中的利用knapsack problem的加密。大意就是,你公开一个序列,然后你把你的消息转为二进制,如果你消息的这一位是1,就从你序列中取出对应位置的值,最后密文就是你所有取出的值的和。
但是这样就产生一个问题,加密是加过去了。那该怎么解密呢?
蛮力攻击的时间复杂度是$O(2^n)$,就算中途相遇也只能降低到$O(2^{\frac{n}{2}})$。太难了。。。
那Alice怎么解决这个问题呢?公钥密码系统如何体现呢?
这就看Alice对序列的选择了。她用的是超递增序列。什么是超递增序列呢?就是后一项≥前一项的两倍,也就意味着,后一项大于前面的所有项之和。
有超递增序列后,给你一个密文,你只需要一项一项对比过来,你就能知道加密者选取的元素是哪几个了。
这不难理解。我们将序列中的每一项放到二进制下就很明显。如果第一项的位长是2,那第二项的位长就至少是3,如果第二项位长是3,那么第三项的位长至少是4。如果你的密文最后是个2位长的,那加密者必定是没有用到第三项,必定是用到了第二项,至于有没有用到第一项,那就看密文减掉第二项之后还有没有剩下来了。【当然,这在每一项只能用一次的大前提下】
preparation
Alice准备加密了,首先她先整了一个超递增序列,$r = (r_1,r_2,,,r_n)$,然后她整了两个大数A和B,其中要求$B>2r_n$ 也就是B大于这个超递增序列之和啦。然后要需要$gcd(A,B)=1$,因为之后要求一个A在B下的逆。
encryption
Alice要加密了,她先用她的A和她的超递增序列生成一个新的序列M,其中$M_i \equiv Ar_i \pmod B$
这个新的序列就是Alice的公钥了,她把这个序列甩给Bob,然后Bob按照之前描述的方式,用这个序列和他的明文生成密文$S = x*M = \sum \limits_{i=1}^{n}x_iM_i$,然后把这传给Alice
decryption
Alice要解密了,她拿到了这个密文S,然后计算
$S’ \equiv A^{-1}S \equiv A^{-1}\sum_{i=1}^{n}x_iM_i\equiv A^{-1}\sum_{i=1}^{n}x_iAr_i\equiv \sum_{i=1}^{n}x_ir_i \pmod B$
所以这个$S’$就是密文在超递增序列下的值了,之后再像之前那样判断一下这个$S’$和序列里面每一项的关系就能解出明文了。【记得从序列大的一端开始判断,如果满足关系别忘了减掉那一项再判断下一项】
伪代码走一波
1 | for i in reverse(r): |
table
来个总体流程
attention
同RSA一样,这里对参数的选择也要慎重,不然会出现许多出人意料的问题。
具体实例可参考BJD3rd-knapsack
这里由于对参数A的不当选择,导致序列中较小的项乘以A后并没有被B模掉,也就导致了参数A的泄露。
并且由于这里的超递增序列的生成规则过于简单,只是不断地整除2,所以攻击者能够利用加密后的序列轻易的计算出B来。
further more
之前提到Alice最开始整的一个无序的序列,由于这玩意儿没有陷门(trapdoor),因此这无法成为一个密码系统。但自从有关LLL的paper发表后,基于背包的密码系统出现了一个大weakness,
这里简短的介绍下Eve怎么去解决这个无序序列的背包问题。不管是序列本身无序,还是超递增序列加密后显得无序的序列。
Eve先构造了一个矩阵$M =
\begin{bmatrix}
2&0&0&\dots&0&0&m_1 \newline
0&2&0&\dots&0&0&m_2 \newline
\vdots&\vdots&\vdots&\ddots&\vdots&\vdots&\vdots \newline
0&0&0&\dots&2&0&m_{n-1}\newline
0&0&0&\dots&0&2&m_{n}\newline
1&1&1&\dots&1&1&S\newline
\end{bmatrix}$
其中这个$m_1,m_2,m_3…$就是那个无序序列,S就是密文
然后Eve从这个矩阵中,将每一条行向量划分出来,分别为$V_1,V_2,…,V_n,V_{n+1}$
我们现在假设向量$x = (x_1,x_2,x_3,…,x_n)$ 是明文,($x_i = 0$ or $1$)
那么这个格中就会有这么一条向量
$t = \sum_ \limits {i=1}^{n}x_iV_i-V_{n+1}=(2x_1-1,2x_2-1,…,2x_n-1,0)$
这个t,因为$2x_i-1=\pm 1$,所以t的模长是$\sqrt{n}$,
根据Minkowskl’s First Theorem,
即对于任意n维满秩格基,都有 $SVP(L)≤\sqrt n(det(L))^{\frac 1 n}$
显然t是格L中的短向量。
所以,如果Eve知道如何找到lattice中的短向量,那么他就可以完成破解了。
关于找到lattice中短向量的算法我们称之为reduction algorithm,最著名的就是LLL algorithm了,然后它还有变体LLL-BKZ。
variant
再刚过去不久的2020RCTF中出现了一道有关knapsack problem 的变体,这里用的不是子集之和,而是子集之积
1 | from Cryptodome.Util.number import bytes_to_long, getPrime |
蛮力攻击的时间复杂度是2的90次方,即使是中途相遇攻击的时间复杂度也仍然有2的45次方,于此同时还得考虑2的45次方的空间复杂度。
赛后看了国外大佬hellman的脚本才明白了本题的解法。
这一道题的切入点就在于模数p,通过不断地nc,直到获得的模数p具有p-1 smooth的性质(为了方便后面解离散对数),
这个时候再找到一个p的原根,然后对所有的数据利用pohlig算法解一个离散对数,就是开一个log,这样这个子集积的问题就能重新变回子集和的问题了。
1 | from sage.all import * |
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可联系QQ 643713081,也可以邮件至 643713081@qq.com
文章标题:密码学学习笔记 之 knapsack
文章字数:2.1k
本文作者:Van1sh
发布时间:2020-06-08, 10:30:43
最后更新:2020-08-21, 14:48:24
原始链接:http://jayxv.github.io/2020/06/08/密码学学习笔记之knapsack/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。