NTRU格密码

NTRU格密码

优势

可以抵抗量子计算、加密体制算法简洁、加解密速度较快、占用空间小、

其安全性依赖于格中的最短向量求解问题(SVP)

密钥生成

Alice需要选择四个整数参数\((N,p,q,d)\)和4个次数为\(N-1\)的整系数多项式集合\(L_f,L_g,L_φ,L_m\),其中\(N\)为素数,\(p,q\)不必为素数但\(gcd(p,q)=1\),且\(q>(6d+1)p\)

\(L(d_1,d_2)=\lbrace F(x)\in R\rbrace\),其中\(F(x)\)\(d_1\)个系数为\(1\)\(d_2\)个系数为\(-1\),其余为\(0\)。Alice再选择两个多项式\(f\in L(d+1,d),g\in L(d,d)\),并且计算\(f\)\(R_p,R_q\)中的逆\(F_p(x),F_q(x)\),若逆不存在则需重新选择\(f\)

而后Alice计算\(R_p\)中的\(h=F_q*g\),把\(h,(N,p,q,d)\)作为公钥,\(f,g\)作为私钥。

加密

Bob有明文\(m\in R_p\),再选择一个随机多项式\(r\in L(d,d)\),计算\(e\equiv pr*h+m(mod\ q)\)

解密

Alice收到密文e后,计算\(a\equiv f*e\equiv pg*r+f*m(mod\ q)\),将\(a\)移动到\(R\)上后再计算\(m\equiv F_p*a(mod\ p)\)就得到了明文

将NTRU写成格的形式

​ 我们构造这样一个矩阵:\(M=\begin{bmatrix} 1 &h \\0&q \end{bmatrix}\)作为lattice,接下来我们证明向量\((f,g)\)是在这个lattice上的。

首先我们可以将同余式\(f*h\equiv g\ (mod\ p)\)改写成等式\(f*h=g+k*p\),再变形\(f*h-k*p=g\)

我们可以发现,\((f,-u)M=(f,-u)\begin{bmatrix} 1 &h \\0&q \end{bmatrix}\)

\(=(f+(-u)*0,f*h+(-u)*p)\)

\(=(f,f*h-u*p)\)

\(=(f,g)\)

也就是说,\((f,g)\)可以用两组向量基\(M\)的某种整系数线性组合\((f,-u)\)来表示,因此\((f,g)\)确实在这个lattice

一道例题

题目附件

源码:

from Crypto.Util.number import *
import gmpy2
from flag import flag


def generate():
    p = getStrongPrime(2048)
    while True:
        f = getRandomNBitInteger(1024)
        g = getStrongPrime(768)
        h = gmpy2.invert(f, p) * g % p
        return (p, f, g, h)


def encrypt(plaintext, p, h):
    m = bytes_to_long(plaintext)
    r = getRandomNBitInteger(1024)
    c = (r * h + m) % p
    return c


p, f, g, h = generate()
c = encrypt(flag, p, h)
with open("cipher.txt", "w") as f:
    f.write("h = " + str(h) + "\n")
    f.write("p = " + str(p) + "\n")
    f.write("c = " + str(c) + "\n")

generate中生成了4个参数:

\(p\):一个\(2048\)位强素数

\(f\):一个\(1024\)位随机数

\(g\):一个\(768\)位强素数

\(h\)\(h\equiv f^{-1}*g\ (mod\ p)\)

encrypt生成一个\(1024\)位随机数\(r\)\(c\equiv r*h+m\)

假设我们知道\(f,g\)

再加上\(h\equiv f^{-1}*g\ (mod\ p)\)\(c\equiv r*h+m\ (mod\ p)\)

就可以有\(c\equiv r*(f^{-1}*g)+m\ (mod\ p)\)

\(c*f\equiv r*f^{-1}*g*f+m*f\ (mod\ p)\)

\(c*f\equiv r*g+m*f\ (mod\ p)\)

观察等式右边可以发现,\(r*g+m*f(约1800位)\)并没有大于\(p(2048位)\)

所以就可以将同余号改成等号

\(a=c*f \ (mod\ p)\),就有\(a=r*g+m*f\)

对等式模\(g\)

\(a\equiv m*f\ (mod\ g)\)

\(m\equiv a*f^{-1}\ (mod\ g)\)

一个小问题

​ 我们知道\(g\)是一个768位的强素数,虽然\(f\)是1024位,但是在\(mod\ g\)下,\(f\)的逆元是必定存在的。

那么

接下来就要求\(f,g\)

前面已经证明过,\((f,g)\)是存在于lattice上的

\(|(1,h)|\approx 2^{2000}\)

\(|(0,p)|\approx 2^{2048}\)

\(|(f,g)|\approx 2^{1024}\)

根据Gaussian heurstic定理可知,在这个lattice中最短向量的长度大概在\(sqrt(2^{2048})=2^{1024}\)左右。因此,很大概率上,这个\((f, g)\)就是这个lattice的最短向量。

怎么在lattice上求最短向量呢

虽然SVP是NP-hard,但本题中维度较低所以并不难求解

目前LLL算法及其变种算法是已知在较低维度的lattice中求解SVP的最好的算法,但在高纬度就比较乏力了

h = 7257231567493321493497732423756001924698993879741072696808433246581786362611889417289029671240997843541696187487722285762633068287623369923457879458577466240950224087015909821079480431797917376609839097610864517760515986973340148901898582075413756737310797402537478388864632901178463429574227279668004092519322204990617969134092793157225082977967228366838748193084097651575835471869030934527383379794480007872562067799484905159381690179011192017159985260435844246766711550315143517066359521598424992244464723490166447105679062078049379153154659732304112563255058750656946353654402824529058734270363154894216317570784
p = 23969137365202547728693945383611572667294904799854243194734466236017441545927679469239814785947383727854265554138290421827510545078908517696536495567625593439996528098119344504866817224169113920532528233185011693829122447604993468817512696036673804626830507903206709121383065701222707251053362179946170981868061834734684494881504724254812067180384269711822738708203454131838741703416329765575995359232573740932069147491776326045743679105041246906081872936901848272288949389026129761726749334006319072981386763830897454245553866145620689939497868469730297795063648030738668273210516497399954626983672357236110363894081
c = 6388077150013017095358415295704360631706672647932184267739118115740221804173068089559645506533240372483689997499821300861865955720630884024099415936433339512125910973936154713306915269365877588850574948033131161679256849814325373882706559635563285860782658950169507940368219930971600522754831612134153314448445006958300840618894359885321144158064446236744722180819829183828290798747455324761671198097712539900569386477647697973195787663298318786718012522378981137877863153067057280649127202971806609339007027052518049995341356359016898069863799529357397514218249272201695539181908803360181347114492616706419618151757

# Construct lattice.
v1 = vector(ZZ, [1, h])
v2 = vector(ZZ, [0, p])
m = matrix([v1,v2]);

# Solve SVP.
shortest_vector = m.LLL()[0]
f, g = shortest_vector
print(f, g)

# Decrypt.
a = f*c % p % g
m = a * inverse_mod(f, g) % g
print(hex(m).decode('hex'))

Summary

本题只是NTRU在低纬度的一道题目

由于本人比较fw,对较高纬度中的NTRU还没有什么研究(

posted @ 2022-02-21 08:46  上辰  阅读(1039)  评论(2编辑  收藏  举报