NTRU密码体制笔记
NTRU 原理
NTRU 是一种基于环与格的公钥密码系统,特点是密钥短且容易产生,算法运算速度快,所需存储空间小。
格问题
基本问题介绍
考虑一个简单的加密方式,随机选取素数 \(p,g\),随机数 \(f\),满足 \(g<f<p\),我们计算 \[ h=gf^{-1}\pmod{p} \] 那么公钥为 \((h,p)\),私钥为 \((f,g)\)。
定义加密方式为 \[ c=r\cdot h+m\pmod{p} \] 其中,\(r\) 为随机数,满足 \(r<p\)。
定义解密方式为 \[ c\cdot f=r\cdot g+m\cdot f\pmod{p} \] 在这里要满足 \(rg+mf<p\),那么可以得知 \[ a=rg+mf=mf\pmod{g} \] 那么求解问题变为 \[ m=af^{-1}\pmod{g} \]
在这里简化了很多步骤,比如说保证 \(\gcd(f,g)=1\) 等条件,其中 \(rg+mf<p\) 是通过控制 \(h, p,f,g\) 的大小实现的。
当我们手里有密文 \(c\),公钥 \((h,p)\) 时,要想破解明文,需要得知密钥 \((f,g)\)。
攻击手段
首先考虑等式 \[ h=gf^{-1}\pmod{p} \] 对其进行变形,得到 \[ f\cdot h=g\pmod{p}=g+kp \] 改写为矩阵乘法,得到 \[ (f,-k)M=(f,g)\newline M=\begin{bmatrix} 1&h\newline 0&p \end{bmatrix} \] 可以证明向量 \((f,g)\) 在格 \(M\) 上,即 SVP 问题。
详细证明在另一篇文章中,暂不在这里讨论。
一个二维格使用 LLL 算法是容易求解的。
生成代码
1 | from Crypto.Util.number import getPrime, getRandomNBitInteger |
攻击代码
1 | from sage.all import * |
多项式环与格
多项式环
设 \(R(N)\) 表示最高次数不超过 \(N-1\) 的所有整系数多项式集合,即 \(a=a_0+a_1x+\cdots+a_{N-1}x^{N-1}\)
\(R\) 上的加法定义为:\(a+b=(a_0+b_0)+(a_1+b_1)x+\cdots+(a_{N-1}+b_{N-1})x^{N-1}\)
\(R\) 上的乘法定义为:\(a\times b=c_0+c_1x+\cdots+c_{N-1}x^{N-1}\),其中第 \(k\) 阶系数为: \[ \sum_{i+j\equiv k\pmod{N}}a_ib_i \]
由以上定义可知,\(R\) 的加法和乘法运算构成一个环。
概述
基于前面的加密算法,我们不难发现破解该算法的主要核心点就在于格攻击上,如果说我们将格的维度提高,那么就很自然的提高了攻击成本。
我们考虑将原本的整数环转化为多项式环,在多项式环进行相应的加解密运算,此时如果还想要对其进行攻击,就必须构建格 \[ \mathscr{L}=\begin{bmatrix} \lambda I&H\newline 0&qI \end{bmatrix}\newline H=\begin{bmatrix} h_{0} & h_{1} & \ldots & h_{N-1} \\ h_{N-1} & h_{0} & \ldots & h_{N-2} \\ \vdots & \vdots & \ddots & \vdots \\ h_{1} & h_{2} & \ldots & h_{0} \\ \end{bmatrix} \] 其中,\(H\) 是有关多项式 \(h\) 的系数循环矩阵,\(I\) 为单位矩阵,\(\lambda\) 为维持格大小的系数,\(q\) 是 NTRU 的参数。
这样很直接地增加了格的维度,使得时间复杂度显著提高,格规约结果变得不稳定,同时还能降低加密运算的复杂度(小的多项式系数照样有一定的安全强度)。
算法
这样根据上面的想法,我们可以改变一下原来算法的描述。
首先我们需要一些公共参数来确定多项式的阶和多项式系数的大小,并且做一定的约束。
公共参数
- \(N\) 是一个素数,要求其足够大以扩展格攻击中格的维度,\(N-1\) 就是多项式环的阶,同时这也是公钥之一。
- \(p,q\) 是互素的数,且 \(q\gg p\),这是为了保证密钥中的多项式 \(f\) 可以进行正常运算,选取的大小可以偏小,但不能太小(\(p\) 一般选择 3,\(q\) 一般选取 2 的倍数,例如 65536)。
- 向量空间 \(L_f,L_g,L_r,L_m\) 为 \(R(N)\)。
密钥生成
随机选取两个多项式 \(f\in L_f,g\in L_g\),其中保证多项式 \(f\) 在模 \(p\) 和模 \(q\) 下均可逆,其逆元分别表示为 \(f_p,f_q\),即满足 \[ f_p\cdot f\equiv1\pmod{p}\newline f_q\cdot f\equiv1\pmod{q} \]
计算 \(h\equiv f_q\cdot g\pmod{q}\)
那么公钥为 \((h,N)\),私钥为 \((f,g)\)
加密
将信息映射到 \(L_m\) 上,定义为 \(m\in L_m\)
随机选取 \(r\in L_r\)
用公钥 \(h\) 对消息进行加密(这里有可能并不会与 \(p\) 相乘,而是计算 \(h=p\cdot f_q\cdot g\pmod{q}\)): \[ e\equiv p\cdot r\cdot h+m\pmod{q} \]
\(e\) 即为密文
解密
- 计算 \(a\equiv f\cdot e\pmod{q}\),其中 \(a\) 的系数选在 \(\displaystyle(-\frac{q}{2},\frac{q}{2})\) 区间内,平衡系数方便计算。
- 计算 \(m=f_p\cdot a\pmod{p}\)
代码实现
1 | from random import shuffle |
解密原理
\[ \begin{align*} a&\equiv f\cdot e\\ &\equiv f\cdot p\cdot r+f\cdot m\pmod{q}\\ &\equiv f\cdot p\cdot r \cdot f_qg+f\cdot m\pmod{q}\\ &\equiv p\cdot r\cdot g+f\cdot m\pmod{q} \end{align*} \]
其中 \(a\) 的系数选在 \(\displaystyle(-\frac{q}{2},\frac{q}{2})\) 区间内,故 \[ m=f_p\cdot a\equiv f_p\cdot p\cdot r\cdot g+f_p\cdot f\cdot m\pmod{p}\equiv m\pmod{p} \]
格攻击
如概述所说,我们需要构建一个格来对其进行攻击,当 \(N\) 较小时,可以很轻松地进行攻击,可以证明 \((f_0,\cdots,f_N,g_0,\cdots,g_N)\) 在格上。
1 | N = 7 |
NTRU 求解
明文爆破
1 | import itertools |
输出为
1 | h = 39*x^9 + 60*x^8 + 349*x^7 + 268*x^6 + 144*x^5 + 469*x^4 + 449*x^3 + 165*x^2 + 248*x + 369 |
由于明文多项式较小,直接爆破即可:
首先各种多项式 m 的值
1 | fp = open('m.txt', 'w') |
然后直接爆破即可
1 | from Crypto.Hash import SHA3_256 |