前言
之前看了好多资料,发现对于BGV的介绍都比较少,大家都主要关注于CKKS。其实在一些整数域上面的计算BGV还是很有优势的,与CKKS相比,BGV是一个确定性的加密方案,与BFV相比,BGV的乘法在RNS下实现要简单非常多。所以在某些场景下(比如有限域上的MPC与HE结合)会更加偏向于使用BGV方案,而且BGV方案也相对最易懂。
推荐阅读资料
最初的BGV文章,但是主要关注于LWE上面。
关于BGV的两篇优化,作者都是(Gentry,Halevi,Smart),所以叫做GHS优化。
这篇文章是关于SIMD的,SIMD技术可以说是RLWE对于LWE的一个碾压性的优势之一了。作者是Smart和Vercauteren。
- Algorithms in HElib
- Bootstrapping for HElib
- Design and implementation of HElib : a homomorphic encryption library
上面三篇文章都是Halevi和Shoup写的,关于Helib中如何实现BGV方案并优化,以及如何对于BGV做Bootstrapping。
BGV方案介绍
密文形式
首先BGV最基本的加密形式是:
在这里我们只看对称加密,因为公钥加密与对称加密的密文形式是一致的。
对于LWE类型的密文来说,
首先有一些公开参数:明文模数
t
t
t,密文模数
q
q
q,向量维度
n
n
n
取私钥为
s
∈
Z
q
n
\mathbf{s} \in \Z_q^n
s∈Zqn,对于明文
m
∈
Z
t
m\in \Z_t
m∈Zt
选取
a
∈
Z
q
n
\mathbf{a}\in \Z_q^n
a∈Zqn,
b
=
⟨
a
,
s
⟩
+
m
+
t
e
m
o
d
q
b=\langle \mathbf{a},\mathbf{s}\rangle + m +te \bmod q
b=⟨a,s⟩+m+temodq。
e
e
e是从高斯分布中选取的整数。
令密文
c
=
(
b
,
a
)
c=(b,\mathbf{a})
c=(b,a)。
则解密为
先计算
μ
=
b
−
⟨
a
,
s
⟩
=
m
+
t
e
m
o
d
q
\mu = b- \langle \mathbf{a},\mathbf{s} \rangle = m+te \bmod q
μ=b−⟨a,s⟩=m+temodq。然后计算
m
=
[
μ
]
t
=
m
m=[\mu]_t=m
m=[μ]t=m。
这里的 ⟨ ⋅ ⟩ \langle \cdot \rangle ⟨⋅⟩为内积操作,对于 a = ( a 0 , . . . , a n − 1 ) , s = ( s 0 , . . . , s n − 1 ) \mathbf{a}=(a_0,...,a_{n-1}),\mathbf{s}=(s_0,...,s_{n-1}) a=(a0,...,an−1),s=(s0,...,sn−1)来说, ⟨ a , s ⟩ = a 0 s 0 + a 1 s 1 + ⋯ + a n − 1 s n − 1 ∈ Z \langle \mathbf{a},\mathbf{s}\rangle=a_0s_0+a_1s_1+\cdots+a_{n-1}s_{n-1}\in\Z ⟨a,s⟩=a0s0+a1s1+⋯+an−1sn−1∈Z。
[ μ ] t [\mu]_t [μ]t其实等价于 μ m o d t \mu \bmod t μmodt。
对于RLWE类型的密文来说,
公开参数为:明文模数
t
t
t,多项式空间
R
=
Z
[
X
]
/
X
n
+
1
\mathcal{R}=\Z[X]/X^n+1
R=Z[X]/Xn+1,以及系数模
q
q
q的多项式空间
R
q
=
Z
q
[
X
]
/
X
n
+
1
\mathcal{R}_q=\Z_q[X]/X^n+1
Rq=Zq[X]/Xn+1。
取私钥为
s
∈
R
q
s\in \mathcal{R}_q
s∈Rq,对于明文
m
∈
R
t
m\in R_t
m∈Rt:
选取
a
∈
R
q
,
b
=
a
s
+
m
+
t
e
∈
R
q
a\in \mathcal{R}_q,b=as+m+te \in \mathcal{R}_q
a∈Rq,b=as+m+te∈Rq,
e
e
e是一个系数满足高斯分布的多项式。
令密文为
c
=
(
b
,
a
)
c=(b,a)
c=(b,a)
则解密为
先计算
μ
=
b
−
a
s
=
m
+
t
e
∈
R
q
\mu = b-as=m+te\in \mathcal{R}_q
μ=b−as=m+te∈Rq,然后计算
m
=
[
μ
]
t
∈
R
t
m=[\mu]_t\in\mathcal{R}_t
m=[μ]t∈Rt。
这里可以看到RLWE类型的密文相对于LWE类型的密文来说的一个优势在于,一个LWE的密文的长度是 n + 1 n+1 n+1,对应的明文是 Z t \Z_t Zt内的,相当于有效信息只有1个,利用率为 1 n + 1 \frac{1}{n+1} n+11;而RLWE的密文长度是 2 n 2n 2n,对应的明文是 R t \mathcal{R}_t Rt内的,有效信息最多有 n n n个,利用率为 1 2 \frac{1}{2} 21。如果使用SIMD的技术的话,可以将这 n n n位都有效的利用起来。
关于SIMD的技术,SV的文章我还没有看,但现在BGV和BFV类型的SIMD应该都用的是INTT来做encoding的吧,可以参考一下CKKS的Encoding。思想是类似的。
噪声
注意到在解密过程中,是先得到了 m + t e m o d q m+te \bmod q m+temodq,然后再模 t t t得到 m m m的。这里一个很重要的条件就是 ( m + t e ) < q (m+te)<q (m+te)<q,BGV将 φ s ( c ) = b − a s = m + t e \varphi_s(c)=b-as=m+te φs(c)=b−as=m+te这一项称作噪声,一个很重要的条件就是噪声的大小要 < q <q <q。如果是一个中心取模的方案,还要额外地要求噪声的大小 < q 2 <\frac{q}{2} <2q。
Modulus Switching
注:后面的符号表示都是针对基于RLWE的BGV方案了。
感觉BGV里面最核心的技术应该就是Modulus Switching了,因为只有这个方案这么用,像Key Switching那种,基本所有同态方案都有使用。
为什么需要MS
首先,Modulus Switching是干什么的,直观上理解,modulus switching是将一个密文模数 q q q转换到另一个密文模数 q ′ q' q′上。
但这样有什么用处呢?
那首先要看一下乘法的密文噪声:
前面我们已经定义了,所谓的噪声就是
φ
s
(
c
)
=
(
m
+
t
e
)
\varphi_s(c)=(m+te)
φs(c)=(m+te),对于两个不同的密文,
c
1
=
E
n
c
(
m
1
)
,
c
2
=
E
n
c
(
m
2
)
c_1 = Enc(m_1),c_2=Enc(m_2)
c1=Enc(m1),c2=Enc(m2),
φ
(
c
1
)
=
m
1
+
t
e
1
,
φ
(
c
2
)
=
m
2
+
t
e
2
\varphi(c_1)=m_1+te_1,\varphi(c_2)=m_2+te_2
φ(c1)=m1+te1,φ(c2)=m2+te2。两个的乘法的噪声为
φ
(
c
1
c
2
)
=
φ
(
c
1
)
⋅
φ
(
c
2
)
=
(
m
1
+
t
e
1
)
(
m
2
+
t
e
2
)
=
m
1
m
2
⏟
<
t
2
+
t
(
m
1
e
2
+
m
2
e
1
)
⏟
<
t
2
∣
e
∣
+
t
2
e
1
e
2
⏟
<
t
2
∣
e
∣
2
\varphi(c_1c_2) = \varphi(c_1)\cdot \varphi(c_2)=(m_1+t e_1)(m_2+te_2) \\ =\underbrace{m_1m_2}_{<t^2} +\underbrace{t(m_1e_2+m_2e_1)}_{<t^2|e|}+\underbrace{t^2e_1e_2}_{<t^2|e|^2}
φ(c1c2)=φ(c1)⋅φ(c2)=(m1+te1)(m2+te2)=<t2
m1m2+<t2∣e∣
t(m1e2+m2e1)+<t2∣e∣2
t2e1e2
可以看到相比原来的噪声大小
φ
(
c
)
=
m
+
t
e
⏟
<
t
∣
e
∣
\varphi(c)=\underbrace{m+te}_{<t|e|}
φ(c)=<t∣e∣
m+te,
乘法之后的噪声是翻倍了。而如果我们需要正确解密的话,需要噪声大小
φ
(
c
)
<
q
/
/
(
φ
(
c
)
<
q
/
2
)
\varphi(c)<q//(\varphi(c)<q/2)
φ(c)<q//(φ(c)<q/2)。假设我们初始的噪声大小为
t
∣
e
∣
=
B
t|e|=B
t∣e∣=B,则乘法之后的噪声大小为
B
2
B^2
B2,再进行一次乘法变为
B
4
B^4
B4,进行
ℓ
\ell
ℓ次乘法之后噪声大小为
B
2
ℓ
B^{2^\ell}
B2ℓ。若要求
B
2
ℓ
<
q
B^{2^\ell}<q
B2ℓ<q,则最多做
ℓ
≈
log
2
(
log
B
(
q
)
)
−
1
\ell\approx \log_2(\log_B(q))-1
ℓ≈log2(logB(q))−1次乘法。
如何减少这种噪声的扩张呢?,其实BGV,BFV,CKKS给出了三种不同的解决方法,其中BGV和CKKS比较类似,都是把密文和模数同时减少(区别在于,CKKS缩小完模数之后会对明文产生影响,变为一个近似的结果;而BGV不会)。BFV则是一个scale invariant的方法,即模数不会变,通过乘法后除以一个扩张因子来保持噪声规模。
为什么模数减小噪声也会变小:考虑以下情况:
φ
(
c
)
=
m
+
t
e
m
o
d
q
,
φ
(
p
q
c
)
=
p
q
m
+
p
q
t
e
⏟
<
p
q
B
m
o
d
p
\varphi(c)=m+te \bmod q,\varphi(\frac{p}{q} c)=\underbrace{\frac{p}{q}m+\frac{p}{q}te}_{<\frac{p}{q}B} \bmod p
φ(c)=m+temodq,φ(qpc)=<qpB
qpm+qptemodp
通过对密文整体进行缩放,模数从
q
q
q变为
p
p
p,噪声从
B
B
B变为
p
q
B
\frac{p}{q}B
qpB,那这里疑问就产生了:噪声和模数的比例关系没变啊,还是
B
q
=
p
q
B
p
\frac{B}{q}=\frac{\frac{p}{q}B}{p}
qB=pqpB,为什么说减少了噪声呢?
这里举个例子:比如
B
=
2
,
q
=
131072
,
p
=
1
2
q
=
65536
B=2,q=131072,p=\frac{1}{2}q=65536
B=2,q=131072,p=21q=65536。那么不使用MS的噪声扩张为
2
m
o
d
131072
→
m
u
l
t
i
p
l
y
4
m
o
d
131072
→
m
u
l
t
i
p
l
y
16
m
o
d
131072
→
m
u
l
t
i
p
l
y
256
m
o
d
131072
→
m
u
l
t
i
p
l
y
65536
m
o
d
131072
→
m
u
l
t
i
p
l
y
(
×
)
6553
6
2
m
o
d
131072
2 \bmod 131072 \stackrel{multiply}{\to}4 \bmod 131072 \stackrel{multiply}{\to} 16 \bmod 131072\stackrel{multiply}{\to} 256 \bmod 131072\stackrel{multiply}{\to} 65536 \bmod 131072\stackrel{multiply(\times)}{\to} 65536^2 \bmod 131072
2mod131072→multiply4mod131072→multiply16mod131072→multiply256mod131072→multiply65536mod131072→multiply(×)655362mod131072
总共能做4层乘法。
如果我们在第一次乘法之后做一个MS,即将
B
→
p
q
B
B\to \frac{p}{q}B
B→qpB,
q
→
p
q\to p
q→p。则噪声扩张为
2
m
o
d
131072
→
m
u
l
t
i
p
l
y
4
m
o
d
131072
→
M
S
2
m
o
d
65536
→
m
u
l
t
i
p
l
y
4
m
o
d
65536
→
m
u
l
t
i
p
l
y
16
m
o
d
65536
→
m
u
l
t
i
p
l
y
256
m
o
d
65536
→
m
u
l
t
i
p
l
y
65536
m
o
d
65536
2 \bmod 131072 \stackrel{multiply}{\to} 4 \bmod 131072\stackrel{MS}{\to} 2 \bmod 65536\stackrel{multiply}{\to} 4 \bmod 65536\stackrel{multiply}{\to} 16 \bmod 65536\stackrel{multiply}{\to} 256 \bmod 65536\stackrel{multiply}{\to} 65536 \bmod 65536
2mod131072→multiply4mod131072→MS2mod65536→multiply4mod65536→multiply16mod65536→multiply256mod65536→multiply65536mod65536
能做5层乘法。
那再考虑另一种情况,每次乘法完都做一次modulus switching,将
B
→
1
2
B
,
q
→
1
2
q
B\to \frac{1}{2}B,q \to \frac{1}{2}q
B→21B,q→21q:
则噪声扩张变为:
2
m
o
d
131072
→
m
u
l
t
i
p
l
y
4
m
o
d
131072
→
M
S
2
m
o
d
65536
→
m
u
l
t
i
p
l
y
4
m
o
d
65536
→
M
S
2
m
o
d
32768
→
m
u
l
t
i
p
l
y
4
m
o
d
32768
→
M
S
2
m
o
d
16384
→
m
u
l
t
i
p
l
y
4
m
o
d
16384
→
M
S
2
m
o
d
8192
→
m
u
l
t
i
p
l
y
4
m
o
d
8192
→
M
S
2
m
o
d
4096
→
m
u
l
t
i
p
l
y
4
m
o
d
4096
→
M
S
2
m
o
d
2048
→
m
u
l
t
i
p
l
y
4
m
o
d
2048
→
M
S
2
m
o
d
1024
→
m
u
l
t
i
p
l
y
4
m
o
d
1024
→
M
S
2
m
o
d
512
→
m
u
l
t
i
p
l
y
4
m
o
d
512
→
M
S
2
m
o
d
256
→
m
u
l
t
i
p
l
y
4
m
o
d
256
→
M
S
2
m
o
d
128
→
m
u
l
t
i
p
l
y
4
m
o
d
128
→
M
S
2
m
o
d
64
→
m
u
l
t
i
p
l
y
4
m
o
d
64
→
M
S
2
m
o
d
32
→
m
u
l
t
i
p
l
y
4
m
o
d
32
→
M
S
2
m
o
d
16
→
m
u
l
t
i
p
l
y
4
m
o
d
16
→
M
S
2
m
o
d
8
→
m
u
l
t
i
p
l
y
4
m
o
d
8
→
M
S
2
m
o
d
4
→
m
u
l
t
i
p
l
y
(
×
)
4
m
o
d
4
2 \bmod 131072 \stackrel{multiply}{\to} 4 \bmod 131072\stackrel{MS}{\to} \\2 \bmod 65536 \stackrel{multiply}{\to} 4 \bmod 65536 \stackrel{MS}{\to} \\2 \bmod 32768\stackrel{multiply}{\to} 4 \bmod 32768\stackrel{MS}{\to} \\ 2 \bmod 16384\stackrel{multiply}{\to} 4 \bmod 16384\stackrel{MS}{\to} \\ 2 \bmod 8192\stackrel{multiply}{\to} 4 \bmod 8192\stackrel{MS}{\to} \\ 2 \bmod 4096\stackrel{multiply}{\to} 4 \bmod 4096\stackrel{MS}{\to} \\ 2 \bmod 2048\stackrel{multiply}{\to} 4 \bmod 2048\stackrel{MS}{\to} \\ 2 \bmod 1024\stackrel{multiply}{\to} 4 \bmod 1024\stackrel{MS}{\to}\\ 2 \bmod 512\stackrel{multiply}{\to} 4 \bmod 512\stackrel{MS}{\to}\\ 2 \bmod 256\stackrel{multiply}{\to} 4 \bmod 256\stackrel{MS}{\to}\\ 2 \bmod 128\stackrel{multiply}{\to} 4 \bmod 128\stackrel{MS}{\to}\\ 2 \bmod 64\stackrel{multiply}{\to} 4 \bmod 64\stackrel{MS}{\to}\\ 2 \bmod 32\stackrel{multiply}{\to} 4 \bmod 32\stackrel{MS}{\to}\\ 2 \bmod 16\stackrel{multiply}{\to} 4 \bmod 16\stackrel{MS}{\to}\\ 2 \bmod 8\stackrel{multiply}{\to} 4 \bmod 8\stackrel{MS}{\to}\\ 2 \bmod 4\stackrel{multiply(\times)}{\to} 4 \bmod 4
2mod131072→multiply4mod131072→MS2mod65536→multiply4mod65536→MS2mod32768→multiply4mod32768→MS2mod16384→multiply4mod16384→MS2mod8192→multiply4mod8192→MS2mod4096→multiply4mod4096→MS2mod2048→multiply4mod2048→MS2mod1024→multiply4mod1024→MS2mod512→multiply4mod512→MS2mod256→multiply4mod256→MS2mod128→multiply4mod128→MS2mod64→multiply4mod64→MS2mod32→multiply4mod32→MS2mod16→multiply4mod16→MS2mod8→multiply4mod8→MS2mod4→multiply(×)4mod4
总计有15层乘法。
总结:
由此可见,MS不改变噪声和模数的比例关系,但是噪声的扩张速度是被减少了的。每次缩小噪声从而导致模数变小,在BGV里面称作密文到达了下一层,也就如为上面的写法一样,一层拥有对应模数。通过模数缩减可以使原本
ℓ
≈
log
2
(
log
B
(
q
)
)
−
1
\ell\approx \log_2(\log_B(q)) -1
ℓ≈log2(logB(q))−1次乘法。变为
ℓ
≈
(
log
B
(
q
)
−
1
\ell\approx (\log_B(q) -1
ℓ≈(logB(q)−1次乘法。
如何做MS
其实在上面的例子里面已经有设计到如何做MS的问题了,对于一个密文
c
=
(
a
,
b
)
c=(a,b)
c=(a,b)。对于
L
L
L层乘法,取多个
Q
:
{
Q
0
,
Q
1
,
.
.
.
,
Q
L
}
Q:\{Q_0,Q_1,...,Q_L\}
Q:{Q0,Q1,...,QL},满足
Q
i
+
1
≈
B
⋅
Q
i
Q_{i+1}\approx B\cdot Q_i
Qi+1≈B⋅Qi的关系。
modulus switching:
c
=
(
a
,
b
)
m
o
d
Q
L
c=(a,b) \bmod Q_L
c=(a,b)modQL。
Modulus Switch的结果为 c ′ c' c′, c ′ c' c′是距离 Q L − 1 Q L c \frac{Q_{L-1}}{Q_{L}}c QLQL−1c很接近的一个密文,且要满足 c ′ = c m o d t c' = c \bmod t c′=cmodt。
那么在 Q i = 1 m o d t Q_i =1 \bmod t Qi=1modt的情况下, ϕ ( c ′ ) m o d t = ϕ ( c ) m o d t = m \phi(c') \bmod t = \phi(c) \bmod t = m ϕ(c′)modt=ϕ(c)modt=m。
这里原本的内容有误,感谢评论区指出,本来凭着记忆写了,没去看文章。对如何找这样一个很接近的密文好奇的小伙伴可以看这篇文章。
关于KeySwitching/Relinearization
KeySwitching其实不算是BGV特有的技术,所以不准备放在BGV里面介绍。这里说一下大概的思路。
对于一个用
s
s
s加密的密文
c
c
c来说,他由两部分组成,
(
a
,
b
)
(a,b)
(a,b),其中
b
=
a
s
+
m
+
t
e
b=as+m+te
b=as+m+te。
如果说我要将这个密文转为由密钥
s
′
s'
s′加密,则我先使用
s
′
s'
s′加密
s
s
s,得到
k
s
k
=
(
a
k
,
b
k
)
ksk=(a_k,b_k)
ksk=(ak,bk)其中
b
k
=
a
k
s
′
+
s
+
t
e
k
b_k=a_ks'+s+te_k
bk=aks′+s+tek。
key switch可以理解为得到
c
′
=
(
a
′
,
b
′
)
=
(
0
,
b
)
−
a
⋅
(
a
k
,
b
k
)
=
(
−
a
⋅
a
k
,
b
−
a
⋅
b
k
)
c'=(a',b')=(0,b)-a\cdot(a_k,b_k)=(-a\cdot a_k,b-a\cdot b_k)
c′=(a′,b′)=(0,b)−a⋅(ak,bk)=(−a⋅ak,b−a⋅bk)。
对
(
a
′
,
b
′
)
(a',b')
(a′,b′)用
s
′
s'
s′解密得到
b
′
−
a
′
s
′
=
b
−
a
⋅
b
k
+
a
⋅
a
k
⋅
s
′
=
b
−
a
(
a
k
s
′
+
s
+
t
e
k
)
+
(
a
⋅
a
k
⋅
s
′
)
=
b
−
a
(
s
+
t
e
k
)
=
b
−
a
s
+
a
t
e
k
=
m
+
t
e
+
a
t
e
k
=
m
+
t
e
′
\begin{aligned} b'-a's' &=b-a\cdot b_k+a\cdot a_k \cdot s' \\&=b-a(a_ks'+s+te_k)+(a\cdot a_k\cdot s') \\&=b-a(s+te_k) \\&=b-as+ate_k \\&=m+te+ate_{k} \\&=m+te' \end{aligned}
b′−a′s′=b−a⋅bk+a⋅ak⋅s′=b−a(aks′+s+tek)+(a⋅ak⋅s′)=b−a(s+tek)=b−as+atek=m+te+atek=m+te′
所以
c
′
c'
c′是一个由
s
′
s'
s′加密的密文。
重线性化可以类似的理解一下,乘法之后的密文变为由 s 2 s^2 s2加密的密文,所以将 s 2 s^2 s2keyswitch回 s s s,就可以继续使用 s s s解密了。
小尾巴
本人正在入门密码学,欢迎各位同学或老师加我微信交流:shenghua-adije