再线性化
用于解决密文乘法导致密文长度增长的问题。
在LWE同态方案中,LWE加密算法具有天然的加法同态,为了使得其再满足乘法同态,将密文乘法定义为密文的张积,用对应的密钥的张积进行解密,将会使得结果满足乘法同态性。但这样的结果是每次乘法将会导致密文长度增加,如果LWE密文长度为 n n n,那么每次乘法后密文都会增长 n 2 / 2 n^2/2 n2/2,因此需要解决密文长度增加的问题。
方案大致是,将解密函数表示为一个关于密文 c c c的一个多变元多项式 f s k ( c ) f_{sk}(c) fsk(c),其中 c c c的各项是该多项式的变元,密钥 s k sk sk的各项是多项式的系数。密文乘法之后,密钥中的各项次数会从1次变为2次,如 s = ( s 1 , s 2 ) s=(s_1,s_2) s=(s1,s2),同态乘法后将变为 s ⊗ s = ( s 1 s 1 , s 1 s 2 + s 2 s 1 , s 2 s 2 ) s\otimes s = (s_1s_1,s_1s_2+s_2s_1,s_2s_2) s⊗s=(s1s1,s1s2+s2s1,s2s2),此时用一个长度与 s s s长度相同的新密钥 t t t对 s ⊗ s s \otimes s s⊗s中的各项加密,就可以将“2次”密钥转化为“1次”密钥,从而得到一个新的密文,长度与原密文基本接近,且使用 t t t对新密文解密和使用 s ⊗ s s \otimes s s⊗s对密文 c 1 ⊗ c 2 c_1 \otimes c_2 c1⊗c2解密结果一样。
维数-模约减
用于压缩解密电路的深度,得解密电路深度小于有限次同态加密的电路深度。
我们知道,同态加密方案中,要使用同态解密达到控制噪声的话,解密电路的深度需要小于同态加密的电路深度(噪声上限所允许的电路深度)。因为解密运算在电路模型上也是和同态运算相同的加法和乘法,那么如果解密电路比同态加密的电路大,那一定会由于噪声过大而导致无法正确解密。要想达到”全同态“,也就是要达到同态解密之后还能再进行同态运算,这样就可以一次同态运算接着一次同态解密运算来达到“全同态”。
若在再线性化中,将新密钥
t
t
t的长度取为比正常密文长度小,就能获得更小长度的密文(此为维数约简),同时如果再进一步将新密钥的模取为比正常密文的模更小(此为模数约简),就可以实现降低解密电路深度。
密钥交换
是再线性化技术的优化版本,该技术用于控制密文维数的增长。
给出维数是
n
1
n_1
n1的密文
c
1
c_1
c1和密钥
s
1
s_1
s1,以及其目标密钥
(
1
,
s
2
)
(1,s_2)
(1,s2)(维数是
n
2
+
1
n_2+1
n2+1),输出结果是密文
c
2
c_2
c2,对应密钥是
(
1
,
s
2
)
(1,s_2)
(1,s2),两个密文对应的明文是一样的,如果让
s
2
s_2
s2的维数小于
s
1
s_1
s1的,那么就能在密文乘积后约减密文的维数,转换为正常的密文维数。
模交换(Modulus Switching)
该技术用于约减密文里的噪声,管理噪声的增长。
假定密文初始噪声为
B
B
B,模
q
≈
B
k
q \approx B^k
q≈Bk(也就是噪音上限)。经过一次乘法电路后噪声增加为
B
2
B^2
B2,通过
log
k
\log k
logk层乘法后,噪声达到上限。如果采用模交换技术,每次乘法之后对密文除以
B
B
B,对
B
2
B^2
B2来说相当于把它约减回
B
B
B,同时将密文长度缩小为原来的
1
/
B
1/B
1/B,则新密文的模变为
q
/
B
q/B
q/B。依次下去,每次噪声都被“拉回”原来的大小
B
B
B,而模依次递减形成一个由高到低的阶梯型,
q
/
B
2
,
q
/
B
3
,
⋯
,
q
/
B
k
−
1
q/B^2,q/B^3,\cdots,q/B^{k-1}
q/B2,q/B3,⋯,q/Bk−1,这样可以执行的乘法深度就近似为
k
−
1
k-1
k−1,对比
log
k
\log k
logk,能够实现的深度显著提高。
Bootstrapping
该技术主要是用来刷新密文噪声。
把一个满噪音的FHE的密文加密进另一个FHE密文中,并且同态计算FHE的解密算法,把里层的密文解密还原为原文,就能获得一个全新的低噪音FHE密文。
一次bootstrapping的过程
- 首先生成多组密钥(以两组为例) ( p k 1 , s k 1 ) , ( p k 2 . s k 2 ) (pk_1,sk_1),(pk_2.sk_2) (pk1,sk1),(pk2.sk2)
- 假定明文为 m m m,首先用第一组密钥进行加密得到 E n c p k 1 ( m ) Enc_{pk_1}(m) Encpk1(m),初始得到的噪声很低,随着不断的同态计算将得到一个达到噪声临界值的密文 C f ( m ) = E n c p k 1 ( f ( m ) ) C_{f(m)} = Enc_{pk_1}(f(m)) Cf(m)=Encpk1(f(m)),也就是说如果再进行一次同态计算就将导致解密失败。
- 接着,将这个密文用 p k 2 pk_2 pk2进行加密得到 E n c p k 2 ( C f ( m ) ) Enc_{pk_2}(C_{f(m)}) Encpk2(Cf(m))。
- 然后使用一个加密后的密钥 E n c p k 2 ( s k 1 ) Enc_{pk_2}(sk_1) Encpk2(sk1),和 E n c p k 2 ( C f ( m ) ) Enc_{pk_2}(C_{f(m)}) Encpk2(Cf(m)) 进行 s k 1 sk_1 sk1下的同态解密运算 D e c s k 1 ( C f ( m ) ) Dec_{sk_1}(C_{f(m)}) Decsk1(Cf(m))。这样一来可以得到 E n c p k 2 ( D e c s k 1 ( C f ( m ) ) ) = E n c p k 2 ( C f ( m ) ) Enc_{pk_2}(Dec_{sk_1}(C_{f(m)})) = Enc_{pk_2}(C_{f(m)}) Encpk2(Decsk1(Cf(m)))=Encpk2(Cf(m)),这样一来,当前的噪声已经不是达到限度的那个噪声了,而是一次同态运算后产生的新的噪声,也就变相的削弱了噪声。
同理,可以继续嵌套这个过程,等到每一波同态计算噪音极限后,再次Bootstrapping来计算更复杂的函数。
当然,这里存在一个小缺点,那就是在生成参数的时候需要事先准备好Bootstrapping的链条,即生成公钥私钥对
{
p
k
i
,
s
k
i
}
\{pk_i,sk_i\}
{pki,ski},并且公开对应的私钥
s
k
i
sk_i
ski加密在下的密文
p
k
i
+
1
pk_{i+1}
pki+1。所以作为第三方,我们仍然不能计算任意深度的电路,因为计算的深度在进行公共参数生成的阶段已经被决定好了。
解决方案可以使用循环密钥,以双密钥的系统来说
(
p
k
1
,
s
k
1
)
,
(
p
k
2
.
s
k
2
)
(pk_1,sk_1),(pk_2.sk_2)
(pk1,sk1),(pk2.sk2),同时公开在
p
k
2
pk_2
pk2加密下的
s
k
1
sk_1
sk1和
p
k
1
pk_1
pk1加密下的
s
k
2
sk_2
sk2,然后无限循环即可。
还可以使用一组密钥即可完成,也就是公开
p
k
1
pk_1
pk1加密下的
s
k
1
sk_1
sk1,接着循环调用即可。
上述Bootstrapping过程称为Circuit Bootstrapping,还有一种Gate Bootstrapping,即每当进行一次最简单的同态计算,就进行一轮的Bootstrapping把噪声值还原到进行计算前的量,这个可以在应用层之下实现Bootstrapping。
当然,上述的密钥循环的安全性是未知的,目前还没有被证明是安全的,这也叫做循环安全假设。
参考
初探全同态加密之四:Bootstrapping的原理与实现
全同态加密知识体系整理
陈智罡,王箭,宋新霞.全同态加密研究[J].计算机应用研究,2014,31(06):1624-1631.