基于NTRU的签名算法学习1
时间:2025-07-16 | 作者: | 阅读:0本文基于Modular Lattice Signatures, revisited学习了NTRUSign的基本思想,以及其改进。本文主要对该文章进行了转译,并利用python实现了底层的加解密、同态、签名等运算。
1. ?介绍
??由于量子计算机的威胁,组织和研究小组正在寻找候选算法来替代RSA和ECC基于方案。在所有候选方案中,基于点阵的解决方案似乎是最有前途的解决方案。对于加密方案,NTRUEncrypt是已知的最快的基于格的加密算法之一。在签名方案方面,目前有几种基于格点的签名方案依赖于NTRU格点的安全性,如BLISS、DLP和pqNTRUSign 。
??本文重述了模格签名方案。给定具有陷门函数T的格L,它是行向量的短基;和向量m形式的信息摘要,其系数为[0,p)模签名方案的签名是格向量v,使
??1.v≡mmodp
??2.v∈L
??可以通过以下步骤获得此向量:
??1.从L采样一个向量v0;
??2.用T对v0进行微调,使v:=v0+aT满足某a的同余条件;
??3.使用拒收抽样从v中隐藏T
??在本文中,我们将从以下角度重新审视上述方案。
??安全证明。在原模格签名方案中,公钥安全问题与唯一最短非零向量问题(uSVP)有关。从L(一个坏的基础)中恢复T;而不可伪造性是基于一个晶格与一个晶格平移的交点上的近似最接近向量问题(approx-CVP),即L∩(pZn+mp)。虽然第二个问题对于这个特殊的晶格来说是困难的,但是第一个问题和第二个问题之间的联系是缺失的。因此,该方案需要两个(看似独立的)硬度假设。例如,当方案通过一个NTRU晶格实例化时,他们需要对NTRU晶格进行uSVP假设,对两个晶格的交集进行上述approx- cvp假设。
??在本文中,我们去掉了第二个假设。从本质上说,攻击者是给定一个晶格(任何晶格,不一定NTRU晶格),他被要求找到一个等晶格向量,这个向量相等的已知值mod p。换句话说,攻击者需要找到一个向量与预先确定的在这篇文章中,我们删除第二个假设。从本质上说,攻击者是给定一个晶格(任何晶格,不一定NTRU晶格),他被要求找到一个等晶格向量,这个向量相等的已知值mod p。换句话说,攻击者需要找到一个向量与预先设定的最低有效位。我们命名这个问题与截断(LWT)学习问题,可以被视为学习的逆着(LWR)问题,给出了在这种情况下,一个矩阵A和b =??sAmodq?p,并要求找到s。也就是说,找到一个向量与晶格预先确定的最重要的部分.
??这允许我们将伪造攻击与approx-SVP连接起来。因此,我们只需要一个简单的假设。特别地,当方案通过一个短整数解决方案(SIS)问题实例化时,在我们的方案中伪造签名与解决随机格的approx-svp一样困难。另一方面,当方案通过一个NTRU格实例化时,我们要求NTRU格的approx- svp是困难的,这等价于unique- svp假设(直到一个多项式因子),即, NTRU算法。
??抽样方法。早期基于点阵的签名方案,如GGHSign和NTRUSign,在消息/签名对的转录本中泄漏私钥信息。攻击者可以使用学习平行六面体的方法从足够长的文本中生成签名密钥"。
??其中,Lyubashevsky提出了一种拒绝采样的方法来阻止转录泄漏攻击。使用他的技术,签名是根据一个固定的公共分布产生的(通常是一个高斯分布,如均匀分布)。记录只显示这种公开分发,不包含关于用于生成签名的特定签名密钥的信息。因此,采样方法成为设计签名方案的核心问题。例如,用双模高斯采样器代替高斯采样器可以显著提高算法的性能.
??原先方案中的签名是格向量。由于验证者已经知道用于验证目的的格的一个(坏的)基,只要验证者在验证阶段能够完成整个向量,那么传输部分向量v就足够了。
??流行的基于格的方案,如BLISS和TESLA,没有这个性质。这些方案中的签名是接近晶格的向量。因此,当向量被压缩时,需要为验证者生成一个额外的帮助器来推导原始向量(尽管这个帮助器只有几百位)。具体地说,如果我们用原先方案中相同的参数来参数化本文提出的方案,签名大小的差异就是这个参数的大小。
??由于采样方法的原因,这种设计上的优势并没有给出更小的签名尺寸。对于系数为[?q/2,q/2)的n维向量,需要n?logq?位进行存储。相比之下,一个离散高斯向量相同的尺寸的偏差σ~q可以存储~n(logq/2+2)位。一个自然的问题是,是否可以使用(双峰)高斯采样[10]对模格签名。在本文中,我们对这个问题给出了肯定的回答.
??备注1。虽然使用高斯采样的方案允许更小的签名大小,但基于格点的签名方案最近的发展显示出一种向均匀拒绝采样的趋势,因为均匀采样更容易实现和确保恒定的时间。然而,使用pqNTRUSign,高斯采样使我们获得了一个额外的属性:签名聚合。
??签名聚合。签名聚合,也称为批处理验证,允许验证一组签名(在同一键下签名),其操作顺序为单个验证。在许多用例中,它是一个有用的属性。例如,对于签名软件映像的安全引导机制,签名聚合允许在一次验证整个软件映像集的同时,分别对各个软件映像进行签名(并且按照组件的方式而不是单块更新)。这允许快速启动.
??我们的方案允许批处理验证(参数经过微调)。一般来说,对于消息摘要m的签名v只要≡m mod p和v∈L就有效。因此,对于一组签名vi,对应于我们所拥有的一组消息mi.
??1.∑vi≡∑mimodp
??2.∑vi∈L
??因此,我们可以简单地检查∑vi而不是检查每个v。在为我们提出的方案实现这种技术时,我们可以使用单环乘法(这通常是验证中代价最高的操作)来验证一批签名。不过我们注意到,仍然需要执行多个散列函数来获得这些消息摘要。此外,由于累积的签名在格子中是一个更大的向量(与单个签名相比),我们将要求这个累积的签名对应的格子问题也很困难。
??我们还注意到,其他基于格的方案,如BLISS和TESLA,不能轻易地提供这个属性,因为它们需要在哈希函数之前执行环操作。
2. 背景知识
??向量用小写粗体字,矩阵用大写粗体字。对于一个多项式f(x)=f0+f1x+...+fn?1xn?1,我们用f表示其向量形式
??我们经常使用多项式环Rq:=Z[x]/F(x)和F(x)=xn±1。环Rq上多项式f(x)的循环旋转矩阵为矩阵M=(f1,f2,...,fn)T;如果f(x)=xn?1,它是完全循环的,并且接近于循环,直到符号,如果f(x)=xn+1。
??对于一个真实的a,我们让bae表示到a的壁橱整数。对于一个整数a,我们使用[a]q来表示a mod q,?a?p:=(a?[a]p)p/用于将a四舍五入到p的最接近倍数的运算。模运算的中心被提升,例如模q在?q/2和q/2范围内返回一个整数。这些符号也扩展到向量和矩阵中。
??NTRU,SIS,LWR与格
??格L是Rn的离散子群,也就是d≤n个线性无关向量在R上的所有积分组合的集合:
??L:=Zb1+Zb2+...+Zbd,bi∈R
??B:=(b1.....bd)T称为L的一组基,给定一个格L,找到一个不超过γ?λ1(L)的向量称为近似最短向量问题(γ?SVP),其中λ1是晶格中最短向量的长度。高斯函数的启发式说在一个随机格中,这第一个最小值λ1≈2πedimdet(L)dim1在det(L)表示的行列式L?.给定一个特定的晶格L,存在一个唯一最短非零向量,发现这个向量称为独特的最短向量问题(u-SVP)
??我们把一个NTRU格看成是一个2阶的Rq模。让f,g的系数为小于q的实数。令h=g/f在?Rq。与h相关的NTRU晶格定义为
??L:={(s,t)∈Rq2:t≡shmodq}.
??已知h,认为很难找到f和g,这就是NTRU假设,可以简化为NTRU格点唯一的最短向量问题。
??我们把NTRU晶格中的向量写成v = ,其中s和t都是Rq的元素;此外,我们将构成该向量第一部分的子向量称为s边的向量,将构成该向量第二部分的子向量称为t边的向量。
??我们将此概念扩展到适用的短整数解决问题(SIS)。回想一下SIS问题的定义如下:
??SISq,n,m,β问题:在一个n×m的随机矩阵中,其中元素皆为小于q的正整数,寻找一个最小非0向量v使得vA≡0modq,∣∣v∣∣2
??如果将A 矩阵看出两个矩阵的上下串联,例如A=∣∣∣∣∣A1A2∣∣∣∣∣,则原问题变为:?L:={(s,t):sA1+tA2≡0modq}
??找到短的(s,t)在此点阵中提供了SIS问题的解决方案。对于n = poly(m),?q?βmδ的一些正数δ,平均求解SIS问题与具有最近似因子 的?max{1,ββ∞/q}?0(βm)?最短独立向量问题一样困难;其中β∞是v的无穷范数的上界。
??SIS问题有一个“双”版本,称为LWE问题。通俗地说,让m,n,q为某个正整数,设格数为由σ参数化的χσ分布,例如:具有标准差为σ的离散高斯分布,均匀随机抽样A∈Zqn×m,s,b1∈Zpn?;样品e∈χσm计算b0=sA+emodq;决策LWE假设表明,给定两对(A,b0),生成b0,(A,b1),b1选自均匀分布,无法区分这两对.
??我们还利用了舍入学习(LWR)问题。这可以被看作是SIVP问题的一个变体,它具有四舍五入带来的确定性误差。我们正式记录LWR问题如下:
??LWRq,r,n,m:均匀从随机抽样矩阵和A∈Zqn×m和向量s∈Zqn,计算b=?sAmodq?r;决策的LWR问题是:给定u在Zqn中均匀随机采样的两对(A,b)和(A,?u?r),区分这两对。计算问题为:给定(A,b),发现s。
??假设带参数的LWRq,r,n,m是困难的,决策LWEq,r,n,m‘问题也是困难的。
??m≥log(2γ)log(q)?m‘?and??q≥γ(nmβp)
??对于一些γ≥1的。就我们所知,我们不知道计算的LWR和其他假设之间的规约。
??双峰高斯分布和拒绝抽样:
??定义了均值v和标准差为σ的n维高斯分布ρv,σ(x):=exp(2σ2?∥x?v∥2);当没有歧义时,我们把它简称为ρσ。定义了一个n维的离散高斯分布在Z上:χσ:=ρσ(Zn)ρσ(x),其中ρσ(Zn):=∑z∈Znρσ(z)是使函数变成概率分布[23]所需要的标度量.
??截断:对于一个离散高斯分布χσm和τ>1
??ρσ(Zm/στmB)≤2ρσ(Zm)(τexp(21?τ2))m
??其中B是中心单位球。令τ=λ2ln2为一维高斯将确保所有样品都以τσ为边界的概率大于1?2?τ。通常情况下,对于λ=128,可以使用$tau= 13.3;对于lambda = 256,可以使用tau= 18.8$
??拒绝抽样:设S为秘密矩阵,c为从均匀分布中抽样得到的向量,y为从离散矩阵中抽样得到的向量。考虑x = y + cS的分布,即,一个经过cS平移的高斯分布。在[28,13]中已经表明,每个样本x都泄漏了关于S的部分信息。用来密封泄漏的方法是拒绝采样,通过根据一定的标准概率接受输出,使输出分布独立于S.
??如果我们希望使输出分布与y相同,则有:
χcS,σ(x)χσ(x)≤M,
??这个不等式成立
M=exp(2σ22τσmaxc∣∣cS∣∣+maxc∣∣cS∣∣2)
??其中M为重复率。常数M决定了拒绝率,M越小,签名生成过程越高效。一种常见的选择是设置出一个常数σ=τmaxc∣∣cS∣∣(虽然仍然较大).:
??双峰高斯分布:非正式地说,双峰高斯分布是两个具有相同的σ和相同的绝对值,符号相反的高斯分布的和。由上例可知,x = y±cS的分布非常接近于双峰高斯分布。如果存在一个常数M,则可以使用拒收抽样从双峰高斯分布21χcS,σ(x)+21χ?cS,σ(x)得到一个新的高斯分布χσ,并且
21χcS,σ(x)+21χ?cS,σ(x)χσ(x)≤M
??这个不等式是成立的:
M=exp(2σ2maxc(∣∣cS∣∣2))
??同时,对于一个个体x = y±cS,接受它的概率为
ρ=1/(Mexp(?2σ2∣∣cS∣∣)cosh(σ2
??备注2。通常,在效率和存储大小之间存在权衡。对于离散高斯分布χσ的列线图,其输出x的熵有上界
H(x)≤≈klog(4.1σ)
??因此,使用霍夫曼编码,这样的向量可以有效地存储为大约k(log(σ)+2)位。因此,一个更小的报文会产生更小的签名σ,但同时也会降低拒收采样的效率。
3. 具有高斯抽样的模格签名
3.1 方案
??构造:设m、n、k为3个正整数,n = k + m,设S1∈Zm×kq为系数小且稀疏的矩阵。为简单起见,我们假设S1是抽样从某个边界为β的分布中采集的,这样∣∣S1∣∣∞≤β?q。在实践中可以使用一个方差小的离散高斯采样器,或均匀取样器在小的范围内。
??我们的密钥是一个矩阵S:=[pS1∣Im]∈Zq(m×n),它具有小的项。公钥是由一个矩阵A=[A1A2]同时SA = 0 mod q和A2是A的逆的mod q。同样,我们可以从Zqk×m均匀得采样到样本A1,然后设置A2=?pS1A1mod q。A1如果A2不是可逆的mod q,我们重取。SIS点阵定义为:
??$$mathcal {L}:={(u,v):u A_1+v A_2 =0 mod q},$$
??其中S是该栅格的短活板门基础。注意,上面的过程是SIS问题的标准构造,除了S1上有一个因子p。在下一小节中,我们将说明我们的构造与标准SIS问题之间的等价性.
??看一个k×m矩阵B:=A1(?A2)?1modq可能更方便。与B,晶格L可以解释为
??$$mathcal {L}:={(u,v):uB=v mod q},$$
??对于错误学习的基
P=[0IkqImB]
??这样就可以进行有效的抽样。
??签名:我们将哈希函数H作为一个随机的oracle,在Zpn上均匀输出,这允许我们从消息文摘中生成随机元素mp∈Zpn。我们写mp:=(up,vp),同时up∈Zpk和vp∈Zpm。
??下一步是从P:u1≡upmodp中采样一个向量(u1,v1)要做到这一点,我们可以简单地从一个离散高斯分布的χσk函数中采样一个向量r。然后计算u0=pr,u1=u0+up,u1满足v1=u1Bmodq,$(u_1,v_1)?是晶格中的一个向量,u_1≡u_p mod p$.
??另一种查看上述过程的方法是生成一个随机向量(r,rBmodq)在晶格中。根据定义,矩阵[Ik∣B]是L(P)的子格的一组基。此外,由于r是从一个离散的高斯分布采样,这个随机向量可以看作是一个GPV采样器L([Ik∣B])的输出r([Ik∣B])。如果参数σ大于平滑参数L([Ik∣B]),则向量r([Ik∣B])在L([Ik∣B])是均匀的,在Zn上是离散的高斯分布。然后我们取这个向量对q的模来得到精确的输出向量.
??由于v1在Zn上是离散高斯分布的,它将具有以p为模的随机系数,因此不满足全等条件。为了完成这个过程,我们需要对v1进行微调,使t侧也满足一致性条件:同时,我们不想破坏s边的同余条件。我们使用秘密基S=[pS1∣Im]来实现这个目标。令a=vp?v1modp,计算(u2,v2)=aS=(paS1,a).注意(u2,v2)≡(0,a)构造对modp,$ (u_2,v_2)$是晶格中的向量。
??最终的签名为(u,v)=(u1,v1)+(u2,v2),很容易看出(u,v)在∣∣v∣∣∞ u=u1+u2=u1≡upmodp ??以及 v=v1+v2≡v1+vp?v1≡vpmodp ??因此,(u,v)是我们方案的有效签名 ??如前所述,候选签名(u,v)泄漏关于密钥S的信息。要密封此泄漏,需要使用拒收采样技术。上述方案的效率很大程度上取决于拒绝签名的频率。作为一个概念的证明,我们将展示拒收抽样可以用来密封信息泄漏在这里。我们将在第4节中给出一个更有效的实例,它使用双峰高斯分布。 ??对u的拒收抽样。先文提到u=p(r+aS1)+up。由于p和up都是公开的,我们需要封住来自b:=r+aS1对S1的泄漏。还请回忆一下,所有r的分布方式为χσk。 ??在v上的拒收抽样,在t边,我们不需要拒收抽样。我们有v=v1+v2。首先v1=(pr+up)B,它没有链接到秘钥S1。其次,S2=(v1?vp)modp也没有链接到任何密钥. ??另一种说法是,拒绝抽样对t边来说是不需要的,因为事实上,与t边相对应的密钥实际上是Im。事实上,我们可以把v=v1+aS2写成S2=Im。在下一节中我们将看到,当一个秘密矩阵替代Im时,我们仍然需要使用拒收抽样来密封S2的泄漏。 ??尽管如此,如果∣∣v∣∣∞变得太大,导致了一个wrap-around mod q,我们确实需要重新启动。当这种情况发生时,mod q降低后,全等条件被打破. ??替代方案。在我们的构建中,我们选择做拒收抽样,这样∣∣v∣∣∞不会导致任何wrap-aroud。尽管有以下两种选择,我们还是选择了这种方法。首先,签署人可以发送一个助手来指示校验人发生wrap-around的系数。这可以看作是2012中基于Ding (R) LWE的密钥交换的一种和解方法。我们不采用这种解决方案,因为它会增加签名的大小。 ??其次,由于wrap-around发生的概率较低,我们可以基于模糊匹配让验证者接受签名:当t侧的大部分系数满足同余条件时接受签名。这种有前途的方法可能会削弱我们的安全,因为它使伪造更容易。出于保守目的,我们不考虑这种方法. ??有三个压缩源。首先,只要向量是l,验证者可以有效地只存储向量的、s边,而不是整个向量,即给定u,验证者可以重构v=uBmodq ??其次,验证者可以从b中重构u=pb+up,因为p和up都是已知的。所以只需要b来验证. ??最后,由于b在拒绝采样后遵循离散高斯分布,可以使用基于代码的压缩技术来减少b的空间需求。 ??最后的签名是一个k维离散高斯向量,允许霍夫曼编码。最终签名的大小为k(log(σ)+2)。 ??上述签名算法必须在统计上与三(up,vp,b),分布为Upk×Upm×χσk的高斯分布,其中Up为均匀模p,高斯分布为χσk高斯分布。在不知道密码匙的情况下,可以通过以下方式模拟这样一份文本: ??1. 从χσk中随机选择b ??2. 设u=pb+up,随机取upmodp,使∣∣u∣∣∞ ??备注3。我们正在做一个假设,经过实验验证,即step4生成一个vp≡uBmodqmodp,它的项都是均匀mod p ??对于公钥的安全性,很容易看出从公钥找到秘钥(或者仅仅是允许伪造的足够短的向量)的能力可以降低为解决SIS问题的能力。在本节中,我们主要关注伪造签名的困难。 ??为了量化伪造的难度,我们首先引入带截断的学习问题。 ??定义3 (LWTq,p,n,m)。让q,p,m,n是p共一撇到q的正整数,均匀随机抽样一个矩阵A∈Zqn×m?q乘以m和一个向量s∈zqn?,计算b = sA mod q mod p;决策LWT问题为:给定两对(A,b)和(A,[u]p)其中u在Zqn中均匀随机采样,区分这两对。计算问题为:给定(A,b),找到s。 ??如前所述,这个LWT问题可以看作是LWR问题的逆。这里我们展示了问题之间的简化。 ??引理1。选择一对(p,q)使得p和r≡p?1modq都在q的数量级上。那么,如果存在求解参数q的计算LWT的算法A?,对于给定参数为q,p,n,m的任意输入(A,b)∈Zqq×m×Zpm,存在另一种算法B,求解参数q,r, n, m, 的LWR,在参数为$ (A',B'),对A'从Z^n _q$中均匀随机取样。 ??我们在这里简述一下证明 ??证明。假设算法A?能够解决LWT问题,即给定(A,b)它找到一个晶格向量 ??- v = b mod p,并且 ??- v = tA mod q 对某些t。 ??然后,我们可以建立一个oracle,在输入(A,b)它找到u和t,这样 v+pu=tAmodq ??对一些∣∣u∣∣∞≤?2pq? ??给定LWR实例(A′,B′)算法B设A=pA′,?b=b′,?r=p?1?mod q;然后B通过调用A?输入(A,b).由于A′是均匀的,p与q是共素的,所以A在Zqn×m上也是均匀的。同时,由于∣∣b∣∣∞≤p, (A,b)将是A?的一个合法输入,因此,A?将找到u和t,使得b + pu = tA mod q,即 rb′+u=tA′modq和b′=?tA′modq?r ??因此,t是计算LWR问题的解。 ??现在我们准备对伪造的难度进行量化 ?? 定理1 (Unforgeability)。让B是一个公共密钥生成按我们的方案参数q, p, n, m。对于任何新的输入消息μ,如果敌人能够打造一个签名,不可忽视ρ概率,然后有一个算法B有相同的概率解决LWTq,p,k,m ??证明。首先,我们将哈希函数H建模为均匀输出在Zpn上的随机预言符。此外,伪造者被要求在一个他以前没有见过的消息上签名。因此,如果算法B能够以不可忽略的概率μ为每一个合法的输入对象伪造签名,那么一定是A能够伪造任何合法的mp=H(μ∣B)同时,从伪造者的角度来看,任何新的向modp向量看起来都像是一个合法的散列输出。 ??其次,我们声明B与随机一致地从Zpk×m中选择的矩阵不可区分。这是由于A与随机均匀地从Zpn×m中选取的矩阵不可区分。回忆B=A1(?A2)?1modq和A=[A1A2]。 ??因此,给定LWT实例(A',b'),伪造者无法区分A'与合法生成的公钥;它也不能区分b'和合法生成的公共消息摘要。结果,它将返回一个签名向量v,该向量将以概率ρ递进的方式通过验证测试。从v中很容易提取出LWT问题的解。 ??我们注意到,从伪造到LWR/LWT的降低如此之小,我们将需要一个相当大的p,按q的顺序,这使得该方案的效率较低。在下一节中,我们将看到,高效的实例化使用来自著名攻击的实际参数(这也是大多数实用的基于格的签名的设计原则)。为此,我们将选择一个小的p,允许有效的拒绝抽样。 ????strong unforgeability。(标准的)不可伪造性概念的一个微妙之处是,伪造者被要求签署以前从未签署过的消息。然而,强不可伪造性的概念要求攻击者不能在消息上伪造签名,即使给出了同一消息的一组签名。上述定理没有说明这一点。实际上,这里我们展示了一个修改,允许实现强大的不可伪造性。 ??对于给定的消息摘要mp,与该消息摘要相关的所有候选签名都是原始格与pZn+mp相交的短向量。因此,伪造的任务变成了在原始格中寻找一个满足长度要求和同余模p要求的短向量。这在[18]大致是还原到approx-cvp. ????现在,假设向攻击者提供了同一消息摘要上的一组签名,那么,攻击者在这个格子中找到另一个短向量(与没有这个列表相比)就变得更容易了,也就是说,在同一消息上生成一个新的签名。然而,我们注意到这些签名的任何线性组合都不太可能同时满足正确的模p同余条件。 ??通常,我们实现强不可伪造性的解决方案是在生成消息摘要时在散列中包含一个随机的“盐”;此盐将作为签名的一部分,并在验证期间使用。这确保了相同的消息摘要出现不止一次的可能性非常小(每个消息的概率(1=p)2n)。注意,这也是为基于GPV的签名[15]提供类似功能的相同技术。 ??然而,由于强不可铸造性模型有时对于实际应用(即,攻击者不需要伪造新的签名,因为它已经在同一消息上获得了它们的列表),我们在有效的实例化中忽略了这个salt,以最小化签名的大小。 ??在上一节中,我们提出了一个基于SIS/LWT的低效模格签名方案,该方案要求n≈m log(m)。即使我们使用环的版本,这个方案仍然有些低效,因为它需要n≈log(m) - m的减少直接来自环的使用。提高效率的一种自然方法是放宽对n≈log(m)的要求(这将使底层(ring) SIS问题更容易,因此我们将从最著名的攻击中获得参数)。 ??例如,我们可以把n简化为2m(在环化的情况下是2)。这使得A1是一个方阵,这就导致了另一个问题: pS1A1+ImA2=0modp ??当A1是方阵且可逆时,我们可以很容易地从A1和A2恢复S1 ??一个天真的补救方法是设置A2是私有的,因此我们将有一个秘密矩阵和[pS1∣A2]一个公共矩阵[A1Im]也满足上述方程没有暴露S1。这个看似合理的解决方案带来了另一个挑战:我们无法再对向量的t边进行微调,因为现在A2已经不再小了。如果我们做同样的微调,u2的系数会非常大,总是会导致q的wrap-around。 ??因此,上述问题的最终解决方案是拥有一个小型的私有A2。最终的关键生成是找到这样的A2和可逆S1,并设置A1=A2(pS1)?1modq。下面,我们将稍微改变符号:H:=A1,G:=A2和F:=S1 ??在下面,我们将对多项式环Rq=Zq[x]/(xN+1)进行处理。我们的方案也适用于其他环,例如Zq[x]/(xN?1),只是做了一些小小的修改。设f(x),g(x)和h(x)是Rq中的3个多项式,其中f(x)和g(x)系数很小;h(x)=p?1g(x)f?1(x)。我们用fgh表示多项式的向量形式。设F、G、H为由负循环旋转得到的矩阵。关于h的NTRU晶格被定义 Lh={(u,v)∈Rq2:uh=v} ??或者更确切地说,向量/矩阵形式: Lh={(u,v):uH=vmodq} ??那里存在一个公共基础P=[0INqINH]和秘密发生器[pF∣G]。我们还要求g(x)对Rp可逆,也就是g对p可逆。 ??该方案的其余部分几乎与上一节中介绍的方案相同,除了两个不同之处。 ??首先,我们使用双峰高斯分布来提高接受率。为了解决这个问题,我们设p = 2,使b=r±af的符号变化在对p作模后消失。 ??其次,我们使用[pF∣G]而不是[pS1∣Im]来执行微观调整。这一修改确实提出了另一个问题:在签字过程中t边的向量将包含关于G的信息。更精确地说,t边的向量将是v:=v1±ag,其中v1与Rq上的一致不可区分,a与ZpN上的一致不可区分。我们需要进行拒收采样来封闭g信息的泄漏。如[18]所示,拒收采样后,v的分布在计算上与均匀分布在(?2q+Bt;2q?Bt)表示一个公共参数Bt,该参数依赖于q、a的(均匀)分布以及g中的+1和- 1的数量。 ??为了避免混淆,我们将用Ms表示s边的拒收率,Mt表示t边,M表示总比率。 设计NTRU加密内容: class NtruCipher: N = None p = None q = None f_poly = None g_poly = None h_poly = None f_p_poly = None f_q_poly = None R_poly = None def __init__(self, N, p, q): self.N = N self.p = p self.q = q self.R_poly = Poly(x ** N + 1, x).set_domain(ZZ) log.info(”NTRU(N={},p={},q={}) initiated“.format(N, p, q)) def generate_random_keys(self): g_poly = random_poly(self.N) log.info(”g: {}“.format(g_poly)) log.info(”g coeffs: {}“.format(Counter(g_poly.coeffs()))) tries = 10 while tries > 0 and (self.h_poly is None): f_poly = random_poly(self.N) log.info(”f: {}“.format(f_poly)) log.info(”f coeffs: {}“.format(Counter(f_poly.coeffs()))) try: self.generate_public_key(f_poly, g_poly) except NotInvertible as ex: log.info(”Failed to invert f (tries left: {})“.format(tries)) log.debug(ex) tries -= 1 if self.h_poly is None: raise Exception(”Couldn't generate invertible f“) def generate_public_key(self, f_poly, g_poly): self.f_poly = 2 * f_poly + 1 self.g_poly = g_poly log.debug(”Trying to invert: {}“.format(self.f_poly)) self.f_p_poly = invert_poly(self.f_poly, self.R_poly, self.p) log.debug(”f_p ok!“) self.f_q_poly = invert_poly(self.f_poly, self.R_poly, self.q) log.debug(”f_q ok!“) log.info(”f_p: {}“.format(self.f_p_poly)) log.info(”f_q: {}“.format(self.f_q_poly)) log.debug(”f*f_p mod (x^n - 1): {}“.format(((self.f_poly * self.f_p_poly) % self.R_poly).trunc(self.p))) log.debug(”f*f_q mod (x^n - 1): {}“.format(((self.f_poly * self.f_q_poly) % self.R_poly).trunc(self.q))) p_f_q_poly = (self.p * self.f_q_poly).trunc(self.q) log.debug(”p_f_q: {}“.format(p_f_q_poly)) h_before_mod = (p_f_q_poly * self.g_poly).trunc(self.q) log.debug(”h_before_mod: {}“.format(h_before_mod)) self.h_poly = (2 * h_before_mod % self.R_poly).trunc(self.q) log.info(”h: {}“.format(self.h_poly)) def encrypt(self, msg_poly, rand_poly): log.info(”r: {}“.format(rand_poly)) log.info(”r coeffs: {}“.format(Counter(rand_poly.coeffs()))) log.info(”msg: {}“.format(msg_poly)) log.info(”h: {}“.format(self.h_poly)) return (((rand_poly * self.h_poly).trunc(self.q) + msg_poly) % self.R_poly).trunc(self.q) def decrypt(self, msg_poly): log.info(”f: {}“.format(self.f_poly)) log.info(”f_p: {}“.format(self.f_p_poly)) a_poly = ((self.f_poly * msg_poly) % self.R_poly).trunc(self.q) log.info(”a: {}“.format(a_poly)) b_poly = a_poly.trunc(self.p) return b_poly登录后复制 def Key_generation(N,p,q): f_raw=mathutils.random_poly(N).trunc(2) f_updated = p * f_raw + 1 modlist=np.zeros(N+1,int) modlist[0]=1 modlist[-1]=1 #print(modlist) mod = Poly(modlist, x).set_domain(ZZ) inv_f_updated = mathutils.invert_poly(f_updated, mod, q) #print(”f:{0}“.format(f_updated)) s=mathutils.random_poly(N).trunc(2) h = ((p * inv_f_updated * s)%mod).trunc(q) #print(s) #print(h) return (f_updated,(h,s))登录后复制 def encryption(N,p,q,pk,m): modlist = np.zeros(N + 1, int) modlist[0] = 1 modlist[-1] = 1 # print(modlist) mod = Poly(modlist, x).set_domain(ZZ) c = ((pk[0] * pk[1] + m) % mod).trunc(q) return cdef decryption(N,p,q,sk,c): modlist = np.zeros(N + 1, int) modlist[0] = 1 modlist[-1] = 1 # print(modlist) mod = Poly(modlist, x).set_domain(ZZ) m = ((sk * c) % mod).trunc(q).trunc(p) return m登录后复制 def homo_add(N,p,q,c1,c2): modlist = np.zeros(N + 1, int) modlist[0] = 1 modlist[-1] = 1 # print(modlist) mod = Poly(modlist, x).set_domain(ZZ) return ((c1+c2)%mod).trunc(q)def homo_mult(N,p,q,c1,c2): modlist = np.zeros(N + 1, int) modlist[0] = 1 modlist[-1] = 1 # print(modlist) mod = Poly(modlist, x).set_domain(ZZ) return ((c1*c2)%mod).trunc(q)def evaluate(N,p,q,sk1,sk2,c): modlist = np.zeros(N + 1, int) modlist[0] = 1 modlist[-1] = 1 # print(modlist) mod = Poly(modlist, x).set_domain(ZZ) m=((sk1*sk2*c)%mod).trunc(q).trunc(p) return m登录后复制 import sys sys.path.append('/home/aistudio/wy')import numpy as np# from ntru import mathutils# from sympy.abc import x# from sympy import ZZ, Polydef Key_generation(N,p,q): f_raw=mathutils.random_poly(N).trunc(2) f_updated = p * f_raw + 1 modlist=np.zeros(N+1,int) modlist[0]=1 modlist[-1]=1 #print(modlist) mod = Poly(modlist, x).set_domain(ZZ) inv_f_updated = mathutils.invert_poly(f_updated, mod, q) #print(”f:{0}“.format(f_updated)) s=mathutils.random_poly(N).trunc(2) h = ((p * inv_f_updated * s)%mod).trunc(q) #print(s) #print(h) return (f_updated,(h,s))def encryption(N,p,q,pk,m): modlist = np.zeros(N + 1, int) modlist[0] = 1 modlist[-1] = 1 # print(modlist) mod = Poly(modlist, x).set_domain(ZZ) c = ((pk[0] * pk[1] + m) % mod).trunc(q) return cdef decryption(N,p,q,sk,c): modlist = np.zeros(N + 1, int) modlist[0] = 1 modlist[-1] = 1 # print(modlist) mod = Poly(modlist, x).set_domain(ZZ) m = ((sk * c) % mod).trunc(q).trunc(p) return mdef homo_add(N,p,q,c1,c2): modlist = np.zeros(N + 1, int) modlist[0] = 1 modlist[-1] = 1 # print(modlist) mod = Poly(modlist, x).set_domain(ZZ) return ((c1+c2)%mod).trunc(q)def homo_mult(N,p,q,c1,c2): modlist = np.zeros(N + 1, int) modlist[0] = 1 modlist[-1] = 1 # print(modlist) mod = Poly(modlist, x).set_domain(ZZ) return ((c1*c2)%mod).trunc(q)def evaluate(N,p,q,sk1,sk2,c): modlist = np.zeros(N + 1, int) modlist[0] = 1 modlist[-1] = 1 # print(modlist) mod = Poly(modlist, x).set_domain(ZZ) m=((sk1*sk2*c)%mod).trunc(q).trunc(p) return mif __name__==”__main__“: N=32 p=32 q=10000723 '''因私有函数库,无法公开进行展示,此处仅对部分技术思路和实验结果进行讲解和展示。 (sk1,pk1)=Key_generation(N, p, q) #print(sk) #print(pk) m1 = Poly([0,1,0,1,1], x).set_domain(ZZ) c1=encryption(N,p,q,pk1,m1) print(”m1=“,m1) print(”m1加密结果:“,c1) m1_decrypted=decryption(N,p,q,sk1,c1) print(”c1解密结果:“,m1_decrypted) (sk2, pk2) = Key_generation(N, p, q) m2 = Poly([1,0,1,0,0], x).set_domain(ZZ) c2=encryption(N,p,q,pk2,m2) print(”m2=“,m2) print(”m2加密结果:“,c2) m2_decrypted=decryption(N,p,q,sk2,c2) print(”c2解密结果:“,m2_decrypted) #print(homo_add(5,2,97,c,c)) homo_c=homo_mult(N, p, q, c1, c2) print(”m1*m2同态乘结果:“,homo_c) homo_m=evaluate(N,p,q,sk1,sk2,homo_c) print(”m1*m2同态解密结果:“,homo_m) '''登录后复制 运行结果如下: m1= Poly(x**3 + x + 1, x, domain='ZZ')m1加密结果: Poly(3284343*x**31 + 2108998*x**30 + 3382527*x**29 - 2022312*x**28 + 1445430*x**27 - 4103553*x**26 + 2186932*x**25 - 2887823*x**24 + 1707515*x**23 - 1961609*x**22 - 4490402*x**21 - 488503*x**20 - 4820228*x**19 - 1419062*x**18 + 4663653*x**17 - 616473*x**16 - 308613*x**15 + 2530948*x**14 - 3788285*x**13 - 2906419*x**12 + 540120*x**11 + 4645349*x**10 - 869216*x**9 + 4873778*x**8 + 2887821*x**7 + 3266827*x**6 - 4884532*x**5 - 533436*x**4 - 2831953*x**3 + 2971347*x**2 + 4985141*x + 118432, x, domain='ZZ')c1解密结果: Poly(x**3 + x + 1, x, domain='ZZ')m2= Poly(x**4 + x**2, x, domain='ZZ')m2加密结果: Poly(633893*x**31 + 3141282*x**30 + 1806755*x**29 + 1074787*x**28 - 4339348*x**27 - 2038976*x**26 + 110016*x**25 - 2084644*x**24 + 941907*x**23 + 764676*x**22 - 1392117*x**21 + 4489722*x**20 + 4260836*x**19 - 4720594*x**18 - 4560990*x**17 + 4477931*x**16 + 91218*x**15 - 971510*x**14 - 2090340*x**13 + 2928978*x**12 - 2315957*x**11 + 2963446*x**10 - 4442306*x**9 + 358189*x**8 - 393412*x**7 - 4145723*x**6 + 4063545*x**5 + 2604736*x**4 + 2841033*x**3 - 2552980*x**2 + 2633358*x + 2589579, x, domain='ZZ')c2解密结果: Poly(x**4 + x**2, x, domain='ZZ')m1*m2同态乘结果: Poly(28479*x**31 - 1950186*x**30 + 4662772*x**29 + 2378350*x**28 + 3222463*x**27 - 3270780*x**26 - 3911557*x**25 + 2268506*x**24 - 4929247*x**23 - 4053986*x**22 + 2746968*x**21 + 2696063*x**20 + 2839513*x**19 - 2438726*x**18 + 1562762*x**17 - 1295123*x**16 + 345153*x**15 - 728221*x**14 - 1510487*x**13 - 1473839*x**12 + 2215256*x**11 + 350121*x**10 - 648692*x**9 - 2116576*x**8 + 1054796*x**7 - 3767592*x**6 + 1611484*x**5 + 474441*x**4 + 961208*x**3 - 953814*x**2 + 2593332*x - 1408044, x, domain='ZZ')m1*m2同态解密结果: Poly(x**7 + 2*x**5 + x**4 + x**3 + x**2, x, domain='ZZ')登录后复制3.2 拒绝抽样
3.3 签名压缩
3.4 模拟记录
3.5 安全性
4. 一个使用NTRU格的实际实例化
4.1 方案实施
4.2 秘钥生成
4.3 加解密
4.4 同态运算
5. 最终代码及结果
In [4]
福利游戏
相关文章
更多-
- 香港置地2022年置慧杯:商业综合体能耗预测基线
- 时间:2025-07-16
-
- 上半年新能源轿车及SUV销量榜出炉:吉利、特斯拉夺冠
- 时间:2025-07-16
-
- 报告显示 Cozy舒适系Steam游戏近年极速增长趋势
- 时间:2025-07-16
-
- 【校园AI Day-AI workshop】交通信号标志图像分类
- 时间:2025-07-16
-
- 『2022语言与智能技术竞赛』段落检索比赛基线
- 时间:2025-07-16
-
- 小米汽车上周销量细节曝光:小米YU7 Max交付860辆
- 时间:2025-07-16
-
- 花呗额度65000算高吗?算什么水平?花呗额度范围一览
- 时间:2025-07-16
-
- 日本最大委托游戏开发商新财报暗示 Switch 2今秋大作发力
- 时间:2025-07-16
大家都在玩
热门话题
大家都在看
更多-
- 一汽奥迪公开反对汽车用消费级芯片!汽车正变成快消品吗 网友专家博主们吵翻
- 时间:2025-07-16
-
- 比特币合约交易规则详解:掌握策略
- 时间:2025-07-16
-
- 改写光合作用!麻省理工科学家让植物加速生长
- 时间:2025-07-16
-
- 央视曝App小程序成隐私刺客:13万份体检报告险泄露
- 时间:2025-07-16
-
- WBTC什么时候上交易所
- 时间:2025-07-16
-
- 京东回应外卖取消超时20分钟免单:外卖准时率已大幅提升
- 时间:2025-07-16
-
- 比亚迪出海舰队再加一!第七艘滚装船“郑州号”今日正式交付
- 时间:2025-07-16
-
- Pi Network杠杆能赚钱吗
- 时间:2025-07-16