Lattice

Reference


​ 本文大部分参照《An introduction to mathematical cryptography》第六章,有兴趣的读者可以自行阅读相关内容。

格基规约算法

格基规约

Background


The security of all of the public key cryptosystems that we have previously studied has been based, either directly or indirectly, on either the difficulty of factoring large numbers or the difficulty of finding discrete logarithms in a finite group. In this chapter we investigate a new type of hard problem arising in the theory of lattices that can be used as the basis for a public key cryptosystem. Further, we will see that the theory of lattices has applications in cryptography beyond simply providing a new source of hard problems.

​ Recall that a vector space V over the real numbers R is a set of vectors, where two vectors can be added together and a vector can be multiplied by a real number. A lattice is similar to a vector space, except that we are restricted to multiplying the vectors in a lattice by integers. This seemingly minor restriction leads to many interesting and subtle questions. Since the subject of lattices can appear somewhat abstruse and removed from the everyday reality of cryptography, we begin this chapter with two motivating examples in which lattices are not mentioned, but where they are lurking in the background, waiting to be used for cryptanalysis.


\(\mathcal{A \ toy \ model}\)


\(\mathcal{How \ to \ do}\)

​ 这里介绍一个并不安全密码学方案,它是 lattice 可用于传统公钥密码分析的例证,另外也是 NTRU 公钥密码体系的一个低端版本。这里是做启发性来帮助大家更容易地理解格问题。

​ Alice首先选择一个大整数q作为公钥的一部分,然后另取两个整数f,g满足

\[f <\sqrt{q/2}, \qquad \qquad \sqrt{q/4}<g<\sqrt{q/2}, \qquad and \qquad \quad gcd(f,q)=1. \]

​ 然后Alice计算一个乘机h(\(gcd(f,q)=1\)证明存在\(f^{-1}\)

\[h \equiv f^{-1}g \quad (mod \quad q) \qquad with \quad 0<h<g \]

​ 对于Alice来说,

\[\begin{align} &pk = (h,q) \\ &sk= (f,g) \\ which \quad pk \quad means \quad public &\quad key \quad and \quad sk \quad means \quad secret \quad key \end{align} \]

​ 对于Bob,想要给Alice发送消息,需要保证\(m<\sqrt{q/4}\),然后随机的选取\(0<r<\sqrt{q/2}\),计算

\[e=rh+m \quad(mod \quad q) \\ \]

​ 然后将密文发送给Alice,那么Alice该如何解密呢?

​ 首先Alice计算以下内容

\[a=fe\quad (mod \quad q) \\ b=f^{-1}a \quad (mod \quad g) \]

​ 可以很容易证明,b就是我们所要求的m

\[\begin{align} &a=fe=f(rh+m)=frh+fm=fr(f^{-1}g)+fm=rg+mf \quad (mod \quad q) \\ &\because \ r,g,m,f<\sqrt{q/2} \\ &\therefore \ rg+mf<\sqrt{q/2}*\sqrt{q/2}+\sqrt{q/2}*\sqrt{q/2}\ <q \\ \end{align} \]

​ 即\(a\)就是\(rg+mf\)的真实值。

\[\begin{align} &b=f^{-1}a=f^{-1}(rg+fm)=m \quad (mod \quad g) \\ &\because \ m <\sqrt{q/4}<g \\ &\therefore \ b \quad is \quad the \quad true \quad value \quad of \quad m \end{align} \]

​ 即\(b\)就是\(m\)的真实值

​ 大致流程入下表所示。

image-20221012104512759

\(\mathcal{How \ to \ attack}\)


​ 现在,我们来考虑敌手 Eve 如何攻击这个密码体系。仅仅已知公钥$ (q,h)\(,她并不能找到真正的\)(f,g)\(;但她可以找到一组\) (F,G)\(,如果\) (F,G) \(在解密时表现与\)(f,g)$ 相同,那么 Eve 就可以完成解密工作。

​ 具体而言,她需要找到 \(F,G\) 满足

\[Fh≡G(mod\quad q),F=O(q),G=O(q) \]

​ 显然真正的 (f,g) 是合法的 (F,G). 现在的问题是为什么这样的 (F,G)可以用于解密。我们有

\[Fe≡F⋅(rh+m)≡rG+Fm\quad (mod\quad q) \]

​ 注意到这求出了\(rG+Fm\)的真实值。继续按照原先的解密算法来操作,模掉G\(Fm(mod\quad G)\),乘以F的逆元,即可恢复出m.

  也就是说,Eve 只需要找到合法的 (F,G),就可以攻破这个密码体系。将\(Fh≡G(mod \ R)\)改写为等价形式\(Fh=G+qR\),那么 Eve 的任务就是找到足够小的 F,G 使得

\[F(1,h)−R(0,q)=(F,G) \]

  这个式子等价于$ (1,h),(0,q)$ 这两个向量以$ F,R \(为系数进行线性组合。如果我们能找到合适的\) F,R$,使得线性组合出来的向量足够短,那么我们就找到了合法的 \((F,G)\),长度为\(O(\sqrt{q})\)来攻击密码体系。

  上面的问题可以概括为:有两个已知的向量,需要找出一套线性组合系数(必须是整数),来生成一个足够短的向量。Eve 的任务是:已知$ v1=(1,h)$ 和 \(v2=(0,q)\),长度均为 \(O(q)\),要寻找它们的线性组合\(w=a_1v_1+a_2v_2\),长度为\(O(q)\). 要求系数\(a1,a2\)均为整数。

  从 lattice 的角度看,Eve 是在一个 lattice\(L\)中寻找一个很短的向量:

\[L={a_1v_1+a_2v_2:a_1,a_2∈Z} \]

  在二维的 lattice 里面找最短向量,是有高效算法的(Gauss算法)。于是 Eve 攻破了这个密码体系。

​ 下面介绍高斯方法。

\(\mathcal{Gaussian\ lattice\ reduction\ in\ dimension\ 2}\)

\(\mathcal{Algorithm \quad process}\)

image-20221012111635146

其中,\(v_1\)即为求解的SVP。

\(\mathcal{Proof}\)

我们假设算法终止并且返回了两个向量\(v_1\),\(v_2\),这意味着\(\parallel v_2\parallel \geq \parallel v_1 \parallel\),并且

\[\frac{\mid v_1 \cdot v_2 \mid}{\parallel v_1 \parallel^{2}} \leq \frac{1}{2} \]

假设\(v \in L\)是一个\(L\)中的任意非零向量(any nonzero vector),记为

\[v=a_1v_1 \ + \ a_2v_2 \qquad with \ a_1,a_2 \in \mathbb{Z} \]

可以证明

\[\begin{align} \parallel v \parallel^2 &= \parallel a_1v_1 \, + \, a_2v_2 \parallel^2 \\ & = a_1^2 \parallel v_1 \parallel^2 + 2a_1a_2(v_1\cdot v_2)+a_2^2 \parallel v_2 \parallel^2 \\ & \geq a_1^2 \parallel v_1 \parallel^2 - 2\mid a_1a_2\mid \mid v_1\cdot v_2\mid +a_2^2 \parallel v_2 \parallel^2 \\ & \geq a_1^2 \parallel v_1 \parallel^2 - \mid a_1a_2\mid \parallel v_1 \parallel^2 +a_2^2 \parallel v_2 \parallel^2 \\ & \geq a_1^2 \parallel v_1 \parallel^2 - \mid a_1a_2\mid \parallel v_1 \parallel^2 +a_2^2 \parallel v_1 \parallel^2 \quad since \ \parallel v_2\parallel>\parallel v_1 \parallel \\ & = (a_1^2-\mid a_1 \mid \mid a_2 \mid + a_2^2)\parallel v_1 \parallel^2 \end{align} \]

对于任意的\(t_1\),\(t_2\),公式

\[t_1^2 \ - \ t_1t_2 \ + \ t_2^2 \quad = \quad (t_1 \ - \ \frac{1}{2}t_2)^2 \ + \ \frac{3}{4}t_2^2 \quad = \quad \frac{3}{4}t_1^2 \ + \ (t_2 \ - \ \frac{1}{2}t_1)^2 \]

只有\(t_1=t_2=0\)时为0。而且考虑到\(a_1,a_2\)都是非零整数,所以有\(\parallel v \parallel > \parallel v_1 \parallel\)

\(\mathcal{Code}\)

# python
def Gauss_SVP(v1,v2):
    while True:
        m = (v1[0] * v2[0] + v1[1] * v2[1]) / (v1[0] * v1[0] + v1[1] * v1[1])
        m = round(m)
        v2 = [v2[0]-m*v1[0] , v2[1]-m*v1[1]]
        if (v2[0] * v2[0] + v2[1] * v2[1]) >= (v1[0] * v1[0]+ v1[1] * v1[1]):
            break
        else:
            tmp = v1
            v1 = v2
            v2 = tmp

    return v1
# sagemath
def Gauss(v1,v2):
    while True:
        m = round(v1.dot_product(v2) / v1.dot_product(v1))

        v2 = v2 - m*v1

        if v1.norm()<v2.norm():
            return v1
        else:
            v1,v2 = v2,v1

# 另一种写法
def Gauss(v1,v2):
    while True:
        if v2.norm() < v1.norm():
            v1,v2 = v2,v1
        m = round(v1.dot_product(v2)/v1.dot_product(v1))
        if m == 0:
            return v1
        v2 = v2-m*v1

\(\mathcal{Example \ NSSCTF\ little\ lattice}\)


from Crypto.Util.number import *
from hashlib import *
from sage.all import *

p = getPrime(2048)
f = getPrime(1024)
g = getPrime(768)
h = pow(f,-1,p)*g%p
verify = sha256(bytes.fromhex(hex(f+g)[2:])).hexdigest()
print(f'verify = {verify}')
print(f'p = {p}')
print(f'h = {h}')
print('NSSCTF{' + md5(bytes.fromhex(hex(f+g)[2:])).hexdigest() + '}')


'''
verify = 24425b693dbcace08a32572d499a5cbeb36e30db9278704195c67c3d32a81bdf
p = 29908110980126088961686288727545150169450107297750996656924523214377817308111189721234667959695817050736874247951762130190209278324144437406652857446810518839546701950883392761869656586963587376306050382973323860395932741791372333809871487575268245618618143456971257992301722141464238875859134379745122404533776003095129169004284619647906206323263396219776072091827094295366090100037898314156271404760715453914459484087562963158208356228410105170495322276351631637885450926240143055767142216931354736779666836018983658010126520397012025067407223630891975504746697630878807952266767406899527721170062789607980517722293
h = 26523576589113781532769165293024254940419790396713708680496148398686334583553504180195363282085884580924842673123375450894537445679687851322807762432476357713740302064160599132450619363411158141423252170448770929403179895813409897048848337375715079396639330537231353596884530617911351334318435031007342479134081403319324838464987064025256038807217697133175585927493402963025439540077915248356077623612217525231722274634984400273765262532561558296870531741633238736650375250957780701118781183335729715295271752736307479795186963108377228330313771245434127095507278278768792281414702334956407755841000748255424212840137
'''

def Gauss(v1,v2):
    while True:
        m = round(v1.dot_product(v2) / v1.dot_product(v1))

        v2 = v2 - m*v1

        if v1.norm()<v2.norm():
            return v1
        else:
            v1,v2 = v2,v1
    return v1

q = 29908110980126088961686288727545150169450107297750996656924523214377817308111189721234667959695817050736874247951762130190209278324144437406652857446810518839546701950883392761869656586963587376306050382973323860395932741791372333809871487575268245618618143456971257992301722141464238875859134379745122404533776003095129169004284619647906206323263396219776072091827094295366090100037898314156271404760715453914459484087562963158208356228410105170495322276351631637885450926240143055767142216931354736779666836018983658010126520397012025067407223630891975504746697630878807952266767406899527721170062789607980517722293
h = 26523576589113781532769165293024254940419790396713708680496148398686334583553504180195363282085884580924842673123375450894537445679687851322807762432476357713740302064160599132450619363411158141423252170448770929403179895813409897048848337375715079396639330537231353596884530617911351334318435031007342479134081403319324838464987064025256038807217697133175585927493402963025439540077915248356077623612217525231722274634984400273765262532561558296870531741633238736650375250957780701118781183335729715295271752736307479795186963108377228330313771245434127095507278278768792281414702334956407755841000748255424212840137

v1= vector([1,h])
v2= vector([0,q])

f,g = Gauss(v1,v2)

verify = sha256(bytes.fromhex(hex(f+g)[2:])).hexdigest()
print(f'Verify = {verify}')
print(f'Verify = {sha256(bytes.fromhex(hex(f+g)[2:])).hexdigest()}')
print('NSSCTF{' + md5(bytes.fromhex(hex(f+g)[2:])).hexdigest() + '}')
# Verify = 24425b693dbcace08a32572d499a5cbeb36e30db9278704195c67c3d32a81bdf
# Verify = 24425b693dbcace08a32572d499a5cbeb36e30db9278704195c67c3d32a8bdf
# NSSCTF{884beaede45bb83d3706bcc14827dece}

\(\mathcal{Subset-sum\ \ problems\ \ and\ \ knapsack\ \ cryptosystems}\)

posted @ 2022-10-12 16:22  J4m  阅读(175)  评论(0编辑  收藏  举报