再线性化
用于解决密文乘法导致密文长度增长的问题。
在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=(s1?s1?,s1?s2?,s2?s1?,s2?s2?),此时用一个长度与
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?),两个密文对应的明文是一样的,如果让
1
,
s
2
1,s_2
1,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)?) 和
E
n
c
p
k
2
(
s
k
1
)
Enc_{pk_2}(sk_1)
Encpk2??(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.
|