同态加密BGV与BFV方案对比与梳理

Revisiting Homomorphic Encryption Schemes for Finite Fields

摘要

这篇文章主要回顾了BGV和BFV方案,展示其区别,并优化了BGV,BFV的RNS实现(BFV的加密,BFV乘法,BFV噪声管理,BFV解密),并在PALISADE上面对其进行了效率测试。

在优化之前,同样的明文模数空间下,BGV的噪声增加要比BFV小,而优化之后,BFV比BGV稍好一点。

优化后的结果上来说,在明文空间模数较大或适中的情况下,BGV效率比较高,在模数比较小的情况下,BFV的效率高。

引言

BFV和BGV的明文空间都是 Z t Z_t Zt,模数为 Q Q Q

BGV方案将消息放在最小字节位(Least Significant Bit)上,使用模数替换技术来保持噪声为一个常量。具体来说,每次乘法之后都会将模数 Q Q Q缩小一个噪声 B B B的大小 Q / B Q/B Q/B,而每次乘法后变为平方的噪声 B 2 B^2 B2也被缩小了一个噪声的大小变为 B B B,因此噪声可以保持为一个常量。

BFV方案将消息放在最大字节位(Most Significant Bit)上,所有的密文在做乘法后都会缩小 Q / t Q/t Q/t。模数 Q Q Q保持不变,而噪声逐渐增加,噪声增加的量和BGV方案中 Q Q Q缩小的量近似。

之前Costache和Smart做了一个噪声对比的测试,结果显示:在 t t t较大时,BGV的噪声增加量要比BFV小。然而他们没有从理论上和实验上比较计算上的开销。

因此这篇文章主要贡献就是优化BGV和BFV方案,使得两者之间的差距缩小,并且从理论和实验上比较两者的效率差异。

修改BFV方案

作者提出了两个方法来改善BFV方案,第一种针对加密,第二种针对乘法操作

  • 加密优化:BFV的密文可以表示为 c = ( b , a ) \boldsymbol{c}=(\boldsymbol{b},\boldsymbol{a}) c=(b,a),其中 b = a ⋅ s + e + Δ m \boldsymbol{b}=\boldsymbol{a} \cdot \boldsymbol{s}+\boldsymbol{e}+\Delta \boldsymbol{m} b=as+e+Δm Δ = ⌊ Q / t ⌋ \Delta = \lfloor Q/t \rfloor Δ=Q/t。BFV的主要开销就来自 Q / t Q/t Q/t ⌊ Q / t ⌋ \lfloor Q/t \rfloor Q/t之间的差距。
    r t ( Q ) = Q − t Δ r_t(Q) = Q- t\Delta rt(Q)=QtΔ,只要令 r t ( Q ) ≈ 0 r_t(Q)\approx 0 rt(Q)0,那么就可以减少BFV的噪声增加,是的BFV的噪声近似于BGV,甚至比BGV更好。所以在修改中,令 b = a ⋅ s + e + ⌈ Q t m ⌋ \boldsymbol{b}=\boldsymbol{a}\cdot \boldsymbol{s} + \boldsymbol{e} + \lceil \frac{Q}{t} \boldsymbol{m} \rfloor b=as+e+tQm
  • 乘法优化:BFV的乘法时最耗时的步骤,因为它需要将两个密文 c 1 \boldsymbol{c}_1 c1 c 2 \boldsymbol{c}_2 c2做相乘,然后再将乘积进行 t / Q t/Q t/Q scale。那这就需要将两个密文的模数 Q Q Q扩展到 Q P QP QP,其中 P P P是一个比 Q Q Q足够大的数。做一次乘法就需要进行一次 Q P QP QP下的NTT,一次Scale down Q / t Q/t Q/t,最后将结果从模 P P P中转到模 Q Q Q中。本文作者提出了一个优化的乘法,能够做到 P ≈ Q P\approx Q PQ,节省了模数扩张以及NTT的开销。
    主要的思想是对 c 2 \boldsymbol{c}_2 c2进行模数替换, c 2 ′   m o d   P ≡ c 2   m o d   Q \boldsymbol{c}_2'\bmod P \equiv \boldsymbol{c}_2\bmod Q c2modPc2modQ。对 c 1 , c 2 ′ \boldsymbol{c}_1,\boldsymbol{c}_2' c1,c2在乘法之后对其进行 t / P t/P t/P scale。那么进行完scale之后的密文就已经在 Q Q Q内了,就无需进行从 P P P Q Q Q的rescale了。用一个 c 2 \boldsymbol{c}_2 c2上的较小的rescale来代替乘积上的较大的rescale。

BFV优化方法

  • Lazy rescale:在CKKS中,有一种lazy relinearization方法,在涉及对多个密文做相乘并聚合的时候,可以先做乘法,再做加法聚合,最后在聚合的密文上进行重线性化,可以减少重线性化的次数。同样的再BFV中可以做lazy rescale,延缓 t / Q t/Q t/Q缩放的时间,对于乘法之后做加法的密文,先进行加法再进行rescale。
  • RNS:对于BFV的RNS优化有两种方法,一种是Bajard-Eynard-Hasan-Zucca(BEHZ)[5]算法,基于整数模算法以及Montgomery reduction算法。第二种是Halevi-Polyakov-Shoup(HPS)算法[21],基于整数模算法以及浮点数近似算法。HPS算法中的很大的一个制约在于他需要用到高精度(双精度/四精度)的浮点数,当CRT的模数取到47~58比特时候需要双精度的浮点数来近似了,更大的模数就需要四精度的浮点数了。
    于是他们就提出了一种 digit decomposition技术,来加入到HPS解密步骤中,只用双精度的浮点数来支持任意大小的CRT模数。
  • 他们还应用了[24]中提出的混合密钥转换(hybrid key switching)应用到了BFV RNS优化中。并说明了在乘法中需要用到的辅助的模数可以被混合密钥转换重利用。

BGV优化及可用性提升

这篇文章用了Gentry-Halevi-Smart(GHS)(HE-Lib)算法来作为实现BGV的基础。GHS虽然涉及一些RNS操作,但在key switching和部分modulus switching操作中仍然是用到了高精度的整数算法。但在这篇文章中,他们把所有高精度的整数都用了RNS来代替(采用了CRT decomposition技术),来达到了更好的效率。

效率比较结果

作者在PALISADE中做了BGV和BFV的实现,结果是:

  • 之前BGV在大明文模数下噪声增长比较小,他们的结果是现在BFV和BGV在大明文模数下表现近似,稍好于BGV。

  • BFV的效率在小明文模数下较好,BGV的效率在适中或者较大的模数情况下表现较好。

  • 他们的BFV实现比之前最好的实现在深层(乘法)电路的评估上快了4倍。

背景知识

分圆多项式: R = Z [ X ] / ( X N + 1 ) \mathcal{R}=\mathbb{Z}[X]/(X^N+1) R=Z[X]/(XN+1) R Q = R / Q R \mathcal{R}_Q=\mathcal{R}/Q\mathcal{R} RQ=R/QR Z Q = ( − Q / 2 , Q / 2 ) ∩ Z \mathbb{Z}_Q=(-Q/2,Q/2)\cap\mathbb{Z} ZQ=(Q/2,Q/2)Z

初始BGV方案

BGV方案主要涉及到一个modulus switching技术,可以将模 Q Q Q的密文 c t ct ct,转化为模 Q ′ Q' Q的密文 c t ′ ct' ct来保证噪声大小为常数。所以在BGV方案中,要执行 L L L层的乘法电路,就要选取 L + 1 L+1 L+1 个模数 Q 0 ∣ Q 1 ∣ … ∣ Q L = Q Q_{0}\left|Q_{1}\right| \ldots \mid Q_{L}=Q Q0Q1QL=Q t t t Q L Q_L QL互素。

公钥: p k = ( [ a ⋅ s + t e ] Q L , − a ) ∈ R Q L 2 \mathrm{pk}=\left([\boldsymbol{a} \cdot \boldsymbol{s}+t \boldsymbol{e}]_{Q_{L}},-\boldsymbol{a}\right) \in \mathcal{R}_{Q_{L}}^{2} pk=([as+te]QL,a)RQL2

加密: c t = ( [ [ m ] t + u ⋅ p k 0 + t e 0 ] Q L , [ u ⋅ p k 1 + t e 1 ] Q L ) = ( c 0 , c 1 ) \mathrm{ct}=\left(\left[[\boldsymbol{m}]_{t}+\boldsymbol{u} \cdot \mathbf{p} \mathbf{k}_{0}+t \boldsymbol{e}_{0}\right]_{Q_{L}},\left[\boldsymbol{u} \cdot \mathbf{p} \mathbf{k}_{1}+t \boldsymbol{e}_{1}\right]_{Q_{L}}\right)=\left( \boldsymbol{c}_0,\boldsymbol{c}_1 \right) ct=([[m]t+upk0+te0]QL,[upk1+te1]QL)=(c0,c1)

可以简单点看作 c t ≈ ( [ m ] t + a ⋅ s , − a ) \mathrm{ct}\approx \left([\boldsymbol{m}]_t+\boldsymbol{a}\cdot \boldsymbol{s}, -\boldsymbol{a}\right) ct([m]t+as,a)

解密: c 0 + c 1 ⋅ s = [ m ] t + t ( u ⋅ e + e 1 ⋅ s + e 0 ) = [ m ] t + t v   m o d   Q L \boldsymbol{c}_{0}+\boldsymbol{c}_{1} \cdot \boldsymbol{s}=[\boldsymbol{m}]_{t}+t\left(\boldsymbol{u} \cdot \boldsymbol{e}+\boldsymbol{e}_{1} \cdot \boldsymbol{s}+\boldsymbol{e}_{0}\right)=[\boldsymbol{m}]_{t}+t \boldsymbol{v} \bmod Q_{L} c0+c1s=[m]t+t(ue+e1s+e0)=[m]t+tvmodQL

m = [ [ c 0 + c 1 ⋅ s ] Q L ] t m = \left[\left[\boldsymbol{c}_{0}+\boldsymbol{c}_{1} \cdot \boldsymbol{s}\right]_{Q_L}\right]_t m=[[c0+c1s]QL]t

噪声要求 ∥ t v ∥ ∞ < Q / 2 → ∥ v ∥ ∞ < Q 2 t − 1 2 \|tv\|_{\infty}<Q/2\to\|v\|_{\infty} < \frac{Q}{2t}-\frac{1}{2} tv<Q/2v<2tQ21

加法: c 0 + c 0 ′ + ( c 1 + c 1 ′ ) ⋅ s = [ m + m ′ ] t + t ( v + v ′ + u )   m o d   Q i \boldsymbol{c}_{0}+\boldsymbol{c}_{0}^{\prime}+\left(\boldsymbol{c}_{1}+\boldsymbol{c}_{1}^{\prime}\right) \cdot \boldsymbol{s}=\left[\boldsymbol{m}+\boldsymbol{m}^{\prime}\right]_{t}+t\left(\boldsymbol{v}+\boldsymbol{v}^{\prime}+\boldsymbol{u}\right) \bmod Q_{i} c0+c0+(c1+c1)s=[m+m]t+t(v+v+u)modQi

加密密文: c t a d d = ( [ c 0 + c 0 ′ ] Q i , [ c 1 + c 1 ′ ] Q i ) \mathrm{ct}_{\mathrm{add}}=\left(\left[\boldsymbol{c}_{0}+\boldsymbol{c}_{0}^{\prime}\right]_{Q_{i}},\left[\boldsymbol{c}_{1}+\boldsymbol{c}_{1}^{\prime}\right]_{Q_{i}}\right) ctadd=([c0+c0]Qi,[c1+c1]Qi)

加法后噪声: ∥ v ∥ ∞ + ∥ v ′ ∥ ∞ + 1 \|v\|_{\infty}+\|v'\|_{\infty}+1 v+v+1

乘法: ( c 0 + c 1 ⋅ s ) ⋅ ( c 0 ′ + c 1 ′ ⋅ s ) = [ m ⋅ m ′ ] t + t ( [ m ] t ⋅ v ′ + v ⋅ [ m ′ ] t + t v ⋅ v ′ + r m ) = [ m ⋅ m ′ ] t + t v m u l t \left(\boldsymbol{c}_{0}+\boldsymbol{c}_{1} \cdot \boldsymbol{s}\right) \cdot\left(\boldsymbol{c}_{0}^{\prime}+\boldsymbol{c}_{1}^{\prime} \cdot \boldsymbol{s}\right)=\left[\boldsymbol{m} \cdot \boldsymbol{m}^{\prime}\right]_{t}+t\left([\boldsymbol{m}]_{t} \cdot \boldsymbol{v}^{\prime}+\boldsymbol{v} \cdot\left[\boldsymbol{m}^{\prime}\right]_{t}+t \boldsymbol{v} \cdot \boldsymbol{v}^{\prime}+r_{m}\right)=[\boldsymbol{m}\cdot \boldsymbol{m}']_t + t \boldsymbol{v}_{mult} (c0+c1s)(c0+c1s)=[mm]t+t([m]tv+v[m]t+tvv+rm)=[mm]t+tvmult

乘法密文: c t m u l t = ( [ c 0 ⋅ c 0 ′ ] Q i , [ c 0 ⋅ c 1 ′ + c 1 ⋅ c 0 ′ ] Q i , [ c 1 ⋅ c 1 ′ ] Q i ) ∈ R Q i 3 \mathrm{ct}_{\mathrm{mult}}=\left(\left[\boldsymbol{c}_{0} \cdot \boldsymbol{c}_{0}^{\prime}\right]_{Q_{i}},\left[\boldsymbol{c}_{0} \cdot \boldsymbol{c}_{1}^{\prime}+\boldsymbol{c}_{1} \cdot \boldsymbol{c}_{0}^{\prime}\right]_{Q_{i}},\left[\boldsymbol{c}_{1} \cdot \boldsymbol{c}_{1}^{\prime}\right]_{Q_{i}}\right) \in \mathcal{R}_{Q_{i}}^{3} ctmult=([c0c0]Qi,[c0c1+c1c0]Qi,[c1c1]Qi)RQi3

乘法后噪声变为: ∥ v mult  ∥ ∞ = ∥ [ m ] t ⋅ v ′ + v ⋅ [ m ′ ] t + t v ⋅ v ′ + r m ∥ ∞ ≤ δ R t 2 ( 2 ∥ v ∥ ∞ ∥ v ′ ∥ ∞ + ∥ v ∥ ∞ + ∥ v ′ ∥ ∞ + 1 ) \begin{aligned} \left\|\boldsymbol{v}_{\text {mult }}\right\|_{\infty} &=\left\|[\boldsymbol{m}]_{t} \cdot \boldsymbol{v}^{\prime}+\boldsymbol{v} \cdot\left[\boldsymbol{m}^{\prime}\right]_{t}+t \boldsymbol{v} \cdot \boldsymbol{v}^{\prime}+\boldsymbol{r}_{m}\right\|_{\infty} \\ & \leq \frac{\delta_{\mathcal{R}} t}{2}\left(2\|\boldsymbol{v}\|_{\infty}\left\|\boldsymbol{v}^{\prime}\right\|_{\infty}+\|\boldsymbol{v}\|_{\infty}+\left\|\boldsymbol{v}^{\prime}\right\|_{\infty}+1\right) \end{aligned} vmult =[m]tv+v[m]t+tvv+rm2δRt(2vv+v+v+1)

模数替换(缩减):

本文的定义如下:要将 Q j Q_j Qj下的密文 c t ct ct替换为 Q i Q_i Qi下的密文 c t ′ ct' ct。前提是 Q i ≡ Q j ≡ 1   m o d   t Q_i \equiv Q_j \equiv 1\bmod t QiQj1modt

在BGV的论文中,是这样表述的:令 c t ′ ct' ct为距离 ( Q i / Q j ) ⋅ c t (Q_i/Q_j)\cdot ct (Qi/Qj)ct最近的元素,使得 c t ′ ≡ c t   m o d   t ct'\equiv ct \bmod t ctctmodt

本文中的意思是一样的,但通过不同的方法表述出来:

δ = ( t [ − c 0 / t ] Q j / Q i , t [ − c 1 / t ] Q j / Q i ) ∈ R 2 \boldsymbol{\delta}=\left(t\left[-\boldsymbol{c}_{0} / t\right]_{Q_{j} / Q_{i}}, t\left[-\boldsymbol{c}_{1} / t\right]_{Q_{j} / Q_{i}}\right) \in \mathcal{R}^{2} δ=(t[c0/t]Qj/Qi,t[c1/t]Qj/Qi)R2

c t ′ = Q i Q j ⋅ ( c 0 + δ 0 , c 1 + δ 1 )   m o d   Q i \mathrm{ct}^{\prime}=\frac{Q_{i}}{Q_{j}} \cdot\left(\boldsymbol{c}_{0}+\boldsymbol{\delta}_{0}, \boldsymbol{c}_{1}+\boldsymbol{\delta}_{1}\right) \bmod Q_{i} ct=QjQi(c0+δ0,c1+δ1)modQi

GHS优化

因为在初始的BGV方案中,模数替换要求所有的 Q i Q_i Qi满足 Q i ≡ 1   m o d   t Q_i \equiv 1 \bmod t Qi1modt,减少了模数的选取范围,所以在GHS中,通过直接加密 [ Q L m ] t [Q_L m]_t [QLm]t的形式,模数替换可以直接替换为 [ Q i m ] t [Q_im]_t [Qim]t,而不需要满足 Q i ≡ 1   m o d   t Q_i \equiv 1 \bmod t Qi1modt的条件。这样做的坏处就在于两个不同层之间的密文加法需要进行层同步后才可进行。

初始BFV方案

BFV方案其实是吧modulus switching的方法隐式的包含在了乘法中。

公钥: p k = ( [ a ⋅ s + e ] Q , − a ) ∈ R Q 2 \mathrm{pk}=\left([\boldsymbol{a} \cdot \boldsymbol{s}+\boldsymbol{e}]_{Q},-\boldsymbol{a}\right) \in \mathcal{R}_{Q}^{2} pk=([as+e]Q,a)RQ2

加密:  ct  = ( [ Δ [ m ] t + u ⋅ p k 0 + e 0 ] Q , [ u ⋅ p k 1 + e 1 ] Q ) \text { ct }=\left(\left[\Delta[\boldsymbol{m}]_{t}+\boldsymbol{u} \cdot \mathbf{p} \mathbf{k}_{0}+\boldsymbol{e}_{0}\right]_{Q},\left[\boldsymbol{u} \cdot \mathbf{p} \mathbf{k}_{1}+\boldsymbol{e}_{1}\right]_{Q}\right)  ct =([Δ[m]t+upk0+e0]Q,[upk1+e1]Q)

可以看做:  ct  ≈ ( Δ [ m ] t + a s , − a ) , Δ = ⌊ Q / t ⌋ \text { ct }\approx\left(\Delta[\boldsymbol{m}]_{t}+\boldsymbol{as},-\boldsymbol{a}\right),\Delta = \lfloor Q/t\rfloor  ct (Δ[m]t+as,a),Δ=Q/t

解密: c 0 + c 1 ⋅ s = Δ [ m ] t + u ⋅ e + e 1 ⋅ s + e 0 = Δ [ m ] t + v fresh    m o d   Q \boldsymbol{c}_{0}+\boldsymbol{c}_{1} \cdot \boldsymbol{s}=\Delta[\boldsymbol{m}]_{t}+\boldsymbol{u} \cdot \boldsymbol{e}+\boldsymbol{e}_{1} \cdot \boldsymbol{s}+\boldsymbol{e}_{0}=\Delta[\boldsymbol{m}]_{t}+\boldsymbol{v}_{\text {fresh }} \bmod Q c0+c1s=Δ[m]t+ue+e1s+e0=Δ[m]t+vfresh modQ

m ′ = ⌊ t Q [ c 0 + c 1 ⋅ s ] Q ] \boldsymbol{m}^{\prime}=\left\lfloor\frac{t}{Q}\left[\boldsymbol{c}_{0}+\boldsymbol{c}_{1} \cdot \boldsymbol{s}\right]_{Q}\right] m=Qt[c0+c1s]Q]

噪声要求: ∥ v ∥ ∞ < Q 2 t − r t ( Q ) 2 \|v\|_{\infty}<\frac{Q}{2t}-\frac{r_t(Q)}{2} v<2tQ2rt(Q)

加法: c 0 + c 0 ′ + ( c 1 + c 1 ′ ) ⋅ s = Δ [ m + m ′ ] t + v + v ′ − r t ( Q ) u   m o d   Q \boldsymbol{c}_{0}+\boldsymbol{c}_{0}^{\prime}+\left(\boldsymbol{c}_{1}+\boldsymbol{c}_{1}^{\prime}\right) \cdot \boldsymbol{s}=\Delta\left[\boldsymbol{m}+\boldsymbol{m}^{\prime}\right]_{t}+\boldsymbol{v}+\boldsymbol{v}^{\prime}-r_{t}(Q) \boldsymbol{u} \bmod Q c0+c0+(c1+c1)s=Δ[m+m]t+v+vrt(Q)umodQ

加法密文: c t a d d = ( [ c 0 + c 0 ′ ] Q , [ c 1 + c 1 ′ ] Q ) \mathrm{ct}_{\mathrm{add}}=\left(\left[\boldsymbol{c}_{0}+\boldsymbol{c}_{0}^{\prime}\right]_{Q},\left[\boldsymbol{c}_{1}+\boldsymbol{c}_{1}^{\prime}\right]_{Q}\right) ctadd=([c0+c0]Q,[c1+c1]Q)

加法噪声: ∥ v a d d ∥ ∞ = ∥ v + v ′ + r t ( Q ) u ∥ ∞ ≤ ∥ v ∥ ∞ + ∥ v ′ ∥ ∞ + r t ( Q ) \left\|\boldsymbol{v}_{\mathrm{add}}\right\|_{\infty}=\left\|\boldsymbol{v}+\boldsymbol{v}^{\prime}+r_{t}(Q) \boldsymbol{u}\right\|_{\infty} \leq\|\boldsymbol{v}\|_{\infty}+\left\|\boldsymbol{v}^{\prime}\right\|_{\infty}+r_{t}(Q) vadd=v+v+rt(Q)uv+v+rt(Q)

乘法: ( c 0 + c 1 ⋅ s ) ⋅ ( c 0 + c 1 ⋅ s ) = ( Δ [ m ] t + v + Q k ) ⋅ ( Δ [ m ′ ] t + v ′ + Q k ′ ) = Q t Δ [ m ⋅ m ′ ] t + Q t v tensor  + Q 2 t k tensor  \begin{aligned} \left(\boldsymbol{c}_{0}+\boldsymbol{c}_{1} \cdot \boldsymbol{s}\right) \cdot\left(\boldsymbol{c}_{0}+\boldsymbol{c}_{1} \cdot \boldsymbol{s}\right) &=\left(\Delta[\boldsymbol{m}]_{t}+\boldsymbol{v}+Q \boldsymbol{k}\right) \cdot\left(\Delta\left[\boldsymbol{m}^{\prime}\right]_{t}+\boldsymbol{v}^{\prime}+Q \boldsymbol{k}^{\prime}\right) \\ &=\frac{Q}{t} \Delta\left[\boldsymbol{m} \cdot \boldsymbol{m}^{\prime}\right]_{t}+\frac{Q}{t} \boldsymbol{v}_{\text {tensor }}+\frac{Q^{2}}{t} \boldsymbol{k}_{\text {tensor }} \end{aligned} (c0+c1s)(c0+c1s)=(Δ[m]t+v+Qk)(Δ[m]t+v+Qk)=tQΔ[mm]t+tQvtensor +tQ2ktensor 

乘法密文: c t t e n s o r = ( c 0 ⋅ c 0 ′ , c 0 ⋅ c 1 ′ + c 1 ⋅ c 0 ′ , c 1 ⋅ c 1 ′ ) ∈ R 3 \mathrm{ct}_{\mathrm{tensor}}=\left(\boldsymbol{c}_{0} \cdot \boldsymbol{c}_{0}^{\prime}, \boldsymbol{c}_{0} \cdot \boldsymbol{c}_{1}^{\prime}+\boldsymbol{c}_{1} \cdot \boldsymbol{c}_{0}^{\prime}, \boldsymbol{c}_{1} \cdot \boldsymbol{c}_{1}^{\prime}\right) \in \mathcal{R}^{3} cttensor=(c0c0,c0c1+c1c0,c1c1)R3

c t s c a l e = [ [ t Q c t tensor  ⌋ ] Q ∈ R Q 3 \mathrm{ct}_{\mathrm{scale}}=\left[\left[\frac{t}{Q} \mathrm{ct}_{\text {tensor }}\right\rfloor\right]_{Q} \in \mathcal{R}_{Q}^{3} ctscale=[[Qtcttensor ]QRQ3

乘法噪声: t Q ( c tensor  0 + c tensor  1 ⋅ s + c tensor  2 ⋅ s 2 ) = Δ [ m ⋅ m ′ ] + v tensor  + Q k tensor  \frac{t}{Q}\left(c_{\text {tensor }_{0}}+c_{\text {tensor }_{1}} \cdot s+c_{\text {tensor }_{2}} \cdot s^{2}\right)=\Delta\left[m \cdot m^{\prime}\right]+v_{\text {tensor }}+Q k_{\text {tensor }} Qt(ctensor 0+ctensor 1s+ctensor 2s2)=Δ[mm]+vtensor +Qktensor 

c t s c a l e 0 + c t s c a l e 1 ⋅ s + c t s c a l e 2 ⋅ s 2 = Δ [ m ⋅ m ′ ] + v tensor  + v r   m o d   Q \mathrm{ct}_{\mathrm{scale}_{0}}+\mathrm{ct}_{\mathrm{scale}_{1}} \cdot \boldsymbol{s}+\mathrm{ct}_{\mathrm{scale}_{2}} \cdot \boldsymbol{s}^{2}=\Delta\left[\boldsymbol{m} \cdot \boldsymbol{m}^{\prime}\right]+\boldsymbol{v}_{\text {tensor }}+\boldsymbol{v}_{\mathrm{r}} \bmod Q ctscale0+ctscale1s+ctscale2s2=Δ[mm]+vtensor +vrmodQ

其中 ∥ v r ∥ ∞ ≤ ( 1 + δ R B k e y + δ R 2 B k e y 2 ) / 2 \left\|\boldsymbol{v}_{r}\right\|_{\infty} \leq\left(1+\delta_{\mathcal{R}} B_{\mathrm{key}}+\delta_{\mathcal{R}}^{2} B_{\mathrm{key}}^{2}\right) / 2 vr(1+δRBkey+δR2Bkey2)/2 v mult  = v tensor  + v r \boldsymbol{v}_{\text {mult }}=\boldsymbol{v}_{\text {tensor }}+\boldsymbol{v}_{r} vmult =vtensor +vr.

∥ v mult ⁡ ∥ ∞ ≤ δ R t 2 ( 2 ∥ v ∥ ∞ ∥ v ′ ∥ ∞ Q + ( 4 + δ R B k e y ) ( ∥ v ∥ ∞ + ∥ v ′ ∥ ∞ ) + r t ( Q ) ( δ R B k e y + 5 ) ) + 1 + δ R B k e y + δ R 2 B k e y 2 2 \begin{aligned} \left\|\boldsymbol{v}_{\operatorname{mult}}\right\|_{\infty} \leq & \frac{\delta_{\mathcal{R}} t}{2}\left(\frac{2\|\boldsymbol{v}\|_{\infty}\left\|\boldsymbol{v}^{\prime}\right\|_{\infty}}{Q}+\left(4+\delta_{\mathcal{R}} B_{\mathrm{key}}\right)\left(\|\boldsymbol{v}\|_{\infty}+\left\|\boldsymbol{v}^{\prime}\right\|_{\infty}\right)\right.\\ &\left.+r_{t}(Q)\left(\delta_{\mathcal{R}} B_{\mathrm{key}}+5\right)\right)+\frac{1+\delta_{\mathcal{R}} B_{\mathrm{key}}+\delta_{\mathcal{R}}^{2} B_{\mathrm{key}}^{2}}{2} \end{aligned} vmult2δRt(Q2vv+(4+δRBkey)(v+v)+rt(Q)(δRBkey+5))+21+δRBkey+δR2Bkey2

RNS表示

中国剩余定理将 Z Q \mathbb{Z}_Q ZQ中的一个元素拆分为一组更小空间中的数(比如64位以内的数),来使得计算机可以快速的计算。这样的表示方法叫做剩余数系统(Residue-Number-System RNS)。

同样的,一个多项式环 R Q \mathcal{R}_Q RQ中元素也可以用他的剩余数来表示,具体来说,取一组互素的数 q i q_i qi使得 Q = q 0 ⋯ q L Q=q_0\cdots q_L Q=q0qL,将多项式环的系数全都从 Z Q \mathbb{Z}_Q ZQ映射到 Z q i \mathbb{Z}_{q_i} Zqi中,然后进行NTT来做 R Q \mathcal{R}_Q RQ上元素的快速乘法操作。

在BGV方案中,通常取 Q L = q 0 ⋯ q L Q_L=q_0\cdots q_L QL=q0qL Q i = q 0 ⋯ q i Q_i=q_0\cdots q_i Qi=q0qi,其中 q i = 1   m o d   2 N , 1 ≤ i ≤ L q_i = 1\bmod 2N,1\le i\le L qi=1mod2N,1iL。在BFV中,取 Q = q 0 ⋯ q k Q=q_0\cdots q_k Q=q0qk Q i = q 0 ⋯ q i Q_i=q_0\cdots q_i Qi=q0qi,其中 q i = 1   m o d   2 N , 1 ≤ i ≤ k q_i = 1\bmod 2N,1\le i\le k qi=1mod2N,1ik。这里用了两种不同的方法来对BGV和BFV的模数进行选取,是因为在BFV中,模数都是选取到软件/硬件能表达的最大位数(64/53)位。而在BGV方案中,模数的选取与每次需要减少的噪声大小有关,因此也与需要执行的算数电路有关。在HE-Lib中,有一个动态的噪声预估方法可以解除这种限制。因此,BGV的可用性是受到限制的。但在本文中,对BGV的噪声进行了统计地预估,增加了可用性。

在使用BFV方案乘法的时候,需要用到一个switchbase操作,就是将 a ∈ R Q \boldsymbol{a}\in\mathcal{R}_Q aRQ的RNS表达转换为 [ a ] Q   m o d   P [\boldsymbol{a}]_Q\bmod P [a]QmodP这样的形式。

按照原本中国剩余定理的表达,需要计算
( ∑ i = 1 k ( a   m o d   q i ) ( ( Q q i ) − 1   m o d   q i ) Q q i )   m o d   Q \left( \sum_{i=1}^{k} (\boldsymbol{a}\bmod q_i)\left( \left(\frac{Q}{q_i}\right)^{-1}\bmod q_i \right) \frac{Q}{q_i} \right) \ mod \ Q (i=1k(amodqi)((qiQ)1modqi)qiQ) mod Q
而在RNS表达中时存储的 [ a ] q i [\boldsymbol{a}]_{q_i} [a]qi,所以一种快速的方法来计算的话是
 FastBaseExtension  ( a , Q , P ) = ∑ i = 1 k [ a ( Q q i ) − 1 ] q i Q q i   m o d   p j \text { FastBaseExtension }(\boldsymbol{a}, Q, P)=\sum_{i=1}^{k}\left[\boldsymbol{a}\left(\frac{Q}{q_{i}}\right)^{-1}\right]_{q_{i}} \frac{Q}{q_{i}} \bmod p_{j}  FastBaseExtension (a,Q,P)=i=1k[a(qiQ)1]qiqiQmodpj
但这样子得到的不是 [ a ] Q   m o d   P [\boldsymbol{a}]_Q\bmod P [a]QmodP而是 [ a ] Q + u Q   m o d   P [\boldsymbol{a}]_Q+\boldsymbol{u}Q\bmod P [a]Q+uQmodP.

于是需要通过[21]中的floating-point instruction技术来得到 u \boldsymbol{u} u u = ⌊ ∑ i = 1 k [ a ( Q q i ) − 1 ] q i 1 q i ⌉ \boldsymbol{u}=\left\lfloor\sum_{i=1}^{k}\left[\boldsymbol{a}\left(\frac{Q}{q_{i}}\right)^{-1}\right]_{q_{i}} \frac{1}{q_{i}}\right\rceil u=i=1k[a(qiQ)1]qiqi1或者蒙哥马利约化来去掉Q。

RNS混合密钥替换

密钥替换(key switching)将一个由 s A \boldsymbol{s}_{A} sA解密的密文 c t = ( c 0 , c 1 ) ∈ R Q 2 \mathrm{ct}=\left(\boldsymbol{c}_{0}, \boldsymbol{c}_{1}\right) \in \mathcal{R}_{Q}^{2} ct=(c0,c1)RQ2转换为一个可以由 s B s_{B} sB解密的密文 c t ′ = ( c 0 ′ , c 1 ′ ) ∈ R Q 2 \mathrm{ct}^{\prime}=\left(\boldsymbol{c}_{0}^{\prime}, \boldsymbol{c}_{1}^{\prime}\right) \in \mathcal{R}_{Q}^{2} ct=(c0,c1)RQ2,两者解密后得到的消息相同。

在BV[9]中有一种进行key switching的方法,后来[5]将其扩展到了RNS中,这种方法是将密文中的多项式环中元素进行digit decomposition。但是这种方法需要平方次的NTTs转换,且有很大的噪声。在GHS[20]中,提出了一种噪声更小,只需要线性个NTT转换的方案,但这种方法需要将 N N N翻倍或者将 Q Q Q缩小2的次数。GHS还提出了一种混合方法,折中结合BV和GHS的方法来达到最好的效果。

优化BFV方案

注意到之前BGV和BFV的噪声对比中:

BGV:

加法: ∥ v a d d ∥ ∞ = ∥ v ∥ ∞ + ∥ v ′ ∥ ∞ + 1 \|\boldsymbol{v}_{add}\|_{\infty}=\|\boldsymbol{v}\|_{\infty}+\|\boldsymbol{v}'\|_{\infty}+1 vadd=v+v+1

乘法: ∥ v mult  ∥ ∞ = ∥ [ m ] t ⋅ v ′ + v ⋅ [ m ′ ] t + t v ⋅ v ′ + r m ∥ ∞ ≤ δ R t 2 ( 2 ∥ v ∥ ∞ ∥ v ′ ∥ ∞ + ∥ v ∥ ∞ + ∥ v ′ ∥ ∞ + 1 ) \begin{aligned} \left\|\boldsymbol{v}_{\text {mult }}\right\|_{\infty} &=\left\|[\boldsymbol{m}]_{t} \cdot \boldsymbol{v}^{\prime}+\boldsymbol{v} \cdot\left[\boldsymbol{m}^{\prime}\right]_{t}+t \boldsymbol{v} \cdot \boldsymbol{v}^{\prime}+\boldsymbol{r}_{m}\right\|_{\infty} \\ & \leq \frac{\delta_{\mathcal{R}} t}{2}\left(2\|\boldsymbol{v}\|_{\infty}\left\|\boldsymbol{v}^{\prime}\right\|_{\infty}+\|\boldsymbol{v}\|_{\infty}+\left\|\boldsymbol{v}^{\prime}\right\|_{\infty}+1\right) \end{aligned} vmult =[m]tv+v[m]t+tvv+rm2δRt(2vv+v+v+1)

BFV:

加法: ∥ v add ∥ ∞ ≤ ∥ v ∥ ∞ + ∥ v ′ ∥ ∞ + r t ( Q ) \left\|\boldsymbol{v}_{\text {add}}\right\|_{\infty}\leq\|\boldsymbol{v}\|_{\infty}+\left\|\boldsymbol{v}^{\prime}\right\|_{\infty}+r_{t}(Q) vaddv+v+rt(Q)

乘法: ∥ v mult ⁡ ∥ ∞ ≤ δ R t 2 ( 2 ∥ v ∥ ∞ ∥ v ′ ∥ ∞ Q + ( 4 + δ R B k e y ) ( ∥ v ∥ ∞ + ∥ v ′ ∥ ∞ ) + r t ( Q ) ( δ R B k e y + 5 ) ) + 1 + δ R B k e y + δ R 2 B k e y 2 2 \begin{aligned} \left\|\boldsymbol{v}_{\operatorname{mult}}\right\|_{\infty} \leq & \frac{\delta_{\mathcal{R}} t}{2}\left(\frac{2\|\boldsymbol{v}\|_{\infty}\left\|\boldsymbol{v}^{\prime}\right\|_{\infty}}{Q}+\left(4+\delta_{\mathcal{R}} B_{\mathrm{key}}\right)\left(\|\boldsymbol{v}\|_{\infty}+\left\|\boldsymbol{v}^{\prime}\right\|_{\infty}\right)\right.\\ &\left.+r_{t}(Q)\left(\delta_{\mathcal{R}} B_{\mathrm{key}}+5\right)\right)+\frac{1+\delta_{\mathcal{R}} B_{\mathrm{key}}+\delta_{\mathcal{R}}^{2} B_{\mathrm{key}}^{2}}{2} \end{aligned} vmult2δRt(Q2vv+(4+δRBkey)(v+v)+rt(Q)(δRBkey+5))+21+δRBkey+δR2Bkey2

BFV相比BGV的噪声项多了 r t ( Q ) r_t(Q) rt(Q)这一项,也就造成了BFV的噪声增长会比BGV要快,这篇文章说明了 r t ( Q ) r_t(Q) rt(Q)是完全可以避免的。

噪声减少

现在回顾一下BFV的乘法噪声,令两个要进行相乘的密文的噪声都是 V V V B k e y = 1 B_{key}=1 Bkey=1,乘法的噪声就大约为:
δ R t ( ( 5 + δ R ) V + r t ( Q ) 2 ( δ R + 5 ) ) + δ R 2 2 ≈ δ R 2 t ( V + r t ( Q ) 2 ) \delta_{\mathcal{R}} t\left(\left(5+\delta_{\mathcal{R}}\right) V+\frac{r_{t}(Q)}{2}\left(\delta_{\mathcal{R}}+5\right)\right)+\frac{\delta_{\mathcal{R}}^{2}}{2} \approx \delta_{\mathcal{R}}^{2} t\left(V+\frac{r_{t}(Q)}{2}\right) δRt((5+δR)V+2rt(Q)(δR+5))+2δR2δR2t(V+2rt(Q))
当乘法继续进行的时候 V V V就比 r t ( Q ) ≈ t / 2 r_t(Q)\approx t/2 rt(Q)t/2要大很多,此时 r t ( Q ) r_t(Q) rt(Q)带来的噪声影响不大。但考虑到第一次乘法,两个新加密的密文的噪声为 c 0 + c 1 ⋅ s = Δ [ m ] t + u ⋅ e + e 1 ⋅ s + e 0 = Δ [ m ] t + v fresh    m o d   Q \boldsymbol{c}_{0}+\boldsymbol{c}_{1} \cdot \boldsymbol{s}=\Delta[\boldsymbol{m}]_{t}+\boldsymbol{u} \cdot \boldsymbol{e}+\boldsymbol{e}_{1} \cdot \boldsymbol{s}+\boldsymbol{e}_{0}=\Delta[\boldsymbol{m}]_{t}+\boldsymbol{v}_{\text {fresh }} \bmod Q c0+c1s=Δ[m]t+ue+e1s+e0=Δ[m]t+vfresh modQ, ∥ v fresh ∥ ∞ ≤ B err  ( 2 δ R B key  + 1 ) ≈ 2 δ R B err  \|\boldsymbol{v}_{\text{fresh}}\|_{\infty} \le B_{\text {err }}\left(2 \delta_{\mathcal{R}} B_{\text {key }}+1\right) \approx 2 \delta_{\mathcal{R}} B_{\text {err }} vfreshBerr (2δRBkey +1)2δRBerr 。根据同态加密标准,噪声分布都是 σ err = 3.2 \sigma_{\text{err}}=3.2 σerr=3.2的高斯分布, B err = 3.2 × 6 B_{\text{err}}=3.2\times6 Berr=3.2×6 δ R ≤ N \delta_R\le \sqrt{N} δRN ,所以 V init = 2 × 6 × 3.2 × 2 N < 77 N V_{\text{init}}=2\times 6 \times 3.2 \times 2 \sqrt{N} < 77 \sqrt{N} Vinit=2×6×3.2×2N <77N ,而 N N N一般不超过 2 16 2^{16} 216,因此初始噪声最多也就14比特左右。但如果取 t > 2 16 + 1 t>2^{16}+1 t>216+1,那么 r t ( Q ) / 2 > 2 14 r_t(Q)/2>2^{14} rt(Q)/2>214就成了噪声的主要组成了。如果取 t = 2 60 t=2^{60} t=260,那么初始噪声会比BGV要大44比特。

减小这个噪声项 r t ( Q ) r_t(Q) rt(Q)的方法也很简单,如同BGV里面一样,取 q i = 1   m o d   t q_i =1\bmod t qi=1modt,那么 r t ( Q ) = 1 r_t(Q)=1 rt(Q)=1,但这样做会减少模数选取的范围,所以不做考虑,另一种方法是不断地选取 Q Q Q直到 r t ( Q ) < N r_t(Q)< \sqrt{N} rt(Q)<N ,但其实有更加自然的方法。

在加密的时候,不选择使用 Δ [ m ] t \Delta [\boldsymbol{m}]_t Δ[m]t,而是 ⌊ Q [ m ] t / t ⌉ \lfloor Q[\boldsymbol{m}]_t/t\rceil Q[m]t/t的形式,那这样做的话,噪声就变了:
KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ \left[\frac{t}…
其中 ⌊ Q [ m ] t / t ⌉ = Q [ m ] t / t + ε \left\lfloor Q[m]_{t} / t\right\rceil=Q[m]_{t} / t+ \boldsymbol{\varepsilon} Q[m]t/t=Q[m]t/t+ε. ∥ ε ∥ ∞ ≤ 1 / 2 \|\boldsymbol{\varepsilon}\|_{\infty} \le 1/2 ε1/2.

t Q ∥ v + ε ∥ ∞ < 1 2 \frac{t}{Q}\|\boldsymbol{v}+\boldsymbol{\varepsilon}\|_{\infty}<\frac{1}{2} Qtv+ε<21时解密正确,也就是 ∥ v ∥ ∞ < Q 2 t − 1 2 \|\boldsymbol{v}\|_{\infty}<\frac{Q}{2t}-\frac{1}{2} v<2tQ21,此时的解密噪声就和BGV一样了。

注意:这个形式的密文加密可以直接用RNS表示,因为
⌊ Q [ m ] t t ⌉ = Q [ m ] t − [ Q m ] t t = − [ Q m ] t t   m o d   Q \left\lfloor\frac{Q[\boldsymbol{m}]_{t}}{t}\right\rceil=\frac{Q[\boldsymbol{m}]_{t}-[Q \boldsymbol{m}]_{t}}{t}=-\frac{[Q \boldsymbol{m}]_{t}}{t} \bmod Q tQ[m]t=tQ[m]t[Qm]t=t[Qm]tmodQ

考虑一下修改后方案的加法噪声:
c 0 + c 1 ⋅ s + c 0 ′ + c 1 ′ ⋅ s = Q t ( [ m ] t + [ m ′ ] t ) + v + v ′ + ε + ε ′ = Q t ( [ m + m ′ ] t + t u ) + v + v ′ + ε + ε ′ = Q t [ m + m ′ ] t + v + v ′ + ε + ε ′   m o d   Q \begin{aligned} \boldsymbol{c}_{0}+\boldsymbol{c}_{1} \cdot \boldsymbol{s}+\boldsymbol{c}_{0}^{\prime}+\boldsymbol{c}_{1}^{\prime} \cdot \boldsymbol{s} &=\frac{Q}{t}\left([\boldsymbol{m}]_{t}+\left[\boldsymbol{m}^{\prime}\right]_{t}\right)+\boldsymbol{v}+\boldsymbol{v}^{\prime}+\boldsymbol{\varepsilon}+\boldsymbol{\varepsilon}^{\prime} \\ &=\frac{Q}{t}\left(\left[\boldsymbol{m}+\boldsymbol{m}^{\prime}\right]_{t}+t \boldsymbol{u}\right)+\boldsymbol{v}+\boldsymbol{v}^{\prime}+\boldsymbol{\varepsilon}+\boldsymbol{\varepsilon}^{\prime} \\ &=\frac{Q}{t}\left[\boldsymbol{m}+\boldsymbol{m}^{\prime}\right]_{t}+\boldsymbol{v}+\boldsymbol{v}^{\prime}+\boldsymbol{\varepsilon}+\boldsymbol{\varepsilon}^{\prime} \bmod Q \end{aligned} c0+c1s+c0+c1s=tQ([m]t+[m]t)+v+v+ε+ε=tQ([m+m]t+tu)+v+v+ε+ε=tQ[m+m]t+v+v+ε+εmodQ
此时加法噪声的bound为:

∥ v new-add ∥ ∞ ≤ ∥ v ∥ ∞ + ∥ v ′ ∥ ∞ + 1 \left\|\boldsymbol{v}_{\text {new-add}}\right\|_{\infty} \leq\|\boldsymbol{v}\|_{\infty}+\left\|\boldsymbol{v}^{\prime}\right\|_{\infty}+1 vnew-addv+v+1

加法噪声也和BGV一样了。

考虑乘法:

( c 0 + c 1 ⋅ s ) ⋅ ( c 0 ′ + c 1 ′ ⋅ s ) = ( Q t [ m ] t + v ~ + k Q ) ⋅ ( Q t [ m ′ ] t + v ~ ′ + k ′ Q ) = Q 2 t 2 [ m ⋅ m ′ ] t + Q t v new-tensor  + Q 2 t k new-tensor  v new-tensor  = [ m ] t ⋅ v ~ ′ + [ m ′ ] t ⋅ v ~ + t Q v ~ ⋅ v ~ ′ + t ( v ~ ⋅ k ′ + v ~ ′ ⋅ k ) k new-tensor  = [ m ] t ⋅ k ′ + [ m ′ ] t ⋅ k + t k ⋅ k ′ + r m \begin{array}{c} \left(\boldsymbol{c}_{0}+\boldsymbol{c}_{1} \cdot \boldsymbol{s}\right) \cdot\left(\boldsymbol{c}_{0}^{\prime}+\boldsymbol{c}_{1}^{\prime} \cdot \boldsymbol{s}\right)=\left(\frac{Q}{t}[\boldsymbol{m}]_{t}+\tilde{\boldsymbol{v}}+\boldsymbol{k} Q\right) \cdot\left(\frac{Q}{t}\left[\boldsymbol{m}^{\prime}\right]_{t}+\tilde{\boldsymbol{v}}^{\prime}+\boldsymbol{k}^{\prime} Q\right) \\ =\frac{Q^{2}}{t^{2}}\left[\boldsymbol{m} \cdot \boldsymbol{m}^{\prime}\right]_{t}+\frac{Q}{t} \boldsymbol{v}_{\text {new-tensor }}+\frac{Q^{2}}{t} \boldsymbol{k}_{\text {new-tensor }} \\ \boldsymbol{v}_{\text {new-tensor }}=[\boldsymbol{m}]_{t} \cdot \tilde{\boldsymbol{v}}^{\prime}+\left[\boldsymbol{m}^{\prime}\right]_{t} \cdot \tilde{\boldsymbol{v}}+\frac{t}{Q} \tilde{\boldsymbol{v}} \cdot \tilde{\boldsymbol{v}}^{\prime}+t\left(\tilde{\boldsymbol{v}} \cdot \boldsymbol{k}^{\prime}+\tilde{\boldsymbol{v}}^{\prime} \cdot \boldsymbol{k}\right) \\ \boldsymbol{k}_{\text {new-tensor }}=[\boldsymbol{m}]_{t} \cdot \boldsymbol{k}^{\prime}+\left[\boldsymbol{m}^{\prime}\right]_{t} \cdot \boldsymbol{k}+t \boldsymbol{k} \cdot \boldsymbol{k}^{\prime}+\boldsymbol{r}_{m} \end{array} (c0+c1s)(c0+c1s)=(tQ[m]t+v~+kQ)(tQ[m]t+v~+kQ)=t2Q2[mm]t+tQvnew-tensor +tQ2knew-tensor vnew-tensor =[m]tv~+[m]tv~+Qtv~v~+t(v~k+v~k)knew-tensor =[m]tk+[m]tk+tkk+rm

那么乘法噪声的bound就是:
∥ v new-mult  ∥ ∞ ≤ δ R t 2 ( 2 ∥ v ~ ∥ ∞ ∥ v ~ ′ ∥ ∞ Q + ( 4 + δ R B k e y ) ( ∥ v ~ ∥ ∞ + ∥ v ~ ′ ∥ ∞ ) ) + 1 + δ R B k e y + δ R 2 B k e y 2 2 \begin{aligned} \left\|\boldsymbol{v}_{\text {new-mult }}\right\|_{\infty} \leq & \frac{\delta_{\mathcal{R}} t}{2}\left(\frac{2\|\tilde{\boldsymbol{v}}\|_{\infty}\left\|\tilde{\boldsymbol{v}}^{\prime}\right\|_{\infty}}{Q}+\left(4+\delta_{\mathcal{R}} B_{\mathrm{key}}\right)\left(\|\tilde{\boldsymbol{v}}\|_{\infty}+\left\|\tilde{\boldsymbol{v}}^{\prime}\right\|_{\infty}\right)\right) \\ &+\frac{1+\delta_{\mathcal{R}} B_{\mathrm{key}}+\delta_{\mathcal{R}}^{2} B_{\mathrm{key}}^{2}}{2} \end{aligned} vnew-mult 2δRt(Q2v~v~+(4+δRBkey)(v~+v~))+21+δRBkey+δR2Bkey2
后面可以证明这样的噪声和BGV里面的是近似的。

在GHS中有一种对于BGV的初始噪声减少手段对于BFV也是有用的,初始时选取一个比 Q Q Q大的模数 Q p = Q ⋅ p Q_p=Q\cdot p Qp=Qp,然后加密完成直接执行scale down/modulus switching:  ct  scale  = ⌊ 1 p ct ⌉   m o d   Q \text { ct }_{\text {scale }}=\left\lfloor\frac{1}{p} \text {ct}\right\rceil \bmod Q  ct scale =p1ctmodQ

scale之后的噪声大小为 ∥ v s c a l e ∥ ∞ ≤ ∥ v ∥ ∞ p + 1 2 p + 1 + δ R B k e y 2 ≈ δ R 2 \left\|\boldsymbol{v}_{\mathbf{s c a l e}}\right\|_{\infty} \leq \frac{\|\boldsymbol{v}\|_{\infty}}{p}+\frac{1}{2 p}+\frac{1+\delta_{\mathcal{R}} B_{\mathrm{key}}}{2}\approx \frac{\delta_R}{2} vscalepv+2p1+21+δRBkey2δR。这样的大小要小于原始加密的噪声,可以作为一种降低初始噪声的手段。

改良乘法实现

缩小模数扩张 Q P QP QP:

在BGV里面,乘法可以直接在模 Q Q Q中实现。然而在BFV中,乘法因为要进行scale down,不能进行取模,因此需要扩大模数。具体来说,取一个新的RNS模数 P = p 1 ⋯ p k ′ P=p_1\cdots p_{k'} P=p1pk使得 ct ⋅ ct ′ \text{ct}\cdot \text{ct}' ctct不超过 P Q PQ PQ的范围,所以在实践中,一般取 k ′ = k + 1 k'=k+1 k=k+1。来回顾一下原本BFV的乘法:
 Expand: ct  ∈ R Q 2  and  c t ′ ∈ R Q 2 → c t ∈ R Q P 2  and  c t ′ ∈ R Q P 2 ▹ ct ⁡ ( s ) = Δ [ m ] t + v + Q k (   m o d   R Q P ) ▹ c t ′ ( s ) = Δ [ m ′ ] t + v ′ + Q k ′ (   m o d   R Q P )  Tensor: ct  tensor  = ( c 0 ⋅ c 0 ′ , c 0 ⋅ c 1 ′ + c 1 ⋅ c 0 ′ , c 1 ⋅ c 1 ′ ) ∈ R Q P 3 : ▹ c t tensor  ( s ) = Q t Δ [ m ⋅ m ′ ] t + Q t v tensor  + Q 2 t k tensor  (   m o d   R Q P )  ScaleDown:  c t scale  = ⌊ t Q c t tensor  ⌉ ∈ R P 3 ▹  ct  scale  ( s ) = Δ [ m ⋅ m ′ ] t + v tensor  + Q k tensor  + v r (   m o d   R P )  SwitchBasis:  c t s c a l e ∈ R P 3 → c t scale  ∈ R Q 3 : ▹  ct  scale  ( s ) = Δ [ m ⋅ m ′ ] t + v tensor  + v r (   m o d   R Q ) \begin{array}{l} \text { Expand: ct } \in \mathcal{R}_{Q}^{2} \text { and } \mathrm{ct}^{\prime} \in \mathcal{R}_{Q}^{2} \rightarrow \mathrm{ct} \in \mathcal{R}_{Q P}^{2} \text { and } \mathrm{ct}^{\prime} \in \mathcal{R}_{Q P}^{2}\\ \triangleright \operatorname{ct}(s)=\Delta[\boldsymbol{m}]_{t}+\boldsymbol{v}+Q \boldsymbol{k}\left(\bmod \mathcal{R}_{Q P}\right)\\ \triangleright \mathrm{ct}^{\prime}(\boldsymbol{s})=\Delta\left[\boldsymbol{m}^{\prime}\right]_{t}+\boldsymbol{v}^{\prime}+Q \boldsymbol{k}^{\prime}\left(\bmod \mathcal{R}_{Q P}\right)\\ \text { Tensor: ct }_{\text {tensor }}=\left(\boldsymbol{c}_{0} \cdot \boldsymbol{c}_{0}^{\prime}, \boldsymbol{c}_{0} \cdot \boldsymbol{c}_{1}^{\prime}+\boldsymbol{c}_{1} \cdot \boldsymbol{c}_{0}^{\prime}, \boldsymbol{c}_{1} \cdot \boldsymbol{c}_{1}^{\prime}\right) \in \mathcal{R}_{Q P}^{3}: \\ \triangleright \mathrm{ct}_{\text {tensor }}(\boldsymbol{s})=\frac{Q}{t} \Delta\left[\boldsymbol{m} \cdot \boldsymbol{m}^{\prime}\right]_{t}+\frac{Q}{t} \boldsymbol{v}_{\text {tensor }}+\frac{Q^{2}}{t} \boldsymbol{k}_{\text {tensor }}\left(\bmod \mathcal{R}_{Q P}\right)\\ \text { ScaleDown: } \mathrm{ct}_{\text {scale }}=\left\lfloor\frac{t}{Q} \mathrm{ct}_{\text {tensor }}\right\rceil \in \mathcal{R}_{P}^{3}\\ \triangleright \text { ct }_{\text {scale }}(s)=\Delta\left[\boldsymbol{m} \cdot \boldsymbol{m}^{\prime}\right]_{t}+\boldsymbol{v}_{\text {tensor }}+Q \boldsymbol{k}_{\text {tensor }}+\boldsymbol{v}_{r}\left(\bmod \mathcal{R}_{P}\right) \\ \text { SwitchBasis: } \mathrm{ct}_{\mathrm{scale}} \in \mathcal{R}_{P}^{3} \rightarrow \mathrm{ct}_{\text {scale }} \in \mathcal{R}_{Q}^{3}: \\ \triangleright \text { ct }_{\text {scale }}(\boldsymbol{s})=\Delta\left[\boldsymbol{m} \cdot \boldsymbol{m}^{\prime}\right]_{t}+\boldsymbol{v}_{\text {tensor }}+\boldsymbol{v}_{r}\left(\bmod \mathcal{R}_{Q}\right) \end{array}  Expand: ct RQ2 and ctRQ2ctRQP2 and ctRQP2ct(s)=Δ[m]t+v+Qk(modRQP)ct(s)=Δ[m]t+v+Qk(modRQP) Tensor: ct tensor =(c0c0,c0c1+c1c0,c1c1)RQP3:cttensor (s)=tQΔ[mm]t+tQvtensor +tQ2ktensor (modRQP) ScaleDown: ctscale =Qtcttensor RP3 ct scale (s)=Δ[mm]t+vtensor +Qktensor +vr(modRP) SwitchBasis: ctscaleRP3ctscale RQ3: ct scale (s)=Δ[mm]t+vtensor +vr(modRQ)
改良方法:对于 c t ∈ R Q 2 , c t ′ ∈ R Q 2 \mathrm{ct} \in \mathcal{R}_{Q}^{2},\mathrm{ct}^{\prime} \in \mathcal{R}_{Q}^{2} ctRQ2,ctRQ2,对其中一个进行modulus switching,变为 R P \mathcal{R}_P RP中,通过一系列的分析,说明了 P ≈ Q P\approx Q PQ就可以满足条件。看一下新的BFV乘法:
 ModSwitch:  c t ∈ R Q 2 → c t ^ ∈ R P 2  Expand:  c ^ t ∈ R P 2 → c t ^ ∈ R Q P 2  and  c t ′ ∈ R Q 2 → c t ′ ∈ R Q P 2 ▹ ct ^ ( s ) = P t [ m ] t + P Q v ~ + P k + ε round  (   m o d   R Q P ) ▹ ct ⁡ ′ ( s ) = Q t [ m ′ ] t + v ~ ′ + Q k ′ (   m o d   R Q P )  Tensor:  c t ^ tensor  = ( c 0 ^ ⋅ c 0 ′ , c 0 ^ ⋅ c 1 ′ + c 1 ^ ⋅ c 0 ′ , c 1 ^ ⋅ c 1 ′ ) ∈ R Q P 3 : ▹  ct  tensor  ( s ) = Q P t 2 [ m ⋅ m ′ ] t + P t v ^ tensor  + Q P t k ^ tensor  (   m o d   R Q P )  ScaleDown: ct  scale  = ⌊ t P c t ^ tensor  ⌉ ∈ R Q 3 ▹ ct scale ( s ) = Q t [ m ⋅ m ′ ] t + v ^ tensor + v r (   m o d   R Q ) \begin{aligned} &\text { ModSwitch: } \mathrm{ct} \in \mathcal{R}_{Q}^{2} \rightarrow \hat{\mathrm{ct}} \in \mathcal{R}_{P}^{2}\\ &\text { Expand: } \hat{\mathrm{c}} \mathrm{t} \in \mathcal{R}_{P}^{2} \rightarrow \hat{\mathrm{c} \mathrm{t}} \in \mathcal{R}_{Q P}^{2} \text { and } \mathrm{ct}^{\prime} \in \mathcal{R}_{Q}^{2} \rightarrow \mathrm{ct}^{\prime} \in \mathcal{R}_{Q P}^{2}\\ &\triangleright \hat{\text {ct}}(s)=\frac{P}{t}[\boldsymbol{m}]_{t}+\frac{P}{Q} \tilde{\boldsymbol{v}}+P \boldsymbol{k}+\varepsilon_{\text {round }}\left(\bmod \mathcal{R}_{Q P}\right)\\ &\triangleright \operatorname{ct}^{\prime}(s)=\frac{Q}{t}\left[\boldsymbol{m}^{\prime}\right]_{t}+\tilde{\boldsymbol{v}}^{\prime}+Q \boldsymbol{k}^{\prime}\left(\bmod \mathcal{R}_{Q P}\right)\\ &\text { Tensor: } \hat{\mathrm{ct}}_{\text {tensor }}=\left(\hat{\boldsymbol{c}_{0}} \cdot \boldsymbol{c}_{0}^{\prime}, \hat{\boldsymbol{c}_{0}} \cdot \boldsymbol{c}_{1}^{\prime}+\hat{\boldsymbol{c}_{1}} \cdot \boldsymbol{c}_{0}^{\prime}, \hat{\boldsymbol{c}_{1}} \cdot \boldsymbol{c}_{1}^{\prime}\right) \in \mathcal{R}_{Q P}^{3}: \\ &\triangleright \text { ct }_{\text {tensor }}(\boldsymbol{s})=\frac{Q P}{t^{2}}\left[\boldsymbol{m} \cdot \boldsymbol{m}^{\prime}\right]_{t}+\frac{P}{t} \hat{\boldsymbol{v}}_{\text {tensor }}+\frac{Q P}{t} \hat{\boldsymbol{k}}_{\text {tensor }}\left(\bmod \mathcal{R}_{Q P}\right)\\ &\text { ScaleDown: ct }_{\text {scale }}=\left\lfloor\frac{t}{P} \hat{\mathrm{ct}}_{\text {tensor }}\right\rceil \in \mathcal{R}_{Q}^{3} \\ &\triangleright \text {ct}_{\text {scale}}(s)=\frac{Q}{t}\left[m \cdot m^{\prime}\right]_{t}+\hat{v}_{\text {tensor}}+v_{r}\left(\bmod \mathcal{R}_{Q}\right) \end{aligned}  ModSwitch: ctRQ2ct^RP2 Expand: c^tRP2ct^RQP2 and ctRQ2ctRQP2ct^(s)=tP[m]t+QPv~+Pk+εround (modRQP)ct(s)=tQ[m]t+v~+Qk(modRQP) Tensor: ct^tensor =(c0^c0,c0^c1+c1^c0,c1^c1)RQP3: ct tensor (s)=t2QP[mm]t+tPv^tensor +tQPk^tensor (modRQP) ScaleDown: ct scale =Ptct^tensor RQ3ctscale(s)=tQ[mm]t+v^tensor+vr(modRQ)
考虑一下做basis extension的次数:在初始的BFV乘法中,Expand中有4步,ScaleDown中有3步,SwitchBasis中有3步,一共10步。而在新的BFV乘法中,ModSwitch中有2步,Expand中有4步,ScaleDown中有3步。一共有9步。因此,新的BFV乘法不仅P取的比之前小了,而且执行basis extension的次数也比初始的BFV方案要少一点。

分层BFV乘法:

和BGV一样,BFV中也可以使用分层的思想,令模数为 Q ℓ = q 1 ⋯ q ℓ Q_{\ell}=q_1 \cdots q_{\ell} Q=q1q,并且在计算过程中执行modulus switching。但是,这样做的话那也就涉及到了不同层之间密文的处理以及噪声的管理。

为了维持BFV的可用性,他们提出了一种预放缩的方法,先将密文缩放 Q ℓ Q \frac{Q_{\ell}}{Q} QQ,对缩放后的密文进行乘法,然后将结果再乘以 Q Q ℓ \frac{Q}{Q_{\ell}} QQ回到   m o d   Q \bmod Q modQ下,

中间过程中经过模数转换的密文噪声为: v ^ = Q ℓ Q v + ε round  \hat{\boldsymbol{v}}=\frac{Q_{\ell}}{Q} \boldsymbol{v}+\varepsilon_{\text {round }} v^=QQv+εround ,其中 ε round \varepsilon_{\text{round}} εround的大小大约为 δ R 2 \frac{\delta_{\mathcal{R}}}{2} 2δR。为了使噪声和缩放前保持基本一致,要求 Q ℓ Q ∥ v ∥ ∞ ≫ ∥ ε round ∥ ∞ \frac{Q_{\ell}}{Q}\| \boldsymbol{v} \|_{\infty} \gg \| \varepsilon_{\text{round}} \|_{\infty} QQvεround → \rightarrow ∥ v ∥ ∞ ≫ Q δ R 2 Q ℓ  and  ∥ v ∥ ∞ ′ ≫ Q δ R 2 Q ℓ \|\boldsymbol{v}\|_{\infty} \gg \frac{Q \delta_{\mathcal{R}}}{2 Q_{\ell}} \text { and }\|\boldsymbol{v}\|_{\infty}^{\prime} \gg \frac{Q \delta_{\mathcal{R}}}{2 Q_{\ell}} v2QQδR and v2QQδR。在实现中,往往取 ∥ v ∥ ∞ > 8 Q δ R Q ℓ  and  ∥ v ∥ ∞ ′ > 8 Q δ R Q ℓ \|\boldsymbol{v}\|_{\infty}>8 \frac{Q \delta_{\mathcal{R}}}{Q_{\ell}} \text { and }\|\boldsymbol{v}\|_{\infty}^{\prime}>8 \frac{Q \delta_{\mathcal{R}}}{Q_{\ell}} v>8QQδR and v>8QQδR

新的BFV乘法过程如下:
 ModSwitchDown:  c t ^ = ⌊ Q ℓ Q c t ⌉ ∈ R Q ℓ 2  and  c t ^ ′ = ⌊ Q ℓ Q c t ′ ⌉ ∈ R Q ℓ 2 ▹ v ^ = Q ℓ Q v + ε round   and  ▹ v ^ ′ = Q ℓ Q v ′ + ε round  ′ t ^ m = New ⁡ M u l t ( c t ^ , c t ^ ′ ) ∈ R Q ℓ 3 ▹ c t ^ m ( s ) = Q ℓ t [ m 1 m 2 ] t + v ^ m (   m o d   R Q ℓ )  ModSwitchUp:  c t m = ⌊ Q Q ℓ t ^ m ⌉ ∈ R Q 3 ▹ ct ⁡ m ( s ) = Q t [ m 1 m 2 ] t + v m (   m o d   R Q ℓ ) ▹ v m = Q Q ℓ v ^ m + v r \begin{aligned} &\text { ModSwitchDown: } \hat{\mathrm{ct}}=\left\lfloor\frac{Q_{\ell}}{Q} \mathrm{ct}\right\rceil \in \mathcal{R}_{Q_{\ell}}^{2} \text { and } c \hat{\mathrm{t}}^{\prime}=\left\lfloor\frac{Q_{\ell}}{Q} \mathrm{ct}^{\prime}\right\rceil \in \mathcal{R}_{Q \ell}^{2} \\ &\triangleright \hat{\boldsymbol{v}}=\frac{Q_{\ell}}{Q} \boldsymbol{v}+\varepsilon_{\text {round }} \text { and } \triangleright \hat{\boldsymbol{v}}^{\prime}=\frac{Q_{\ell}}{Q} \boldsymbol{v}^{\prime}+\varepsilon_{\text {round }}^{\prime}\\ &\hat{\mathrm{t}}_{\mathrm{m}}=\operatorname{New} \mathrm{Mul} t\left(\hat{\mathrm{ct}}, \hat{\mathrm{ct}}^{\prime}\right) \in \mathcal{R}_{Q_{\ell}}^{3} \\ &\triangleright \hat{\mathrm{ct}}_{\mathrm{m}}(\boldsymbol{s})=\frac{Q_{\ell}}{t}\left[\boldsymbol{m}_{1} \boldsymbol{m}_{2}\right]_{t}+\hat{\boldsymbol{v}}_{\mathrm{m}}\left(\bmod \mathcal{R}_{Q_{\ell}}\right)\\ &\text { ModSwitchUp: } \mathrm{ct}_{\mathrm{m}}=\left\lfloor\frac{Q}{Q_{\ell}} \hat{\mathrm{t}}_{\mathrm{m}}\right\rceil \in \mathcal{R}_{Q}^{3} \\ &\triangleright \operatorname{ct}_{\mathrm{m}}(\boldsymbol{s})=\frac{Q}{t}\left[\boldsymbol{m}_{1} \boldsymbol{m}_{2}\right]_{t}+\boldsymbol{v}_{\mathrm{m}}\left(\bmod \mathcal{R}_{Q_{\ell}}\right) \\ &\triangleright \boldsymbol{v}_{\mathrm{m}}=\frac{Q}{Q_{\ell}} \hat{\boldsymbol{v}}_{\mathrm{m}}+\boldsymbol{v}_{r} \end{aligned}  ModSwitchDown: ct^=QQctRQ2 and ct^=QQctRQ2v^=QQv+εround  and v^=QQv+εround t^m=NewMult(ct^,ct^)RQ3ct^m(s)=tQ[m1m2]t+v^m(modRQ) ModSwitchUp: ctm=QQt^mRQ3ctm(s)=tQ[m1m2]t+vm(modRQ)vm=QQv^m+vr

优化HPS RNS variant解密

看不懂,待补充。

更加实用的BGV方案

静态噪声处理(通过模数选取的方式)

BGV在使用过程中,需要精确地预估出目前的噪声大小,然后动态地决定什么时候进行模数缩减,每次的缩放系数是多少。在HE-Lib中有详实的噪声动态分析技术。因为BFV是采用了最大位编码,缩放系数 Q / t Q/t Q/t比较大,对噪声不是那么敏感,只要确定一个噪声的上界就可以了,而BGV时最小位编码,而且每次的缩放系数较小,所以需要更加准确的噪声控制。

在这篇文章的实现中,他们不进行动态的噪声控制,而是提前输入一些参数:乘法深度,每个乘法层中加法的最大次数,第一次乘法之前的加法和旋转次数。然后就可以生成所有的模数 Q L , Q L − 1 , . . . , Q 1 , Q 0 Q_L,Q_{L-1},...,Q_1,Q_0 QL,QL1,...,Q1,Q0,更具这些模数来进行模数缩减就可以保证噪声控制在一个较小的范围内。在每次乘法前会自动执行模数缩减,这样子修改那么BGV的可用性就和BFV差不多了。

然后这篇文章就计算了具体的每个模数如何选取,最后得出结论:
q 0 > 2 t ∥ v c ∥ ∞ − t q i > 2 ( ( n a d d ′ + 1 ) δ R t 2 ( 2 ∥ v c ∥ ∞ + 2 + 1 ∥ v c ∥ ∞ ) + ( n k s ′ + 1 ) ∥ v k s ∥ ∞ ∥ v c ∥ ∞ ) q L + 1 > 2 ( ( n a d d + 1 ) ∥ v f r e s h ∥ ∞ ∥ v c ∥ ∞ + n k s ∥ v k s ∥ ∞ ∥ v c ∥ ∞ ) \begin{gathered} q_{0}>2 t\left\|\boldsymbol{v}_{\mathrm{c}}\right\|_{\infty}-t \\ q_{i}>2\left(\left(n_{\mathrm{add}}^{\prime}+1\right) \frac{\delta_{\mathcal{R}} t}{2}\left(2\left\|\boldsymbol{v}_{\mathrm{c}}\right\|_{\infty}+2+\frac{1}{\left\|\boldsymbol{v}_{\mathrm{c}}\right\|_{\infty}}\right)+\left(n_{\mathrm{ks}}^{\prime}+1\right) \frac{\left\|\boldsymbol{v}_{\mathrm{ks}}\right\|_{\infty}}{\left\|\boldsymbol{v}_{\mathrm{c}}\right\|_{\infty}}\right) \\ q_{L+1}>2\left(\left(n_{\mathrm{add}}+1\right) \frac{\left\|\boldsymbol{v}_{\mathrm{fresh}}\right\|_{\infty}}{\left\|\boldsymbol{v}_{\mathrm{c}}\right\|_{\infty}}+n_{\mathrm{ks}} \frac{\left\|\boldsymbol{v}_{\mathrm{ks}}\right\|_{\infty}}{\left\|\boldsymbol{v}_{\mathrm{c}}\right\|_{\infty}}\right) \end{gathered} q0>2tvctqi>2((nadd+1)2δRt(2vc+2+vc1)+(nks+1)vcvks)qL+1>2((nadd+1)vcvfresh+nksvcvks)
其中 Q 0 = q 0 , Q i = Q i − 1 q i Q_0 = q_0,Q_i = Q_{i-1}q_i Q0=q0,Qi=Qi1qi Q L + 1 = Q L q L + 1 Q_{L+1}=Q_Lq_{L+1} QL+1=QLqL+1 Q L + 1 Q_{L+1} QL+1是最初密文加密用的模数,然后会直接进行一次模数缩减到 Q L Q_L QL中来降低初始噪声,所以总共的层数是 L L L层。

处理不同层的密文之间的操作

在HE-Lib中,每个密文都有不同的缩放系数,导致需要将两个密文通过好几次scalar product来统一缩放系数,而在本文的实现中,每一层的缩放系数是一样的,那么就减少了scalar product的次数。

BFV和BGV比较

以下比较是本文优化过的BFV与BGV的比较,并不是原本方案的比较。

噪声增长

分析过程不看,结论上来说,BGV和BFV在 Q 0 Q_0 Q0时的噪声一致。在其余每一个乘法层中,BFV的每一层乘法噪声比BGV小1比特。而对于密钥替换(重线性化)操作来说,在明文模数较小的情况下 ( t ≪ 2 16 + 1 t\ll 2^{16}+1 t216+1),BFV会有优势,在明文模数变大的情况下,BGV会有优势。总体来说,BFV和BGV的噪声增长系数类似,优化过的BFV可能会比BGV有稍微有一点点点点优势。具体可以看实验结果内的数据。

计算复杂度

BFV和BGV最大的计算区别在于乘法之后的scale down,BFV中因为采用了MSD编码,每次乘法完都需要scale down一个很大的 Q / t Q/t Q/t,而对于BGV来说,只需要scale down一个和初始噪声差不多大小的模数,因此很容易想象BGV的效率是远远高于BFV的。统计下来,BFV的乘法,scaledown,重线性化总计需要 16 ℓ + α ( d num 2 + 3 ) 16 \ell + \alpha\left(d_{\text{num}}^2 +3 \right) 16+α(dnum2+3)个NTT,BGV的乘法,重线性化,modulus switching总计需要 7 ℓ ′ + 4 + α ( d num 2 + 2 ) 7 \ell^{\prime} +4+ \alpha \left( d_{\text{num}}^2 + 2 \right) 7+4+α(dnum2+2)个NTT。看上去BFV需要NTT的数量是BGV的2x左右,但是实际上因为模数选取的关系,BFV中 q i q_i qi都会取得尽可能大(60bit),而在t=2的时候,BGV的 q i q_i qi只需要取到20bit ( t ⋅ δ R 2 ) (t\cdot \delta_R^2) (tδR2)左右,因此 ℓ ′ > 3 ℓ \ell^{\prime}>3\ell >3,此时BFV使用NTT数量要小于BGV;但是当 t = 2 16 + 1 t=2^{16}+1 t=216+1时, ℓ ′ ≈ 2 ℓ \ell^{\prime}\approx 2\ell 2,此时BGV效率略优于BFV,当 t t t再取大一点的时候,BGV的噪声就比BFV要高很多了。

实验结果

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/AdijeShen/article/details/118905260