TFHE的Bootstrapping(同态刷新),除了减少噪音外,还可以运算一个单变量函数(用查找表LUT的方式)。然而,它需要预先知道明文的最高位,从而导致损失了一个位的空间来存储信息。此外,在许多使用情况下,它的计算开销很大。
在本文中,我们提出了一个解决方案来克服上述限制,我们称之为可编程的无填充同态刷新(Programmable Bootstrapping Without Padding WoP-PBS)。这种方法依赖于两个构建模块。第一个是BFV乘法,我们将其纳入TFHE。有充分的噪声分析来证明,使用TFHE的参数可以正确的进行BFV乘法。第二个构件是本文介绍的TFHE同态刷新的一般化。它提供了灵活性,可以在同态刷新过程中选择加密明文中的任何块位。当工作的精度足够小时,它还能同时评估许多LUT。所有这些改进在一些应用中特别有帮助,如布尔电路的评估(在每个被评估的门中不再需要自举),更普遍的是,即使有大的整数,也能有效评估算术电路。这些结果也改善了TFHE电路的同态刷新。此外,我们还表明,现在可以使用比TFHE的参数小得多的参数来同态刷新大精度的整数。
TFHE是一种支持高效同态刷新的(R)LWE-based FHE方案。最初是对FHEW方案的一种优化,后来也加入了别的一些技术来提高效率。TFHE的高效性来自于他们选取的参数是非常小的,支持使用CPU内带的64位整形来表示出来,因此可以达到非常好的效率。
TFHE加密形式:
TFHE使用将加密的消息放在最高位,对于消息 m ∈ Z m\in \Z m∈Z,加噪后的明文看起来就是 Δ ⋅ m + e m o d q \Delta \cdot m + e\bmod q Δ⋅m+emodq。其中 m m m的精度位大小为 p = log 2 ( q Δ ) p=\log_2(\frac{q}{\Delta}) p=log2(Δq)。可以通过下图来形式化地理解一下:
在这里 p = 7 p=7 p=7,最高位(蓝色部分)为消息,最低位(红色部分)为噪声。
可编程同态刷新(Programmable Bootstrapping P B S \mathbf{PBS} PBS):
TFHE的同态刷新过程很高效,但其实也同时是可编程的,也就是说,可以在降低密文的噪声的同时,对明文运算一个单变量的函数 f f f。类似 L W E ( m + e ) → P B S L W E ( f ( m + e ) + e ′ ) \mathsf{LWE}(m+e)\stackrel{\mathbf{PBS}}{\rightarrow}\mathsf{LWE}(f(m+e)+e') LWE(m+e)→PBSLWE(f(m+e)+e′),因为使用LUT进行刷新,这里的 f f f可以是任意的函数(不局限于多项式)。具体的方法是将 f f f的LUT编码为一个多项式,然后通过同态地旋转查找表来得到 f ( m + e ) f(m+e) f(m+e),通常在 P B S \mathbf{PBS} PBS中,需要将LUT中的临近的几位设置为相同的系数,使得 f ( m + e ) = f ( m ) f(m+e)=f(m) f(m+e)=f(m)。
一次同态刷新运算多个函数:
文章1中有提到一种在一个密文上同时运算多个函数的技术, { f i } i \{f_i\}_i {fi}i,每个函数都被编码为一个多项式 P i P_i Pi,可以生成一个共享多项式 Q Q Q使得 P i = Q ⋅ P i ′ P_i = Q\cdot P_i' Pi=Q⋅Pi′,并计算 C T o u t ← P B S ∗ ( c t i n , B S K , Q ) {\sf CT_{out}}\gets {\bf PBS}^*({\sf ct_{in}, BSK},Q) CTout←PBS∗(ctin,BSK,Q),然后可以用 C T o u t \sf CT_{out} CTout去乘 P i ′ P_i' Pi′来得到运算不同函数的结果。
这种方法的一个缺点在于输出的密文的噪声与 P i ′ P_i' Pi′有关。
m<q/2,即最高位为0)。
这篇文章解决了上述的TFHE的限制。
首先,他们扩展了TFHE的 P B S \bf PBS PBS,现在可以不引入额外噪声的情况下一次执行多个函数了。这种方法适用于明文非常小的情况。这种方法解决了限制6和8。
其次,他们分析了BFV类型的LWE乘法+重现性化的噪声增长,找到了适合TFHE的参数来运算BFV类型的乘法+重线性化,而不是通过 P B S \bf PBS PBS来做乘法。这就解决了限制4。
基于这种乘法,他们定义了一种新的 P B S \bf PBS PBS方案,这种 P B S \bf PBS PBS不需要消息的最高位为0,解决了限制1,并且这种新的 P B S \bf PBS PBS方案可以由多个子 P B S \bf PBS PBS并行运算得到,支持多线程操作,解决了限制3。不同于CHIMERA以及PEGASUS这样的方案,这篇文章在TFHE中加入了BFV类型的乘法,因此就可以全程保留在TFHE的状态下,而不需要去转换。
由新的 P B S \bf PBS PBS方案可以构造一个同态的 d e c o m p o s e \sf decompose decompose(分块)方案,解决了限制5,而且也解除了每个布尔门都需要 P B S \bf PBS PBS的限制7。
由上述的 P B S \bf PBS PBS方法和 h o m o m o r p h i c d e c o m p o s e \sf homomorphic~decompose homomorphic decompose方法,可以运算超过6比特的数。解决了限制2。
这里主要介绍几个文章中的符号,首先 R q = Z q [ X ] / ( X N + 1 ) \mathfrak{R}_q=\Z_q[X]/(X^N+1) Rq=Zq[X]/(XN+1)多项式环大家都比较熟悉了。
然后这篇文章将 L W E , R L W E \sf LWE, RLWE LWE,RLWE融合成了一个 G L W E \sf GLWE GLWE表示,具体来说为:
C T = ( A 1 , ⋯ , A k , B = ∑ i = 1 k A i ⋅ S i + ⌊ M ⋅ Δ ⌉ q + E ) = G L W E S ( M ⋅ Δ ) ∈ R q k + 1 {\sf CT} = (A_1,\cdots,A_k,B=\sum_{i=1}^kA_i\cdot S_i + \lfloor M \cdot \varDelta \rceil_q + E)={\sf GLWE}_{\bf S}(M\cdot \varDelta) \in \mathfrak{R}_{q}^{k+1} CT=(A1,⋯,Ak,B=i=1∑kAi⋅Si+⌊M⋅Δ⌉q+E)=GLWES(M⋅Δ)∈Rqk+1
其中 S = ( S 1 , ⋯ , S k ) ∈ R q k {\bf S}=(S_1,\cdots,S_k)\in \mathfrak{R}_{q}^k S=(S1,⋯,Sk)∈Rqk要么是一个{0,1},要么是{-1,0,1}中均匀分布的密钥。
对于 G L W E {\sf GLWE} GLWE密文来说,当 N = 1 N=1 N=1的时候这就是一个 L W E \sf LWE LWE密文,当 N > 1 , k = 1 N>1,k=1 N>1,k=1的时候这就是一个 R L W E \sf RLWE RLWE密文。
其实 G L e v \sf GLev GLev密文就是对 G L W E \sf GLWE GLWE密文的分解,形式如同:
C T ‾ = ( C T 1 , ⋯ , C T ℓ ) = G L e v S B , ℓ ∈ R q ℓ × ( k + 1 ) \overline{\sf CT}=({\sf CT}_1,\cdots ,{\sf CT}_{\ell}) = {\sf GLev}_{\bf S}^{\mathfrak{B},\ell}\in \mathfrak{R}_q^{\ell \times(k+1)} CT=(CT1,⋯,CTℓ)=GLevSB,ℓ∈Rqℓ×(k+1)
其中 C T i = G L W E ( M ⋅ q B i ) {\sf CT}_i={\sf GLWE}(M\cdot \frac{q}{\mathfrak{B}^i}) CTi=GLWE(M⋅Biq),是对于 M M M的基为 B \mathfrak{B} B的分解。
再定义一个分解算法。对于一个基 B ∈ N ∗ \mathfrak{B}\in \N^* B∈N∗, x ∈ Z q x\in\Z_q x∈Zq:
d e c ( B , ℓ ) ( x ) = ( x 1 , ⋯ , x ℓ ) ∈ Z q ℓ {\sf dec}^{(\mathfrak{B},\ell)}(x)=(x_1,\cdots,x_{\ell})\in \Z_q^{\ell} dec(B,ℓ)(x)=(x1,⋯,xℓ)∈Zqℓ
满足
⟨ d e c ( B , ℓ ) ( x ) , ( q B 1 , ⋯ , q B ℓ ) ⟩ = ⌊ x ⋅ B ℓ q ⌉ ⋅ q B ℓ ∈ Z q \langle {\sf dec}^{(\mathfrak{B},\ell)}(x),\big(\frac{q}{\mathfrak{B}^1},\cdots,\frac{q}{\mathfrak{B}^{\ell}} \big)\rangle=\left\lfloor x\cdot\frac{\mathfrak{B}^\ell}{q} \right\rceil \cdot \frac{q}{\mathfrak{B}^\ell} \in \Z_q ⟨dec(B,ℓ)(x),(B1q,⋯,Bℓq)⟩=⌊x⋅qBℓ⌉⋅Bℓq∈Zq
可以类似地定义一个对整数多项式的分解 X ∈ R q X\in \mathfrak{R}_q X∈Rq:
d e c ( B , ℓ ) ( X ) = ( X 1 , ⋯ , X ℓ ) ∈ R q ℓ {\sf dec}^{(\mathfrak{B},\ell)}(X)=(X_1,\cdots,X_{\ell})\in \mathfrak{R}_q^{\ell} dec(B,ℓ)(X)=(X1,⋯,Xℓ)∈Rqℓ
⟨ d e c ( B , ℓ ) ( X ) , ( q B 1 , ⋯ , q B ℓ ) ⟩ = ⌊ X ⋅ B ℓ q ⌉ ⋅ q B ℓ ∈ R q \langle {\sf dec}^{(\mathfrak{B},\ell)}(X),\big(\frac{q}{\mathfrak{B}^1},\cdots,\frac{q}{\mathfrak{B}^{\ell}} \big)\rangle=\left\lfloor X \cdot\frac{\mathfrak{B}^\ell}{q} \right\rceil \cdot \frac{q}{\mathfrak{B}^\ell} \in \mathfrak{R}_q ⟨dec(B,ℓ)(X),(B1q,⋯,Bℓq)⟩=⌊X⋅qBℓ⌉⋅Bℓq∈Rq
G G S W \sf GGSW GGSW其实就是多个 G L e v \sf GLev GLev密文结合,令 S = ( S 1 , ⋯ , S k ) ∈ R q k {\bf S}=(S_1,\cdots ,S_k) \in \mathfrak{R}_q^k S=(S1,⋯,Sk)∈Rqk,则 G G S W \sf GGSW GGSW密文为:
C T ‾ ‾ = ( C T ‾ 1 , ⋯ , C T ‾ k + 1 ) = G G S W S ( B , ℓ ) ( M ) ∈ R q ( k + 1 ) × ℓ × ( k + 1 ) \overline{\overline{\sf CT}}=(\overline{\sf CT}_1,\cdots ,\overline{\sf CT}_{k+1})={\sf GGSW}_{\bf S}^{(\mathfrak{B},\ell)}(M) \in \mathfrak{R}_q^{(k+1)\times \ell \times (k+1)} CT=(CT1,⋯,CTk+1)=GGSWS(B,ℓ)(M)∈Rq(k+1)×ℓ×(k+1)
其中 C T ‾ i = G L e v S ( B , ℓ ) ( − S i ⋅ M ) 。 \overline{\sf CT}_i={\sf GLev}_{\bf S}^{(\mathfrak{B},\ell)}(-S_i\cdot M)。 CTi=GLevS(B,ℓ)(−Si⋅M)。
当 N = 1 N=1 N=1时,这就是个 G S W \sf GSW GSW密文,当 N > 1 , k = 1 N>1,k=1 N>1,k=1时,这是一个 R G S W \sf RGSW RGSW密文。
KeySwitching算是全同态加密当中最重要的一个组件了,没有这个好多事情都做不了。KeySwitching会需要一个 KSK,看一下这篇文章中的三种定义:
K S K = { C T ‾ i = G L e v S ′ B , ℓ ( s i ) 1 ≤ i ≤ n } {\sf KSK}=\{\overline{\sf CT}_i={\sf GLev}_{\bf S'}^{\mathfrak{B},\ell}(s_i)_{1 \le i \le n} \} KSK={CTi=GLevS′B,ℓ(si)1≤i≤n}。 s = ( s 1 , ⋯ , s n ) ∈ Z q n {\bf s}=(s_1,\cdots,s_n)\in\Z_q^n s=(s1,⋯,sn)∈Zqn是输入的LWE密钥, S ′ = ( S 1 ′ , ⋯ , S k ′ ) ∈ R q k {\bf S'}=(S'_1,\cdots,S_k')\in \mathfrak{R}_q^k S′=(S1′,⋯,Sk′)∈Rqk是输出的GLWE密钥。定义一个LWE-to-GLWE转换:
P B S \bf PBS PBS分为三步:
第一步: M o d u l u s S w i t c h i n g \sf Modulus~Switching Modulus Switching,将一个在 Z q n + 1 \Z_q^{n+1} Zqn+1上的 L W E ( m ) {\sf LWE}(m) LWE(m)密文缩减到 Z 2 N n + 1 \Z_{2N}^{n+1} Z2Nn+1上,这里可以参考FHEW的Bootstrapping过程,只支持模 2 N 2N 2N大小的密文。
第二步:使用 B l i n d R o t a t i o n \sf Blind Rotation BlindRotation(其实和FHEW里面的Refresh算法差不多,可以参考一下)得到一个 G L W E ( f ( m ) ) ∈ R q {\sf GLWE}(f(m))\in\mathfrak{R}_q GLWE(f(m))∈Rq密文。
第三步:通过一个 e x t r a c t \sf extract extract算法将 G L W E \sf GLWE GLWE密文提取为 L W E \sf LWE LWE密文。
对PBS感兴趣可以看一下这篇 TOTA: Fully Homomorphic Encryption with Smaller Parameters and Stronger Security
在TFHE2017的文章里面有讲如何做Circuit Bootstrapping,可以在降低噪声的同时将LWE密文转换文GGSW密文。
但是一次Circuit Bootstrapping需要使用 ℓ \ell ℓ次的 P B S \bf PBS PBS以及 ( k + 1 ) ℓ (k+1)\ell (k+1)ℓ次的 P r i v a t e K S \mathbf{PrivateKS} PrivateKS,是通过像搭积木一样把GLWE密文搭成一个GGSW密文,感觉效率会很慢。
首先定义一个 G L W E M u l t \bf GLWEMult GLWEMult,由乘法和一次relinearize组成。
单个 L W E \sf LWE LWE乘法:
有了 G L W E \sf GLWE GLWE的乘法之后,就可以通过将 L W E \sf LWE LWE先转换为 G L W E \sf GLWE GLWE,然后调用 G L W E M u l t \bf GLWEMult GLWEMult做乘法,最后通过 S a m p l e E x t r a c t \bf SampleExtract SampleExtract将 L W E \sf LWE LWE从 G L W E \sf GLWE GLWE中提取出来。
这里刚开始不太明白为什么要用两次KeySwitch以及一次GLWE乘法+Relin和一次Extract来做LWE之间的乘法,难道会比LWE原生的乘法要快吗?我觉得应该是为了能够计算后面的Packed LWE乘法。但这种PackedLWEMult应该也要满足 α ( α + 1 ) < k N \alpha(\alpha+1) < kN α(α+1)<kN的限制。
多个 L W E \sf LWE LWE乘法:
可以通过简单的修改算法2,让其可以单次计算多个 L W E \sf LWE LWE密文的乘积。
令输入为 { c t i ( 1 ) } = { L W E S ( m i ( 1 ) ⋅ Δ 1 ) } ( 0 ≤ i < α ) , { c t i ( 2 ) } = { L W E S ( m i ( 2 ) ⋅ Δ 2 ) } ( 0 ≤ i < α ) \{{\sf ct}_i^{(1)}\}=\{{\sf LWE}_{\bf S}(m_i^{(1)}\cdot \varDelta_1)\}_{}(0\le i < \alpha),\{{\sf ct}_i^{(2)}\}=\{{\sf LWE}_{\bf S}(m_i^{(2)}\cdot \varDelta_2)\}_{}(0\le i < \alpha) {cti(1)}={LWES(mi(1)⋅Δ1)}(0≤i<α),{cti(2)}={LWES(mi(2)⋅Δ2)}(0≤i<α)。
只需要修改算法2的2,3步,将2的Index从 { 0 } \{0\} {0}改为 I 1 = { 0 , 1 , 2 , ⋯ , α − 1 } 。 \mathcal{I}_1=\{0,1,2,\cdots,\alpha-1\}。 I1={0,1,2,⋯,α−1}。,将3的Index从 { 0 } \{0\} {0}改为 I 2 = { 0 , α , 2 α , ⋯ , ( α − 1 ) α } \mathcal{I}_2=\{0,\alpha,2\alpha,\cdots,(\alpha-1)\alpha\} I2={0,α,2α,⋯,(α−1)α}。可以算一下这样最后GLWE密文中的第 i ⋅ ( α + 1 ) i \cdot(\alpha+1) i⋅(α+1)项就是 m i ( 1 ) ⋅ m i ( 2 ) ⋅ Δ o u t m_i^{(1)}\cdot m_i^{(2)}\cdot \varDelta_{\sf out} mi(1)⋅mi(2)⋅Δout。
多个 L W E \sf LWE LWE乘累加:
只要简单的修改一下上面的index,改为 I 1 = { 0 , 1 , 2 , ⋯ , α − 1 } \mathcal{I}_1=\{0,1,2,\cdots,\alpha-1\} I1={0,1,2,⋯,α−1}, I 2 = { α − 1 , α − 2 , α − 3 , ⋯ , 0 } \mathcal{I}_2=\{\alpha-1,\alpha-2,\alpha-3,\cdots,0\} I2={α−1,α−2,α−3,⋯,0},那么结果的 G L W E \sf GLWE GLWE中的第 α − 1 \alpha-1 α−1项就 ∑ 0 ≤ i < α ( m i ( 1 ) m i ( 2 ) ⋅ Δ o u t ) \sum_{0\le i<\alpha}(m_i^{(1)}m_{i}^{(2)}\cdot \varDelta_{\sf out}) ∑0≤i<α(mi(1)mi(2)⋅Δout)。
文中还有一个做PackedSquare的,和PackedMult同样思路,就不写了。
在TFHE(以及FHEW)中,他们的 P B S \bf PBS PBS都是只刷出一个MSB(为了做Bootstrapping),而其实 P B S \bf PBS PBS可以刷新一段消息中的任何位置,而且一次 P B S \bf PBS PBS可以同时对这一段位置执行多个函数。为了形式化地表达这种能力,这篇文章引入了两个额外的参数 ϰ \varkappa ϰ和 ϑ \vartheta ϑ。其中 ϰ \varkappa ϰ表示在 P B S \bf PBS PBS刷新的那段消息前面的没被刷新的消息个数, ϑ \vartheta ϑ表示可以批量执行 2 ϑ 2^{\vartheta} 2ϑ个函数。
这张图可以理解一下一般化的 P B S \bf PBS PBS以及上述两个参数,将一个密文中包含的phase展开为二进制 ( Δ M + e ) (\Delta M+e) (ΔM+e),其中 M M M为原始消息,很显然,消息部分由于乘了 Δ \varDelta Δ,所以在高位,而噪声在低位,只要噪声没有达到蓝色部分-1的位置,即 ∣ e ∣ < Δ / 2 |e|<\varDelta/2 ∣e∣<Δ/2,就可以正确解密。
对于 P B S \bf PBS PBS来说,他的有效空间是模 2 N 2N 2N的,所以图中只有绿色部分的消息可以进入 P B S \bf PBS PBS,而由于刷出来的消息是 f ( m + e ) f(m+e) f(m+e),因此要使得 f ( m + e ) = f ( m ) f(m+e)=f(m) f(m+e)=f(m)这个性质满足,也就是不能刷 2 N 2N 2N这么大的数,有噪声存在,可以看到图中每次只能刷 5 5 5比特。而刷出来的密文后面本应该有6位的噪声(应该Output中后面六位是红的),但这里为了实现批量运算 2 ϑ 2^{\vartheta} 2ϑ个函数的功能,手动将后面 ϑ \vartheta ϑ位设为 0 0 0。
在介绍 G e n P B S \bf GenPBS GenPBS前要先说一下为什么一般化的 P B S \bf PBS PBS函数会没办法一起刷最高位。对于编码为 2 N 2N 2N上的多项式 f : Z 2 N → Z f:\Z_{2N}\to\Z f:Z2N→Z的函数来说,输入为 ( 0 , 1 , . . . , 2 N − 1 ) (0,1,...,2N-1) (0,1,...,2N−1),做 P B S \bf PBS PBS时需要将这个函数打包为一个多项式 P = f ( 0 ) − f ( N − 1 ) X − ⋯ − f ( 1 ) X ( N − 1 ) ∈ R q P=f(0)-f(N-1)X-\cdots - f(1)X^{(N-1)}\in R_q P=f(0)−f(N−1)X−⋯−f(1)X(N−1)∈Rq。而我们的 R q R_q Rq是模 X N + 1 X^N+1 XN+1的,所以对于 f ( i ) f(i) f(i)来说,我们计算 P ⋅ X i P\cdot X^i P⋅Xi,这个多项式的常数项为 f ( i ) f(i) f(i),但考虑到他只有模 X N + 1 X^N+1 XN+1,而 f f f的定义域在 2 N 2N 2N上。所以会满足一个自反的性质: X N = − 1 X^N=-1 XN=−1,即 f ( x + N ) = − f ( x ) f(x+N)=-f(x) f(x+N)=−f(x)。因此 x > N x>N x>N的时候,得到的是 − f ( x − N ) -f(x-N) −f(x−N),即有效位只有 log N − 1 \log N-1 logN−1。
可以看下面这张图,最后能刷的只有 m ′ m' m′,得到的结果是 ( − 1 ) β ⋅ m ′ (-1)^{\beta}\cdot m' (−1)β⋅m′。
那么来看一下本文的 G e n P B S \bf GenPBS GenPBS流程。
很标准的过程,modulusSwitch+BlindRotate(Accumulation)+Extract。值得注意的是这里的modulusSwitch是把最后的 2 ϑ 2^{\vartheta} 2ϑ位给空出来了,为了之前说的批量执行 2 ϑ 2^{\vartheta} 2ϑ个函数。
注意到这里的 P B S \bf PBS PBS刷新出来的结果并非 f ( m ) f(m) f(m),而是 ( − 1 ) β ⋅ f ( m ′ ) (-1)^{\beta}\cdot f(m') (−1)β⋅f(m′)。
我们先假设 ϑ = 0 \vartheta=0 ϑ=0,其实就有效位来说,其实只有 d d d比特 ( m ′ ) (m') (m′)。而非 d + 1 d+1 d+1比特 ( m ) (m) (m)。他所有运算的函数都要满足 f ( x + N ) = − f ( x ) f(x+N)=-f(x) f(x+N)=−f(x)的自反性性质。
现在的目的是把前面的一位 β \beta β所带来的自反性去掉。来看一下这篇文章是如何做的。作者管具有这种性质的 P B S \bf PBS PBS叫做PBS with out Padding W o p ⋅ P B S \bf Wop·PBS Wop⋅PBS。
分别使用两次 P B S \bf PBS PBS刷新出 ( − 1 ) β ⋅ f ( m ′ ) (-1)^{\beta}\cdot f(m') (−1)β⋅f(m′)以及 ( − 1 ) β (-1)^{\beta} (−1)β,再将两者相乘就可以得到 f ( m ′ ) f(m') f(m′)的结果了。 P B S \bf PBS PBS可以用来得到 ( − 1 ) β (-1)^{\beta} (−1)β,就直接令 f ( x ) = 1 ( 0 ≤ x < N ) , − 1 ( N ≤ x < 2 N ) f(x)=1(0\le x
其实他的这样做之后的有效位还是d位,只是避免了翻转。
看一下算法怎么写的:
需要用两次 P B S \bf PBS PBS分别刷出 c t f = L W E ( ( − 1 ) β ⋅ m ′ ⋅ Δ o u t ) {\sf ct}_{\sf f}={\sf LWE}((-1)^{\beta}\cdot m'\cdot \varDelta_{\sf out}) ctf=LWE((−1)β⋅m′⋅Δout)。以及 c t s i g n = L W E ( ( − 1 ) β ) {\sf ct_{sign}}={\sf LWE}((-1)^{\beta}) ctsign=LWE((−1)β)。然后要做一次 L W E \sf LWE LWE的乘法。感觉来说优点在于两个 P B S \bf PBS PBS可以并行计算,缺点是也是只能刷 d d d比特,而且用乘法的噪声会比较大。
第二种方法是弄两个函数,分别对应 β = 0 \beta=0 β=0和 β = 1 \beta=1 β=1的情况,然后用过乘法来做选择,劣势在于需要用到3个 P B S \bf PBS PBS,这样做的好处在于可以刷新 d + 1 d+1 d+1个比特。
具体的方案如下:
在编码多项式的时候,原本对于 f ( m ′ ) f(m') f(m′)我们的LUT是如下的:
f ( 0 ) , f ( 0 ) X , f ( 0 ) X 2 , f ( 0 ) X 3 , . . . , f ( 2 d − 1 ) X N − 3 , f ( 2 d − 1 ) X N − 2 , f ( 2 d − 1 ) X N − 1 f(0),f(0)X,f(0)X^2,f(0)X^3,...,f(2^d-1)X^{N-3},f(2^d-1)X^{N-2},f(2^d-1)X^{N-1} f(0),f(0)X,f(0)X2,f(0)X3,...,f(2d−1)XN−3,f(2d−1)XN−2,f(2d−1)XN−1
这样子做的话在查询常数项的时候会得到 f ( m ′ + e ) = f ( m ′ ) f(m'+e)=f(m') f(m′+e)=f(m′)。因为相邻几位的LUT是相同的,所以噪声不影响查询的结果。
那如果我们令噪声的最后几位(举例为1位)固定为0。
将LUT编码为
f 0 ( 0 ) , f 1 ( 0 ) X , f 0 ( 1 ) X 2 , f 1 ( 1 ) X 3 , . . . , f 0 ( 2 d − 1 − 1 ) X N − 2 , f 1 ( 2 d − 1 − 1 ) X N − 1 f_0(0),f_1(0)X,f_0(1)X^2,f_1(1)X^3,...,f_0(2^{d-1}-1)X^{N-2},f_1(2^{d-1}-1)X^{N-1} f0(0),f1(0)X,f0(1)X2,f1(1)X3,...,f0(2d−1−1)XN−2,f1(2d−1−1)XN−1
那么查询最后结果的常数项为 f 0 ( x ) f_0(x) f0(x),1项为 f 1 ( x ) f_1(x) f1(x),也就可以通过多次的extract将多输出的结果提取出来。
但这样做法会缩小函数的有效位。如图所示:
算法如下:
值得注意的是上面两个 W o p ⋅ P B S \bf Wop·PBS Wop⋅PBS也可以采用 P B S m a n y L U T \bf PBSmanyLUT PBSmanyLUT来代替 G e n P B S \bf GenPBS GenPBS来运算多个函数。
在应用里提到了固定精度算法,一个精度为p的数,密文表示为 c t i = L W E ( m i ⋅ q 2 p ) {\sf ct}_i={\sf LWE}(m_i \cdot \frac{q}{2^p}) cti=LWE(mi⋅2pq)。用整数 m i ∈ [ 0 , 2 p ) m_i\in [0,2^p) mi∈[0,2p)来表示一个精度为p的小数。
那对于一个固定点数的exact算法,就是每次做完加法和乘法之后(精度变为2p),把最低位p个数拿出来减掉,就重新回到了p位。
但这样做也有限制,因为一次刷新要把整个精度位p刷出来,所以能支持的精度位比较小。
要扩大精度位这篇文章也提出了方法,就是从最低位开始,每次刷p中的一部分,然后减去这一部分,重复上述步骤,直到刷到需要的精度为止。
Circuit Bootstrapping是在[CGGI17]中提出的,是将一个 R L W E ( μ ) \sf RLWE(\mu) RLWE(μ)刷为 R G S W ( μ ) {\sf RGSW}(\mu) RGSW(μ),是通过执行 ℓ \ell ℓ次Bootstrapping得到 ℓ \ell ℓ个 R L W E ( μ q B j ) 1 ≤ j ≤ ℓ {\sf RLWE}(\mu \frac{q}{\mathfrak{B}^j})_{1\le j\le \ell} RLWE(μBjq)1≤j≤ℓ密文,然后将 ℓ \ell ℓ个 R L W E \sf RLWE RLWE组合成一个 R G S W \sf RGSW RGSW。
在这篇文章里,可以用 P B S m a n y L U T \bf PBSmanyLUT PBSmanyLUT同时刷出 ℓ \ell ℓ个 R L W E \sf RLWE RLWE,那就有了 ℓ \ell ℓ倍的加速。
除此之外,使用 W o P − P O S \bf WoP-POS WoP−POS还可以在密文上进行Decomp算法。这个很好理解。
这篇文章主要的贡献就在于解决 P B S \bf PBS PBS的自反性吧。以及提出了一些可能的应用。
New techniques for multi-value input homomorphic evaluation and applications. ↩︎ ↩︎