Lattice Learning2

Lattice Learning

这一节利用格的知识解决一下之前遗留的问题

1.coppersmith

我们知道的是coppersmith是通过将求\(x_0\)满足\(f(x_0)≡0\)转换为一个具有相同根的小系数多项式F,使得能够满足\(F(x_0)=0\)

考虑一个简单情况下的应用:
N=17×19=323 ,F(x)=\(x^2+33x+215\) ,找小根\(x_0\)满足\(F(x_0)≡0(mod N)\)

我们找到多项式G(x)=9F(x)-N(x+6)=\(9x^2-26x-3\)=(9x+1)(x-3)

于是我们便找到了小根\(x_0=3\)

下面证明几个需要用到的引理

Theorem1(Howgrave-Graham)

利用 Howgrave-Graham提出的一个定理,可以完善Coppersmith寻找m模方程根的思想。

F(x)=\([a_0,a_1,···,a_n]\),有\(F(x_0)≡0(mod N)\)

\[\vec{a}=(a_0,a_1x_0,···,a_nx_0^n) \]

那么当\(||\vec{a}||<\frac{N}{\sqrt{n+1}}\)时有F\((x_0)=0\)

proof:

由cauchy不等式

\(|F(x)|≤\sqrt{(n+1)}||\vec{a}||<N\)

=>\(-N<F(x_0)<N =>F(x_0)=0\)

于是有了这个引理我们在求解模N的多项式小根解时,只需找到一个同根的小系数多项式

下面介绍小系数多项式如何找

根据上面例子的想法我们需要消去一个NG(x)

构造矩阵

\[A=\left[ \begin{matrix} N&0&0&0&···&0&0\\ 0&Nx&0&0&···&0&0\\ 0&0&Nx^2&0&···&0&0\\ ···&···&···&···&···&···&···\\ 0&0&0&0&···&Nx^{n-1}&0\\ a_0&a_1x&a_2x^2&a_3x^3&···&a_{x-1}x^{n-1}&x^n\\ \end{matrix} \right] \]

|A|=\(N^nx^\frac{n(n+1)}{2}\)

现在对A进行格基规约

记规约后的第一行向量为\(\vec{s}\)

由LLL的性质(了解不多,以后进行补充)

||\(\vec{s}\)||≤\(2^{\frac{n-1}{4}}det(L)^{\frac{1}{n}}\)

于是对A规约后我们有规约后的向量\(\vec{a}≤2^{\frac{n}{4}}N^{\frac{n}{n+1}}x^{\frac{n}{2}}\)

于是根据Theorem1,若\(2^{\frac{n}{4}}N^{\frac{n}{n+1}}x^{\frac{n}{2}}<\frac{N}{\sqrt{n+1}}\)则该向量满足我们的需求(但是这个范围相比图一所示的范围还是松了,以后再进一步分析)

下面举几个例子实验一下(虽然small_roots很好,但是我们还是需要知道原理的)

1.已知明文高位攻击

from Crypto.Util.number import *

m=bytes_to_long(b'happy_new_year!!!happy_new_year!!!happy_new_year!!!happy_new_year!!!')
e=3
p=getPrime(256)
q=getPrime(256)
n=p*q
c=pow(m,e,n)
print(n)
print(c)
print(m>>40)

#9677308850805072615245338772573038756194472761218833637549002026260651828849253582986766773068999761609142518697886921427163239409796891474031612292051243
#3619062459035100688199905801885001763102350553764315045632083081114951726640899393420854287661472297915641990877935483766234743101262919652708578368432163
#21354909218710478405558840015746007979798119883625401161254670224022140989734793925077991132006894434531534543193456590592582639039948875227320492718437

直接用small_roots()

n=9677308850805072615245338772573038756194472761218833637549002026260651828849253582986766773068999761609142518697886921427163239409796891474031612292051243
c=3619062459035100688199905801885001763102350553764315045632083081114951726640899393420854287661472297915641990877935483766234743101262919652708578368432163
m=21354909218710478405558840015746007979798119883625401161254670224022140989734793925077991132006894434531534543193456590592582639039948875227320492718437
m=m<<40
PR.<x>=PolynomialRing(Zmod(n))
f=(x+m)^3-c
print(f.small_roots(X=2^40,beta=0.4))

自己实现一下small_roots()

n=9677308850805072615245338772573038756194472761218833637549002026260651828849253582986766773068999761609142518697886921427163239409796891474031612292051243
c=3619062459035100688199905801885001763102350553764315045632083081114951726640899393420854287661472297915641990877935483766234743101262919652708578368432163
m=21354909218710478405558840015746007979798119883625401161254670224022140989734793925077991132006894434531534543193456590592582639039948875227320492718437
m=m<<40
A=Matrix(ZZ,[[n,0,0,0],[0,n,0,0],[0,0,n,0],[m^3-c,3*m^2,3*m,1]])
a0,a1,a2,a3=A.LLL()[0]
f=a3*x^3+a2*x^2+a1*x+a0
print(f.roots())
x0=418526601505
m=m+x0
print(m)

2.已知p高位攻击

from Crypto.Util.number import *

m=bytes_to_long(b'happy_new_year!!!happy_new_year!!!')
e=65537
p=getPrime(512)
q=getPrime(512)
n=p*q
c=pow(m,e,n)
print(n)
print(c)
print(p>>50)

#54060887550532723272804491491374218825303386194769604403301237855287320166950984445284954394763478284306466624176813065249567486894333153394551047300618799086142422643687308836933163238621183896218769490003417057463770405400335586296986350482751217289141261142237966211292736825145713656843966612806077745329
#22692808780477242242604897314135674620054340664309853323817502590548239362962842164482102833394042835412699817175849014262650146356823960891637841589136301486661603510207997804036604648165322903293580446732857395180046959403932388132572868509397243833454077454840359947651439987465748232122077365747130552350
#6310452412924798276026163996315343345064403172760003297028720453757654166862307758039141797676906511272518076593683813219223012613014341066

这个按照原来的格的构造方式无法得出(还是没弄懂small_roots()在此处的实现),这个地方有点特殊,copper在这个点的解决方式之前也没太看明白,到时候问明白一下😢


通过读paper终于想明白了,其实模n和模p在规约的时候并没有很大区别,只要你构造的格满足闵可夫斯基约束就有办法解决

https://github.com/mimoo/RSA-and-LLL-attacks/blob/master/survey_final.pdf

import gmpy2
n=54060887550532723272804491491374218825303386194769604403301237855287320166950984445284954394763478284306466624176813065249567486894333153394551047300618799086142422643687308836933163238621183896218769490003417057463770405400335586296986350482751217289141261142237966211292736825145713656843966612806077745329
c=22692808780477242242604897314135674620054340664309853323817502590548239362962842164482102833394042835412699817175849014262650146356823960891637841589136301486661603510207997804036604648165322903293580446732857395180046959403932388132572868509397243833454077454840359947651439987465748232122077365747130552350
p0=6310452412924798276026163996315343345064403172760003297028720453757654166862307758039141797676906511272518076593683813219223012613014341066
p0=p0<<50
e=65537
A=Matrix(ZZ,[[n,0,0,0,0,0],
            [p0,1,0,0,0,0],
            [0,p0,1,0,0,0],
            [0,0,p0,1,0,0],
            [0,0,0,p0,1,0],
            [0,0,0,0,p0,1]])
a0,a1,a2,a3,a4,a5=A.LLL()[0]
f=a5*x^5+a4*x^4+a3*x^3+a2*x^2+a1*x+a0
print(f.roots())
p=p0+333945612185009
q=n//p
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=int(pow(c,d,n))
print(m.to_bytes(40,'big'))

2.背包问题

虽然还没在题目里碰到过背包问题,但是这个确实是格攻击的典型了

简介

背包问题基于数学的子集和问题

给定一个正整数集合\((a_1,a_2,···,a_n)\),及整数S,求出\((x_1,x_2,···,x_n)\),使得\(∑a_ix_i=S\)

于是用在密码学上,我们可以把明文m的二进制信息,作为\(x_i\)分别乘上\(a_i\)将算出的S作为密文

在这个基础上,如果接收者能够快速找到\(x_i\)而敌手无法找到,那这就是一个行之有效的加密方式

这需要在原子集和问题基础上进行修改

先引入超递增数列的概念,

超递增数列:称一个序列A=\((a_1,a_2,···,a_n)\)是超递增数列,<=>对∀1≤i≤n-1有\(a_{i+1}≥2a_i\)

这种情况下我们很容易找到满足条件的X(等比数列算算),从\(x_n\)开始往前推

于是Merkle和Hellmen提出以下方案

1.Alice生成超递增数列A*,生成整数a,b,满足\(b>2a_n\),且(a,b)=1

2.Alice计算序列A≡aA* (modb),并将A作为公钥序列

3.Bob要加密信息m,将S=\(∑a_im_i\)发送

4.Alice接收到S后先计算\(S*=a^{-1}S(modb)\)

再求子集和问题(S*,A*)的解

由于A*是超递增数列,故Alice很容易便可算出明文m

但是在LLL算法下私钥长度须达到很大才能保证安全性

示例

现在具体实现一下攻击流程

import random
from Crypto.Util.number import *

m='10010010010100011101101'
def makekey(bits):
    A=[random.randint(1,100)]
    for i in range(1,bits):
        x=random.randint(2*A[i-1],3*A[i-1])
        A.append(x)
    while(1):
        a=getPrime(A[bits-1].bit_length()+1)
        b=getPrime(A[bits-1].bit_length()+1)
        if b>2*A[bits-1] and a!=b:
            break
    AA=[]
    for i in A:
        i=a*i%b
        AA.append(i)
    return A,AA,a,b
def MerkleHellmen(m):
    A,AA,a,b=makekey(len(m))
    C=0
    for i in range(len(m)):
        C+=AA[i]*int(m[i])
    print(AA)
    print(C)

MerkleHellmen(m)

#[69625456399, 50216649406, 37647263665, 69864762116, 73193132405, 97788130380, 79658655279, 94330003119, 1885700479, 83965859888, 68552103445, 108757121293, 107985028412, 80341581743, 107145204046, 71693027761, 70591195267, 113983796351, 91862656854, 30728147032, 116634672822, 114087627810, 10823305638]
#826325999846

开始明文取的是happy_new_year的二进制,发现LLL跑不出来,问学长才想起来LLL解高维的格也不太行

于是就把m随便取了一串二进制

我们构造格进行规约,得到的结果的第一行就是m(注意常数的选取还是十分巧妙的)

\[\left[\begin{matrix} 2&0&0&0&···&0&a_1\\ 0&2&0&0&···&0&a_2\\ 0&0&2&0&···&0&a_3\\ 0&0&0&2&···&0&a_4\\ ···&···&···&···&···&···&···\\ 0&0&0&0&0&2&a_{n}\\ 1&1&1&1&1&1&s \end{matrix}\right] \]

A=[69625456399, 50216649406, 37647263665, 69864762116, 73193132405, 97788130380, 79658655279, 94330003119, 1885700479, 83965859888, 68552103445, 108757121293, 107985028412, 80341581743, 107145204046, 71693027761, 70591195267, 113983796351, 91862656854, 30728147032, 116634672822, 114087627810, 10823305638]
s=826325999846
n=len(A)
L=Matrix.zero(n+1)
for i in range(n):
    L[i,i]=2
    L[i,n]=A[i]
for i in range(n):
    L[n,i]=1
L[n,n]=s
m=list(L.LLL()[0])
for i in range(len(m)):
    if m[i]==-1:
        m[i]=1
    else:
        m[i]=0
print(m)

3.Boneh and Durfee attack


wait for update

4.WienerAttack-Extend

多组e的维纳攻击方式,照着wiki过一遍,非常硬核的一篇文章,正好把维纳攻击过程复习一下

Wiener‘s approach

维纳攻击的使用条件:d<\(\frac{1}{3}N^{\frac{1}{4}}\) ,故也称低解密指数攻击

我们有ed-kλ(N)=1 =>edg-kλ(N)g=g =>edg-kφ(N)=g

=>edg-kN=g-k(p+q-1)

=>\(\frac{e}{N}-\frac{k}{dg}=\frac{g-k(p+q-1)}{dgN}=\frac{1}{dN}-\frac{k(p+q-1)}{dgN}\)

注意到e~N,(p+q-1)~\(\sqrt{N}\) =>\(\frac{k}{dg}\)~1

故|\(\frac{e}{N}-\frac{k}{dg}\)|~\(\frac{1}{\sqrt{N}}\)

由Legendre定理

故我们只需\(2(dg)^2<\sqrt{N}\) =>d<\(\frac{\sqrt{2}}{g}N^{\frac{1}{4}}\)时我们可以根据\(\frac{e}{N}\)的连分数展开得到\(\frac{k}{dg}\)

Guo's approach

这种方法是针对多个e的情况的研究

\(e_1d_1g-k_1φ(N)=g\)

\(e_2d_2g-k_2φ(N)=g\)

\(=>e_1d_1k_2-e_2d_2k_1=k_2-k_1=>\frac{e_1}{e_2}-\frac{d_2k_1}{d_1k_2}=\frac{k_2-k_1}{e_2d_1k_2}\)

\(d_i<N^α =>\frac{k_2-k_1}{e_2d_1k_2}~N^{-(1+α)}\)

则当\(2(d_1k_2)^2<N^{(1+α)}\)时我们可以通过\(\frac{e_1}{e_2}\)的连分数展开求得\(\frac{d_2k_1}{d_1k_2}\)

Extend

我们记s=1-p-q

\(W_i:e_id_ig-k_iN=g+k_is\)

\(G_{i,j}:k_id_je_j-k_jd_ie_i=k_i-k_j\)

不妨设\(d_i,k_i<N^α\) =>\(W_i,G_{i,j}\)的右边等式估计为\(N^{\frac{1}{2}+α}\)\(N^α\)

\(W_iG_{i,j}\)的大小估计为\(N^{\frac{1}{2}+2α}\)

我们考虑三个等式\(k_2W_1,gG_{1,2},W_1W_2\)(展开写一下,不然格的构造太抽象了)

\(k_2e_1d_1g-k_1k_2N=k_2g+k_1k_2s\)

\(k_1e_2d_2g-k_2e_1d_1g=(k_1-k_2)g\)

\(e_1e_2d_1d_2g^2-k_1e_2d_2gN-k_2e_1d_1gN+k_1k_2N^2=(g+k_1s)(g+k_2s)\)

\[(k_1k_2,d_1gk_2,d_2gk_1,d_1d_2g^2)\left[\begin{matrix}1&-N&0&N^2\\\\&e_1&-e_1&-e_1N\\\\&&e_2&-e_2N\\\\&&&e_1e_2\end{matrix}\right]=(k_1k_2,k_2(g+k_1s),g(k_1-k_2),(g+k_1s)(g+k_2s)) \]

注意到det(L)~N,很容易发现右边的向量不满足Minkowski第一定理的约束

\(λ_1≤\sqrt{n}det(L)^{\frac{1}{n}}\)
这也是为什么在做有难度的题的时候需要反复调整所构造的格(太难了呀)

估计右边向量各分量的范围\(N^{2α},N^{2α+1/2},N^α,N^{2α+1}\)

\(\sqrt{n}det(L)^{\frac{1}{n}}\)=2N

这里我们考虑调整格的构造使得右边的向量满足Minkowski约束

注意到两边右乘对角阵,左边是乘积速率增长而右边是加法速率增长

且注意Minkowski约束的取等大致可理解为一个正n维体的构造

于是我们构造L*=\(\left[\begin{matrix}N&0&0&0\\0&N^{\frac{1}{2}}&0&0\\0&0&N^{α+1}&0\\0&0&0&1\end{matrix}\right]\)等式两边同乘

\(\sqrt{n}det(LL*)^{\frac{1}{n}}\)=2\(N^{\frac{13}{8}+\frac{α}{4}}\)

右边向量的长度为\(2N^{2α+1}\)

故我们只需要求α<\(\frac{5}{14}\)就有可能利用格基规约得到该向量(相比之下Wiener要求α<\(\frac{1}{4}\))

sage实现一下

e1=
e2=
N=
a=5/14
L=Matrix(ZZ,[[1,-N,0,N^2],[0,e1,-e1,-e1*N],[0,0,e2,-e2*N],[0,0,0,e1*e2]])
LL=diagonal_matrix(ZZ,[N,int(N^(1/2)),int(N^(a+1)),1])
L=L*LL
v=L.LLL()[0]
t=v*L^(-1)
print(t)

三组\(e~i\)格构造如下

\[L=\left[\begin{matrix}1&-N&0&N^2&0&0&0&-N^3\\\\ 0&e_1&-e_1&-e_1N&-e_1&0&e_1N&e_1N^2\\\\ 0&0&e_2&-e_2N&0&e_2N&0&e_2N^2\\\\ 0&0&0&e_1e_2&0&-e_1e_2&-e_1e_2&-e_1e_2N\\\\ 0&0&0&0&e_3&-e_3N&-e_3N&e_3N^2\\\\ 0&0&0&0&0&e_1e_3&0&-e_1e_3N\\\\ 0&0&0&0&0&0&e_2e_3&-e_2e_3N\\\\ 0&0&0&0&0&0&0&e_1e_2e_3\end{matrix} \right]\times L^* \]

L*=diag(\(\begin{matrix}N^{\frac{3}{2}}&N&N^{α+\frac{3}{2}}&\sqrt{N}&N^{α+\frac{3}{2}}&N^{α+1}&N^{α+1}&1\end{matrix}\))

此时α<\(\frac{2}{5}\)即可

得到指数的范围大小的变化为\(\frac{1}{4},\frac{5}{14},\frac{2}{5},···,1-ε\)

posted @ 2022-01-23 16:57  hash_hash  阅读(220)  评论(0编辑  收藏  举报