本文主要记录隐私计算中的同态加密(Homomorphic Encryption,HE)技术,包括部分同态加密(RSA、GM、ElGamal、Paillier)、近似同态加密(BGN)、有限级数全同态加密和全同态加密(DGHV、BGV、BFV、CKKS、GSW、FHEW、TFHE)等技术,仅供参考

由于篇幅限制,将同态加密技术的介绍分为四个部分,第一部分讲述部分同态加密和近似同态加密技术;第二部分讲述 Bootstrapping 和 DGHV、BGV 全同态加密方案;第三部分讲述 SIMD 打包技术与 BFV、CKKS 全同态加密方案;第四部分讲述 GSW、FHEW、TFHE 全同态加密方案。

在本文中为简化表示,将加密记为 Enc(⋅)Enc(\cdot)Enc(),解密记为 Dec(⋅)Dec(\cdot)Dec(),不标明使用的公钥和私钥代表只有一对公私钥。本文中介绍的加密方案基本都依赖于各种计算难题,在之前的文章中有过介绍。

四、(有限级数)全同态加密(续)

4. BFV 加密方案

Fan 和 Vercauteren 在 Brakerski 的研究基础上提出了 BFV 方案[12]^{[12]}[12],该方案省去了 BGV 方案中多个模数的复杂构造,且降低了同态乘法计算产生的噪声。BFV 方案也利用 RLWE 假设。

在介绍 BFV 方案时,除了范数 ∣∣⋅∣∣||\cdot||∣∣∣∣ 默认为无穷范数(最大值)外,其余设置均采用和上述 BGV 方案一致的符号标记。此外,记 rq(x)r_q(x)rq(x)xxxqqq正常取模结果(即结果取值满足 rq(x)∈[0,q−1]r_q(x)\in[0,q-1]rq(x)[0,q1])。

⌊x⌋\lfloor x \rfloorx 为向下取整,⌈x⌉\lceil x \rceilx 为向上取整,⌊x⌉\lfloor x \rceilx 为四舍五入(取离得最近的整数)。

设置消息空间为多项式环 m∈Zt[x]/(xd+1)m\in\mathbb{Z}_t[x]/(x^d+1)mZt[x]/(xd+1) ,简记为 m∈Rtm\in R_tmRt


4.1 密钥生成算法

这里为简化理解省略了安全参数的要求,详细信息可以参考论文。

  1. 随机选取模数 q>tq\gt tq>t,不要求 q,tq,tq,t 为素数,也不要求它们互素。计算 Δ=⌊qt⌋\Delta = \lfloor \frac{q}{t} \rfloorΔ=tq,即 q=Δ⋅t+rt(q)q = \Delta \cdot t + r_t(q)q=Δt+rt(q)。通常在 BFV 的优化中会设置 t∣qt | qtq,这里按照一般情况讨论。

  2. 随机选取符合 RLWE 问题的 a,s,e∈Rqa,s,e\in R_{q}a,s,eRq,并计算 b=[−(as+e)]qb=[-(as+e)]_{q}b=[(as+e)]q。(可以随机选取,满足 ∣∣s∣∣=1||s||=1∣∣s∣∣=1,同时设 ∣∣e∣∣≤B||e|| \le B∣∣e∣∣B)。

  3. 公钥为 a,ba,ba,b,私钥为 sss

4.2 加密算法

对于明文 m∈Rtm\in R_tmRt,随机选取 u,e0,e1∈RqLu,e_0,e_1\in R_{q_L}u,e0,e1RqL,其中 ∣∣u∣∣=1||u||=1∣∣u∣∣=1,且 e0,e1e_0,e_1e0,e1 满足 ∣∣e0∣∣≤B,∣∣e1∣∣≤B||e_0||\le B,||e_1|| \le B∣∣e0∣∣B,∣∣e1∣∣B小噪声分布中采样(后续噪声不特殊说明都如此采样)。使用公钥加密过程如下:

c⃗=Enc(m)=(c0,c1)=([Δm+bu+e0]q,[au+e1]q) \vec{c}=Enc(m)=(c_0,c_1)=([\Delta m+bu+e_0]_{q},[au+e_1]_{q}) c =Enc(m)=(c0,c1)=([Δm+bu+e0]q,[au+e1]q)

得到的密文 c⃗\vec{c}c 可以看作是一个元素为多项式的二维向量。

4.3 解密算法

可以把私钥包装为一个二维向量 s⃗=(1,s)\vec{s}=(1,s)s =(1,s),使用该私钥解密过程如下:

m=Dec(c⃗)=[⌊t⋅[c⃗⋅s⃗]qq⌉]t=[⌊t⋅[c0+c1⋅s]qq⌉]t m = Dec(\vec{c})= [\lfloor \frac{t\cdot[\vec{c}\cdot\vec{s}]_{q}}{q} \rceil]_t = [\lfloor \frac{t\cdot[c_0+c_1\cdot s]_{q}}{q} \rceil]_t m=Dec(c )=[⌊qt[c s ]q]t=[⌊qt[c0+c1s]q]t


正确性

可以观察到在解密时:

[c0+c1⋅s]q=Δm+v+rq [c_0+c_1\cdot s]_{q}=\Delta m + v + rq [c0+c1s]q=Δm+v+rq

其中 rrr 为整数,代表模 qqq 运算增加/减少的 qqq 的个数,v=eu+e0+e1sv=eu+e_0+e_1sv=eu+e0+e1s 表示若干小噪声之和,考虑到 ∣∣u∣∣=∣∣s∣∣=1||u||=||s||=1∣∣u∣∣=∣∣s∣∣=1,则 ∣∣v∣∣≤γR∣∣e∣∣∣∣u∣∣+∣∣e0∣∣+γR∣∣e1∣∣∣∣s∣∣=(2γR+1)B||v||\le \gamma_R ||e||||u||+||e_0|| + \gamma_R||e_1||||s|| =(2\gamma_R+1)B∣∣v∣∣γR∣∣e∣∣∣∣u∣∣+∣∣e0∣∣+γR∣∣e1∣∣∣∣s∣∣=(2γR+1)B。此时有:

⌊t⋅[c0+c1⋅s]qq⌉=m+tq(v−ϵm)+rt \lfloor \frac{t\cdot[c_0+c_1\cdot s]_{q}}{q} \rceil=m+\frac{t}{q}(v-\epsilon m) +rt qt[c0+c1s]q=m+qt(vϵm)+rt

其中,ϵ=qt−Δ=rt(q)t<1\epsilon =\frac{q}{t} - \Delta= \frac{r_t(q)}{t}\lt1ϵ=tqΔ=trt(q)<1,显然要解密成功,需满足 tq∣∣v−ϵm∣∣<12\frac{t}{q}||v-\epsilon m||<\frac{1}{2}qt∣∣vϵm∣∣<21 使得四舍五入消去该项,从而有:

[⌊t⋅[c0+c1⋅s]qq⌉]t=[m+rt]t=m [\lfloor \frac{t\cdot[c_0+c_1\cdot s]_{q}}{q} \rceil]_t= [m +rt]_t=m [⌊qt[c0+c1s]q]t=[m+rt]t=m

正确性成立。可以看出噪声大小主要取决于 ∣∣v∣∣||v||∣∣v∣∣,应当综合安全和噪声影响合理设置参数。

安全性

由于解决 RLWE 问题是困难的,BFV 方案公开 a,ba,ba,b 作为公钥不会泄露 sss 的取值,且在加密时 u,e0,e1∈Rqu,e_0,e_1\in R_{q}u,e0,e1Rq 都是随机选取的,可以认为 BFV 方案是安全的。

加法同态性

BFV 加密方案具有加法同态性,可以验证:

Enc(m0)+Enc(m1)=[c⃗0+c⃗1]q=(m0+m1+b(u0+u1)+e00+e01,a(u0+u1)+e10+e11)=Enc(m0+m1) \begin{align} Enc(m_0)+Enc(m_1)&=[\vec{c}_0+\vec{c}_1]_{q} \nonumber \\ &=\left(m_0+m_1+b(u_0+u_1)+e_{00}+e_{01},a(u_0+u_1)+e_{10}+e_{11}\right) \nonumber \\ &= Enc(m_0+m_1) \nonumber \end{align} Enc(m0)+Enc(m1)=[c 0+c 1]q=(m0+m1+b(u0+u1)+e00+e01,a(u0+u1)+e10+e11)=Enc(m0+m1)

且噪声增长为线性:

[(c⃗0+c⃗1)s⃗]q=Δ(m0+m1)+v0+v1+r0q=Δ[m0+m1]t+v0+v1+r0q+r1tΔ=Δ[m0+m1]t+v0+v1+r1(tΔ−q)+q(r0+r1) \begin{align} [(\vec{c}_0+\vec{c}_1)\vec{s}]_{q}&=\Delta(m_0+m_1) + v_0+v_1 +r_0q\nonumber \\ &=\Delta[m_0+m_1]_t + v_0+v_1 +r_0q +r_1t\Delta \nonumber \\ &=\Delta[m_0+m_1]_t + v_0+v_1 +r_1(t\Delta - q)+q(r_0+r_1) \nonumber \end{align} [(c 0+c 1)s ]q=Δ(m0+m1)+v0+v1+r0q=Δ[m0+m1]t+v0+v1+r0q+r1tΔ=Δ[m0+m1]t+v0+v1+r1(tΔq)+q(r0+r1)

其中,噪声为 v0+v1+r1(tΔ−q)+q(r0+r1)v_0+v_1 +r_1(t\Delta - q)+q(r_0+r_1)v0+v1+r1(tΔq)+q(r0+r1),由于 ∣∣r1∣∣≤1||r_1||\le 1∣∣r1∣∣1(因为 m0,m1∈Rtm_0,m_1\in R_tm0,m1Rt∣∣m0+m1∣∣<2t||m_0+m_1||\lt 2t∣∣m0+m1∣∣<2t) 且 ∣∣tΔ−q∣∣<t||t\Delta - q||\lt t∣∣tΔq∣∣<t,因此噪声最多额外增长 ttt

乘法同态性

BFV 加密方案具有乘法同态性。记两个明文 m0,m1m_0,m_1m0,m1 对应的密文为 c⃗0=Enc(m0)=(c00,c10)\vec{c}_0=Enc(m_0)=(c_{00},c_{10})c 0=Enc(m0)=(c00,c10)c⃗1=Enc(m1)=(c01,c11)\vec{c}_1=Enc(m_1)=(c_{01},c_{11})c 1=Enc(m1)=(c01,c11),不妨设:

c⃗0⋅s⃗=Δm0+v0+r0qc⃗1⋅s⃗=Δm1+v1+r1qtq⋅(c⃗0⋅s⃗)⋅(c⃗1⋅s⃗)=c0+c1s+c2s2+ra \vec{c}_0 \cdot \vec{s}=\Delta m_0+v_0 +r_0q\\ \vec{c}_1 \cdot \vec{s}=\Delta m_1+v_1 +r_1q\\ \frac{t}{q}\cdot(\vec{c}_0 \cdot \vec{s}) \cdot (\vec{c}_1 \cdot \vec{s})=c_0+c_1s+c_2s^2 +r_a c 0s =Δm0+v0+r0qc 1s =Δm1+v1+r1qqt(c 0s )(c 1s )=c0+c1s+c2s2+ra

其中易证 ∣∣r0∣∣<γR⋅∣∣s∣∣||r_0||\lt \gamma_R\cdot||s||∣∣r0∣∣<γR∣∣s∣∣,上述第三个等式的 rar_ara 为小数,且系数满足方程:

c0=⌊t(c00c01)q⌉c1=⌊t(c00c11+c10c01)q⌉c2=⌊t(c10c11)q⌉ c_0=\lfloor\frac{t(c_{00}c_{01})}{q} \rceil \\ c_1=\lfloor\frac{t(c_{00}c_{11}+c_{10}c_{01})}{q} \rceil \\ c_2=\lfloor\frac{t(c_{10}c_{11})}{q} \rceil c0=qt(c00c01)c1=qt(c00c11+c10c01)c2=qt(c10c11)

证明可参考 BGV 方案中同态乘法计算中 c0,c1,c2c_0,c_1,c_2c0,c1,c2 的计算方式。由此可以看出 rar_ara 其实是 c0,c1,c2c_0,c_1,c_2c0,c1,c2 三项四舍五入舍掉的小数项,属于舍入误差,由于每项舍入最大为 12\frac{1}{2}21,因此满足:

∣∣ra∣∣≤12(1+γR∣∣s∣∣+γR2∣∣s∣∣2)<12(1+γR∣∣s∣∣)2 ||r_a|| \le \frac{1}{2}(1+\gamma_R||s||+\gamma_R^2||s||^2)\lt \frac{1}{2}(1+\gamma_R||s||)^2 ∣∣ra∣∣21(1+γR∣∣s∣∣+γR2∣∣s2)<21(1+γR∣∣s∣∣)2

由于:

(c⃗0⋅s⃗)⋅(c⃗1⋅s⃗)=(Δm0+v0+r0q)⋅(Δm1+v1+r1q)=Δ2m0m1+Δ(m0v1+m1v0)+v0v1+q(v0r1+v1r0)+qΔ(m0r1+m1r0)+q2r0r1) \begin{align} (\vec{c}_0 \cdot \vec{s}) \cdot (\vec{c}_1 \cdot \vec{s})&=(\Delta m_0+v_0 +r_0q)\cdot (\Delta m_1+v_1+r_1q) \nonumber \\ &=\Delta^2m_0m_1+\Delta(m_0v_1+m_1v_0) + v_0v_1+q(v_0r_1+v_1r_0)+q\Delta(m_0r_1+m_1r_0)+q^2r_0r_1) \nonumber \end{align} (c 0s )(c 1s )=(Δm0+v0+r0q)(Δm1+v1+r1q)=Δ2m0m1+Δ(m0v1+m1v0)+v0v1+q(v0r1+v1r0)+qΔ(m0r1+m1r0)+q2r0r1)

ϵ=qt−Δ=rt(q)t<1\epsilon =\frac{q}{t} - \Delta= \frac{r_t(q)}{t}\lt1ϵ=tqΔ=trt(q)<1,且 m0m1=[m0m1]t+rmtm_0m_1=[m_0m_1]_t+r_mtm0m1=[m0m1]t+rmt 以及 v0v1=[v0v1]Δ+rvΔv_0v_1=[v_0v_1]_\Delta+r_v\Deltav0v1=[v0v1]Δ+rvΔ,显然有 ∣∣rm∣∣<γR∣∣m0∣∣∣∣m1∣∣t=γRt4||r_m||\lt \frac{\gamma_R||m_0||||m_1||}{t}=\frac{\gamma_Rt}{4}∣∣rm∣∣<tγR∣∣m0∣∣∣∣m1∣∣=4γRt,同理 ∣∣rv∣∣<γRE2Δ||r_v|| \lt \frac{\gamma_RE^2}{\Delta}∣∣rv∣∣<ΔγRE2(其中 ∣∣vi∣∣<E<Δ2||v_i||\lt E\lt\frac{\Delta}{2}∣∣vi∣∣<E<2Δ),因此有如下方程成立:

tq⋅(c⃗0⋅s⃗)⋅(c⃗1⋅s⃗)=Δm0m1+m0v1+m1v0+tqv0v1+t(v0r1+v1r0)+tΔ(m0r1+m1r0)+qtr0r1−ϵ(Δm0m1+m0v1+m1v0)=Δ[m0m1]t+m0v1+m1v0+tq[v0v1]Δ+t(v0r1+v1r0)+(q−rt(q))(rm+m0r1+m1r0)+rv+qtr0r1−ϵ(Δm0m1+m0v1+m1v0+rv) \begin{align} \frac{t}{q}\cdot(\vec{c}_0 \cdot \vec{s}) \cdot (\vec{c}_1 \cdot \vec{s})&= \Delta m_0m_1+m_0v_1+m_1v_0+\frac{t}{q}v_0v_1+t(v_0r_1+v_1r_0)+t\Delta(m_0r_1+m_1r_0)+qtr_0r_1-\epsilon(\Delta m_0m_1 + m_0v_1+m_1v_0) \nonumber \\ &=\Delta[m_0m_1]_t+m_0v_1+m_1v_0+\frac{t}{q}[v_0v_1]_\Delta +t(v_0r_1+v_1r_0)+(q-r_t(q))(r_m+m_0r_1+m_1r_0) + r_v+qtr_0r_1-\epsilon(\Delta m_0m_1 + m_0v_1+m_1v_0 + r_v) \nonumber \end{align} qt(c 0s )(c 1s )=Δm0m1+m0v1+m1v0+qtv0v1+t(v0r1+v1r0)+tΔ(m0r1+m1r0)+qtr0r1ϵ(Δm0m1+m0v1+m1v0)=Δ[m0m1]t+m0v1+m1v0+qt[v0v1]Δ+t(v0r1+v1r0)+(qrt(q))(rm+m0r1+m1r0)+rv+qtr0r1ϵ(Δm0m1+m0v1+m1v0+rv)

注意,只有算到当前这一步才可以对 qqq 取模,否则会影响正确性(因为要乘上 tq\frac{t}{q}qt 这个小数,不能提前取模)。代入前式,有:

tq⋅(c⃗0⋅s⃗)⋅(c⃗1⋅s⃗)=c0+c1s+c2s2+ra=Δ[m0m1]t+m0v1+m1v0+t(v0r1+v1r0)+(q−rt(q))(rm+m0r1+m1r0)+rv+qtr0r1+rr \begin{align} \frac{t}{q}\cdot(\vec{c}_0 \cdot \vec{s}) \cdot (\vec{c}_1 \cdot \vec{s})&=c_0+c_1s+c_2s^2 +r_a \nonumber\\ &=\Delta[m_0m_1]_t+m_0v_1+m_1v_0 +t(v_0r_1+v_1r_0)+(q-r_t(q))(r_m+m_0r_1+m_1r_0) + r_v+qtr_0r_1 +r_r\nonumber \end{align} qt(c 0s )(c 1s )=c0+c1s+c2s2+ra=Δ[m0m1]t+m0v1+m1v0+t(v0r1+v1r0)+(qrt(q))(rm+m0r1+m1r0)+rv+qtr0r1+rr

其中 rr=tq[v0v1]Δ−ϵ(Δm0m1+m0v1+m1v0+rv)r_r=\frac{t}{q}[v_0v_1]_\Delta -\epsilon(\Delta m_0m_1 + m_0v_1+m_1v_0 + r_v)rr=qt[v0v1]Δϵ(Δm0m1+m0v1+m1v0+rv) 为小数,且有:

∣∣rr∣∣<tq⋅Δ2+tq⋅(γRΔ(t2)2+γRt2⋅Δ2+γRt2⋅Δ2+γRΔ4)<12+γR(t+12)2 \begin{align} ||r_r||&\lt \frac{t}{q}\cdot \frac{\Delta}{2} +\frac{t}{q}\cdot (\gamma_R\Delta (\frac{t}{2})^2+ \gamma_R\frac{t}{2}\cdot\frac{\Delta}{2}+ \gamma_R\frac{t}{2}\cdot\frac{\Delta}{2}+\frac{\gamma_R\Delta}{4} )\nonumber \\ &\lt\frac{1}{2}+\gamma_R(t+\frac{1}{2})^2 \nonumber \end{align} ∣∣rr∣∣<qt2Δ+qt(γRΔ(2t)2+γR2t2Δ+γR2t2Δ+4γRΔ)<21+γR(t+21)2

将小数合并后取模,得到:

[c0+c1s+c2s2]q=Δ[m0m1]t+m0v1+m1v0+t(v0r1+v1r0)−rt(q)(rm+m0r1+m1r0)+rv+rr−ra=Δ[m0m1]t+v2 \begin{align} [c_0+c_1s+c_2s^2]_q &=\Delta[m_0m_1]_t+m_0v_1+m_1v_0+t(v_0r_1+v_1r_0)-r_t(q)(r_m+m_0r_1+m_1r_0) + r_v+r_r-r_a \nonumber \\ &=\Delta[m_0m_1]_t + v_2 \nonumber \end{align} [c0+c1s+c2s2]q=Δ[m0m1]t+m0v1+m1v0+t(v0r1+v1r0)rt(q)(rm+m0r1+m1r0)+rv+rrra=Δ[m0m1]t+v2

其中:

v2=(m0v1+m1v0)+t(v0r1+v1r0)−rt(q)(rm+m0r1+m1r0)+rv+rr−ra v_2=(m_0v_1+m_1v_0)+t(v_0r_1+v_1r_0)-r_t(q)(r_m+m_0r_1+m_1r_0) + r_v+r_r-r_a v2=(m0v1+m1v0)+t(v0r1+v1r0)rt(q)(rm+m0r1+m1r0)+rv+rrra

经过大量放缩,可以得出噪声上界为:

∣∣v2∣∣<γRtE+γR2tE∣∣s∣∣+tγR(t4+γR∣∣s∣∣)+γRE2+γR(t+12)2+12+(γR∣∣s∣∣+1)22<γRtE(γR∣∣s∣∣+1)+t2γR2(∣∣s∣∣+1)2+γRtE(γR∣∣s∣∣+1)+12t2γR2(∣∣s∣∣+1)2+t2γR2(∣∣s∣∣+1)2=2γRtE(γR∣∣s∣∣+1)+2t2γR2(∣∣s∣∣+1)2 \begin{align} ||v_2|| &\lt \gamma_RtE+\gamma_R^2tE||s||+t\gamma_R(\frac{t}{4}+\gamma_R||s||)+\frac{\gamma_RE}{2}+\gamma_R(t+\frac{1}{2})^2+\frac{1}{2}+\frac{(\gamma_R||s||+1)^2}{2}\nonumber \\ &\lt \gamma_RtE(\gamma_R||s||+1)+t^2\gamma_R^2(||s||+1)^2+\gamma_RtE(\gamma_R||s||+1)+\frac{1}{2}t^2\gamma_R^2(||s||+1)^2+t^2\gamma_R^2(||s||+1)^2 \nonumber \\ &= 2\gamma_RtE(\gamma_R||s||+1)+2t^2\gamma_R^2(||s||+1)^2 \nonumber \end{align} ∣∣v2∣∣<γRtE+γR2tE∣∣s∣∣+tγR(4t+γR∣∣s∣∣)+2γRE+γR(t+21)2+21+2(γR∣∣s∣∣+1)2<γRtE(γR∣∣s∣∣+1)+t2γR2(∣∣s∣∣+1)2+γRtE(γR∣∣s∣∣+1)+21t2γR2(∣∣s∣∣+1)2+t2γR2(∣∣s∣∣+1)2=2γRtE(γR∣∣s∣∣+1)+2t2γR2(∣∣s∣∣+1)2

由于设置 ∣∣s∣∣=1||s||=1∣∣s∣∣=1,可以从上式看出,经过同态乘法计算,噪声从 EEE 增长到大约 2γR2tE2\gamma_R^2tE2γR2tE,并不像 BGV 方案中平方增长,这也是 BFV 方案的主要创新点。BGV 方案中每做一次乘法都需要进行一次模数转换,而 BFV 中噪声增长并非平方级别,不进行模数转换。

BFV 方案之所以噪声不是平方增长,是因为 BFV 在得到 v2v_2v2 时进行了一次放缩(乘 tq\frac{t}{q}qt),通过该放缩可以粗略理解为直接减少了一个次方的噪声,因此相较于 BGV 方案噪声减少很多。

但类似于 BGV 方案,BFV 方案同态乘法运算后密文也会变成三维向量 (c0,c1,c2)(c_0,c_1,c_2)(c0,c1,c2),需要通过 Relinearisation 转换回二维向量。一个可行的办法在 BGV 方案已经讲述过了(BGV同态乘法中的密钥转换),BFV 还额外提供了另一个解决方法,通过类似模数转换的操作来实现,具体地说,该操作实现如下转换:

[c0+c1s+c2s2]q=[c0′+c1′s+r]q [c_0+c_1s+c_2s^2]_q=[c_0'+c_1's+r]_q [c0+c1s+c2s2]q=[c0+c1s+r]q

其中 rrr 为转换引入的噪声,值很小。该方法通过选择一个随机数 p>qp\gt qp>q,然后在 RpqR_{pq}Rpq 密文空间中对 ps2ps^2ps2 进行加密,得到:

rlk=([−(as+e)+ps2]pq,a) rlk=([-(as+e)+ps^2]_{pq},a) rlk=([(as+e)+ps2]pq,a)

其中,a∈Rpqa\in R_{pq}aRpq∣∣e∣∣<Bk||e||\lt B_k∣∣e∣∣<BkBkB_kBk 的选取需要满足一些条件,在论文中给出了公式)。随后可以得到 c2s2c_2s^2c2s2 的密文(不直接加密 c2s2c_2s^2c2s2 的原因是在预处理阶段不知道 c2c_2c2 的取值):

(c20,c21)=([⌊c2rlk[0]p⌉]q,[⌊c2rlk[1]p⌉]q) (c_{20},c_{21})=([\lfloor \frac{c_2rlk[0]}{p} \rceil]_q,[\lfloor \frac{c_2rlk[1]}{p}\rceil]_q) (c20,c21)=([⌊pc2rlk[0]]q,[⌊pc2rlk[1]]q)

该操作的正确性可以按照 BGV 中的模数转换理解(但不完全一样),为了方便理解,可以堪称上述密文计算相当于从模数 pqpqpq 转换为模数 qqq,因此乘上一个模数转换缩放因子 qpq=1p\frac{q}{pq}=\frac{1}{p}pqq=p1

正确性容易证明:

c20+c21s=c2s2+⌊−c2(as+e)p⌉+⌊c2ap⌉s=c2s2+r \begin{align} c_{20}+c_{21}s&=c_2s^2+\lfloor \frac{-c_2(as+e)}{p} \rceil+\lfloor\frac{c_2a}{p} \rceil s \nonumber \\ &= c_2s^2+r \nonumber \end{align} c20+c21s=c2s2+pc2(as+e)+pc2as=c2s2+r

其中 rrr 的大小主要成分为 c2ep\frac{c_2e}{p}pc2e,外加一点小舍入误差,可以得到:

∣∣r∣∣<∣∣c2ep∣∣+12+γR⋅12⋅∣∣s∣∣+∣∣c2asp∣∣−∣∣c2asp∣∣=γRqBkp+γR∣∣s∣∣+12 \begin{align} ||r|| &\lt ||\frac{c_2e}{p}||+\frac{1}{2}+\gamma_R\cdot\frac{1}{2}\cdot ||s||+||\frac{c_2as}{p}||-||\frac{c_2as}{p}|| \nonumber \\ &= \frac{\gamma_RqB_k}{p}+\frac{\gamma_R||s||+1}{2} \nonumber \end{align} ∣∣r∣∣<∣∣pc2e∣∣+21+γR21∣∣s∣∣+∣∣pc2as∣∣∣∣pc2as∣∣=pγRqBk+2γR∣∣s∣∣+1

可以通过合理选取 ppp 的值来控制该噪声,这样一来,BFV 方案就以非平方增长的噪声代价实现了同态乘法计算,能够去除 BGV 方案中复杂的模数构造及大量的模数转换,提高效率。

5. SIMD 技术

SIMD(Simple Instruction Multiple Data)技术在全同态加密中特指一种数据打包技术,在 BGV、BFV、CKKS 这些第二代全同态加密方案中具有重要的作用。在介绍 CKKS 加密方案前,先介绍一下 SIMD 打包技术。

BGV 和 BFV 中的 SIMD 技术

由上述 BGV 和 BFV 方案的介绍可知,它们都利用 RLWE 问题进行数据加密和运算,加密的明文是一个多项式 m∈Zt[x]/(xd+1)m\in\mathbb{Z}_t[x]/(x^d+1)mZt[x]/(xd+1),而在实际应用中要处理的数据通常整数或浮点数,且往往需要将若干数据以向量表示进行并行运算,因此需要一种编码方式,将向量编码至多项式,同时还要满足加法和乘法等操作的正确性

BGV 和 BFV 处理整数向量,设要编码的明文向量为 m=(1,3)m=(1,3)m=(1,3),希望将其编码至多项式环 m′∈Z16[x]/(x2+1)m'\in \mathbb{Z}_{16}[x]/(x^2+1)mZ16[x]/(x2+1) 中,一种符合直觉的做法是直接将向量作为多项式系数,得到:

m′=1+3x m'=1 + 3x m=1+3x

该编码满足加法的并行计算:

m′+m′=2+6x=Encode(m+m) m' + m' = 2+6x = Encode(m+m) m+m=2+6x=Encode(m+m)

不满足乘法的并行计算(向量按位乘法 ⊙\odot ):

m′×m′=1+6x+9x2=−8+6x≠Encode(m⊙m) m' \times m' =1+6x+9x^2=-8+6x\ne Encode(m \odot m) m×m=1+6x+9x2=8+6x=Encode(mm)

因此该编码方式并不能正确的实现若干数的并行计算,只能对单个数进行编码计算。而 SIMD 技术就是一种能够正确实现并行计算的向量至多项式的编码方式。

单位根和本原单位根

首先了解一些前置知识,即单位根本原单位根相关性质。

复数域中,若 xn=1x^n=1xn=1,则称 xxxnnn 次单位根。

nnn 次单位根 xxx 满足对任意 1≤i<n1\le i \lt n1i<nxi≠1x^i \ne 1xi=1,则称 xxxnnn 次本原单位根。

显然 ωn=e2πin\omega_n=e^{\frac{2\pi i}{n}}ωn=en2πi 为一个 nnn 次本原单位根,且能生成所有的 nnn 次单位根 {ωn0,ωn1,⋯ ,ωnn−1}\{\omega_n^0,\omega_n^1,\cdots,\omega_n^{n-1}\}{ωn0,ωn1,,ωnn1}

对于一个 2n2n2n 次本原单位根 ω2n=e2πi2n\omega_{2n}=e^{\frac{2\pi i}{2n}}ω2n=e2n2πi,显然有 ω2nn=−1\omega_{2n}^n=-1ω2nn=1,则 {ω2n,ω2n3,ω2n5,⋯ ,ω2n2n−1}\{\omega_{2n},\omega_{2n}^3,\omega_{2n}^5,\cdots ,\omega_{2n}^{2n-1}\}{ω2n,ω2n3,ω2n5,,ω2n2n1} 为方程 xn+1=0x^n+1=0xn+1=0nnn 个解,因此有如下因式分解:

xn+1=(x−ω2n)(x−ω2n3)⋯(x−ω2n2n−1) x^n+1 =(x-\omega_{2n})(x-\omega_{2n}^3)\cdots (x-\omega_{2n}^{2n-1}) xn+1=(xω2n)(xω2n3)(xω2n2n1)

且由于上述分解每一项互素,根据中国剩余定理,模 xn+1x^n+1xn+1 意义下的多项式可以分解为 nnn 个模 x−ω2nix-\omega_{2n}^ixω2ni 的多项式,SIMD 编码就是根据上述分解实现的。

具体地,对于待编码向量 m=(m0,m1,⋯ ,mn−1)m=(m_0,m_1,\cdots, m_{n-1})m=(m0,m1,,mn1),设其对应的 SIMD 编码多项式为 p(x)=p0+p1x+⋯+pn−1xn−1p(x)=p_0+p_1x+\cdots + p_{n-1}x^{n-1}p(x)=p0+p1x++pn1xn1,则有 p(x) mod (x−ω2n2i+1)=mip(x) \ mod \ (x-\omega_{2n}^{2i+1}) =m_ip(x) mod (xω2n2i+1)=mi (即可以转换为 p(x)=mi+p1′(x−ω2n2i+1)+p2′(x−ω2n2i+1)2+⋯+pn−1(x−ω2n2i+1)n−1p(x)=m_i+p_1'(x-\omega_{2n}^{2i+1})+p_2'(x-\omega_{2n}^{2i+1})^2+\cdots +p_{n-1}(x-\omega_{2n}^{2i+1})^{n-1}p(x)=mi+p1(xω2n2i+1)+p2(xω2n2i+1)2++pn1(xω2n2i+1)n1),因此有:

[m0m1⋮mn−1]=[(ω2n)0(ω2n)1⋯(ω2n)n−1(ω2n3)0(ω2n3)1⋯(ω2n3)n−1⋮⋮⋱⋮(ω2n2n−1)0(ω2n2n−1)1⋯(ω2n2n−1)n−1]×[p0p1⋮pn−1]=[p(ω2n)p(ω2n3)⋮p(ω2n2n−1)] \begin{bmatrix} m_0 \\ m_1 \\ \vdots \\ m_{n-1} \end{bmatrix} = \begin{bmatrix} (\omega_{2n})^0 & (\omega_{2n})^1& \cdots &(\omega_{2n})^{n-1} \\ (\omega_{2n}^3)^0 & (\omega_{2n}^3)^1 & \cdots & (\omega_{2n}^3)^{n-1} \\ \vdots & \vdots & \ddots & \vdots \\ (\omega_{2n}^{2n-1})^0 & (\omega_{2n}^{2n-1})^1 & \cdots & (\omega_{2n}^{2n-1})^{n-1} \end{bmatrix} \times \begin{bmatrix} p_0 \\ p_1 \\ \vdots \\ p_{n-1} \end{bmatrix} = \begin{bmatrix} p(\omega_{2n}) \\ p(\omega_{2n}^3) \\ \vdots \\ p(\omega_{2n}^{2n-1}) \end{bmatrix} m0m1mn1 = (ω2n)0(ω2n3)0(ω2n2n1)0(ω2n)1(ω2n3)1(ω2n2n1)1(ω2n)n1(ω2n3)n1(ω2n2n1)n1 × p0p1pn1 = p(ω2n)p(ω2n3)p(ω2n2n1)

为了得到消息向量 m=(m0,m1,⋯ ,mn−1)m=(m_0,m_1,\cdots, m_{n-1})m=(m0,m1,,mn1) 的 SIMD 编码 p(x)=p0+p1x+⋯+pn−1xn−1p(x)=p_0+p_1x+\cdots + p_{n-1}x^{n-1}p(x)=p0+p1x++pn1xn1,可以通过如下线性变换得到:

[p0p1⋮pn−1]=[(ω2n)0(ω2n)1⋯(ω2n)n−1(ω2n3)0(ω2n3)1⋯(ω2n3)n−1⋮⋮⋱⋮(ω2n2n−1)0(ω2n2n−1)1⋯(ω2n2n−1)n−1]−1×[m0m1⋮mn−1] \begin{bmatrix} p_0 \\ p_1 \\ \vdots \\ p_{n-1} \end{bmatrix} = \begin{bmatrix} (\omega_{2n})^0 & (\omega_{2n})^1& \cdots &(\omega_{2n})^{n-1} \\ (\omega_{2n}^3)^0 & (\omega_{2n}^3)^1 & \cdots & (\omega_{2n}^3)^{n-1} \\ \vdots & \vdots & \ddots & \vdots \\ (\omega_{2n}^{2n-1})^0 & (\omega_{2n}^{2n-1})^1 & \cdots & (\omega_{2n}^{2n-1})^{n-1} \end{bmatrix}^{-1} \times \begin{bmatrix} m_0 \\ m_1 \\ \vdots \\ m_{n-1} \end{bmatrix} p0p1pn1 = (ω2n)0(ω2n3)0(ω2n2n1)0(ω2n)1(ω2n3)1(ω2n2n1)1(ω2n)n1(ω2n3)n1(ω2n2n1)n1 1× m0m1mn1

类似地,在模 ppp 意义上,若 n∣φ(p)n|\varphi(p)nφ(p),则一定存在 nnn 次本原单位根(当 nnn 整除群的阶时,阶为 nnn 的子群一定存在)。

ω2n\omega_{2n}ω2n 为模 ppp 意义下的一个 2n2n2n 次本原单位根,则有如下因式分解:

xn+1=(x−ω2n)(x−ω2n3)⋯(x−ω2n2n−1) x^n+1 =(x-\omega_{2n})(x-\omega_{2n}^3)\cdots (x-\omega_{2n}^{2n-1}) xn+1=(xω2n)(xω2n3)(xω2n2n1)

与复数域不同的点在与这里的 ω2ni\omega_{2n}^iω2ni 均为 Zq\mathbb{Z}_qZq 中的整数,例如:

x2+1=(x−4)(x−13) mod 17 x^2+1=(x-4)(x-13) \ mod \ 17 x2+1=(x4)(x13) mod 17

其余如中国剩余定理分解、SIMD编码均与复数域一致。

模意义下的 SIMD 编码

记 BGV 或 BFV 加密的多项式环为 Zq[x]/(xn+1)\mathbb{Z}_q[x]/(x^n+1)Zq[x]/(xn+1),对于消息向量 m=(m0,m1,⋯ ,mn−1)∈Zqnm=(m_0,m_1,\cdots, m_{n-1})\in \mathbb{Z}_q^nm=(m0,m1,,mn1)Zqn,编码后的多项式为: p(x)=p0+p1x+⋯+pn−1xn−1p(x)=p_0+p_1x+\cdots + p_{n-1}x^{n-1}p(x)=p0+p1x++pn1xn1,满足:

[p0p1⋮pn−1]=[(ω2n)0(ω2n)1⋯(ω2n)n−1(ω2n3)0(ω2n3)1⋯(ω2n3)n−1⋮⋮⋱⋮(ω2n2n−1)0(ω2n2n−1)1⋯(ω2n2n−1)n−1]−1×[m0m1⋮mn−1] \begin{bmatrix} p_0 \\ p_1 \\ \vdots \\ p_{n-1} \end{bmatrix} = \begin{bmatrix} (\omega_{2n})^0 & (\omega_{2n})^1& \cdots &(\omega_{2n})^{n-1} \\ (\omega_{2n}^3)^0 & (\omega_{2n}^3)^1 & \cdots & (\omega_{2n}^3)^{n-1} \\ \vdots & \vdots & \ddots & \vdots \\ (\omega_{2n}^{2n-1})^0 & (\omega_{2n}^{2n-1})^1 & \cdots & (\omega_{2n}^{2n-1})^{n-1} \end{bmatrix}^{-1} \times \begin{bmatrix} m_0 \\ m_1 \\ \vdots \\ m_{n-1} \end{bmatrix} p0p1pn1 = (ω2n)0(ω2n3)0(ω2n2n1)0(ω2n)1(ω2n3)1(ω2n2n1)1(ω2n)n1(ω2n3)n1(ω2n2n1)n1 1× m0m1mn1

容易验证该编码符合多项式加法与乘法和整数向量加法和按位乘法的对应关系,以乘法为例,有:

p(x)×p′(x) mod (x−ω2n2i+1)=mi×mi′ p(x) \times p'(x) \ mod \ (x-\omega_{2n}^{2i+1}) =m_i \times m_i' p(x)×p(x) mod (xω2n2i+1)=mi×mi

因此该编码可以用于 BGV 和 BFV 的并行同态计算,从而大大提高实际应用中的效率。

CKKS 的 SIMD 技术

在介绍 CKKS 之前首先介绍一下应用在 CKKS 中的 SIMD 编码技术。

CKKS 方案明文空间为复数向量 m∈Cn2m\in \mathbb{C}^{\frac{n}{2}}mC2n。对于一个 2n2n2n 次本原单位根 ω2n=e2πi2n\omega_{2n}=e^{\frac{2\pi i}{2n}}ω2n=e2n2πi,由其生成的 {ω2n,ω2n3,ω2n5,⋯ ,ω2n2n−1}\{\omega_{2n},\omega_{2n}^3,\omega_{2n}^5,\cdots ,\omega_{2n}^{2n-1}\}{ω2n,ω2n3,ω2n5,,ω2n2n1} 为方程 xn+1=0x^n+1=0xn+1=0nnn 个解,且满足 ω2ni=ω2n2n−i‾\omega_{2n}^{i}=\overline{\omega_{2n}^{2n-i}}ω2ni=ω2n2niω‾\overline{\omega}ωω\omegaω共轭复数),因此对多项式 p(x)∈C[x]/(xn+1)p(x)\in \mathbb{C}[x]/(x^n+1)p(x)C[x]/(xn+1),设 p(x)=p0+p1x+⋯+pn−1xn−1p(x)=p_0+p_1x+\cdots + p_{n-1}x^{n-1}p(x)=p0+p1x++pn1xn1,有 p(ω2ni)=p(ω2n2n−i)‾p(\omega_{2n}^{i})=\overline{p(\omega_{2n}^{2n-i})}p(ω2ni)=p(ω2n2ni),因此有 pi=pi‾p^{i} = \overline{p^i}pi=pi,所以由 {ω2n,ω2n3,ω2n5,⋯ ,ω2n2n−1}\{\omega_{2n},\omega_{2n}^3,\omega_{2n}^5,\cdots ,\omega_{2n}^{2n-1}\}{ω2n,ω2n3,ω2n5,,ω2n2n1} 插值而得的多项式 p(x)p(x)p(x) 的系数均为实数(虚部为0)。

CKKS 方案正是利用这一点将复数向量编码至实数多项式,考虑到 p(ω2ni)=p(ω2n2n−i)‾p(\omega_{2n}^{i})=\overline{p(\omega_{2n}^{2n-i})}p(ω2ni)=p(ω2n2ni),这意味着待编码向量必须满足 mi=mn−1−i‾m_i=\overline{m_{n-1-i}}mi=mn1i,这正是 m∈Cn2m\in \mathbb{C}^{\frac{n}{2}}mC2n 长度为 n2\frac{n}{2}2n 的原因,要将其扩展m′m'm

m′=(m0′,m1′,⋯ ,mn−1′)=(m0,m1,⋯ ,mn2−1,mn2−1‾,⋯ ,m0‾) m'=(m_0',m_1',\cdots, m_{n-1}')=(m_0,m_1,\cdots, m_{\frac{n}{2}-1},\overline{m_{\frac{n}{2}-1}},\cdots,\overline{m_0}) m=(m0,m1,,mn1)=(m0,m1,,m2n1,m2n1,,m0)

将该过程记为 m′=π−1(m)m'=\pi^{-1}(m)m=π1(m),显然有 m=π(m′)m = \pi(m')m=π(m)。设 m′m'm 通过中国剩余定理编码为多项式 p(x)p(x)p(x),该过程记作 p(x)=σ−1(m′)p(x)=\sigma^{-1}(m')p(x)=σ1(m),同时有 m′=σ(p(x))m'=\sigma(p(x))m=σ(p(x))

由于编码后的多项式系数为实数,而 CKKS 要使用 RLWE 问题进行加密,因此要将其转换为整数。直接转换会引入大量的精度损失,CKKS 方案引入一个缩放因子 Δ\DeltaΔ,将多项式系数乘以该缩放因子后取整得到整数多项式(和安全多方计算将实数转为定点数存储的方式类似)。

具体地,CKKS 中的编码过程为 Ecd(m,Δ)Ecd(m,\Delta)Ecd(m,Δ)

Ecd(m,Δ)=p(x)=⌊Δ⋅σ−1(π−1(m))⌉ Ecd(m,\Delta)= p(x) = \lfloor \Delta \cdot \sigma^{-1}(\pi^{-1}(m)) \rceil Ecd(m,Δ)=p(x)=Δσ1(π1(m))⌉

同样的,有解码过程记为 Dcd(p(x),Δ)Dcd(p(x), \Delta)Dcd(p(x),Δ)

Dcd(p(x),Δ)=m=π(σ(⌊Δ−1⋅p(x)⌉)) Dcd(p(x),\Delta) = m=\pi(\sigma(\lfloor \Delta^{-1} \cdot p(x) \rceil)) Dcd(p(x),Δ)=m=π(σ(⌊Δ1p(x)⌉))

6. CKKS 加密方案

CKKS 方案由 Cheon、Andrey Kim、Miran Kim 和 Song 发表[13]^{[13]}[13],主要特点是它的明文空间为复数向量,这代表着它支持浮点数(实际上是编码成定点数)的加密和运算。浮点数的支持主要体现在加密前的消息编码上,编码之后的加密和运算与 BGV 和 BFV 类似。在介绍本方案时,取模等符号表示与前文 BFV 方案相同,设 CKKS 方案中密文空间多项式为 Rq=Zq[x]/(xn+1)R_q=\mathbb{Z}_q[x]/(x^n+1)Rq=Zq[x]/(xn+1)


6.1 密钥生成算法

  1. 随机选取模数 q0q_0q0 以及大小在缩放因子 Δ\DeltaΔ 附近的随机数 ppp,再生成 LLL 个模数 qi=q0⋅pi(1≤i≤L)q_i=q_0\cdot p^i(1\le i \le L)qi=q0pi(1iL)

  2. 随机选取符合 RLWE 问题的 a,s,e∈RqLa,s,e\in R_{q_L}a,s,eRqL,并计算 b=[−as+e]qLb=[-as+e]_{q_L}b=[as+e]qL

  3. 公钥为 a,ba,ba,b,私钥为 sss

6.2 加密算法

对于明文 z∈Cn2z\in \mathbb{C}^{\frac{n}{2}}zC2n,首先应用 SIMD 技术将其编码为多项式 m=Ecd(z,Δ)∈RqLm=Ecd(z,\Delta)\in R_{q_L}m=Ecd(z,Δ)RqL,随后随机选取 v,e0,e1∈RqLv,e_0,e_1\in R_{q_L}v,e0,e1RqL,其中 vvv 很小,且 e0,e1e_0,e_1e0,e1 满足从小噪声分布中采样。使用公钥加密过程如下:

c⃗=Enc(m)=(c0,c1)=([m+bv+e0]qL,[av+e1]qL) \vec{c}=Enc(m)=(c_0,c_1)=([m+bv+e_0]_{q_L},[av+e_1]_{q_L}) c =Enc(m)=(c0,c1)=([m+bv+e0]qL,[av+e1]qL)

6.3 解密算法

可以把私钥包装为一个二维向量 s⃗=(1,s)\vec{s}=(1,s)s =(1,s),对于模数为 qlq_lql 的密文 c⃗\vec{c}c ,使用该私钥解密过程如下:

m=Dec(c⃗)=[c⃗⋅s⃗]ql=[m+e′]ql m = Dec(\vec{c})= [\vec{c}\cdot\vec{s}]_{q_l}=[m+e']_{q_l} m=Dec(c )=[c s ]ql=[m+e]ql

随后利用 SIMD 解码技术计算得到明文 z=Dcd(m,Δ)z=Dcd(m,\Delta)z=Dcd(m,Δ)


正确性

CKKS 方案的正确性与 BFV 方案类似,只需解密时噪声满足 ∣∣e′Δ∣∣<12||\frac{e'}{\Delta}|| \lt \frac{1}{2}∣∣Δe∣∣<21 即可。

安全性

CKKS 的安全性也与 BFV 方案类似,依赖于 RLWE 问题的求解难度。

加法同态性

CKKS 加密方案具有加法同态性,可以验证:

Enc(m0)+Enc(m1)=[c⃗0+c⃗1]ql=(m0+m1+b(v0+v1)+e′)=Enc(m0+m1) \begin{align} Enc(m_0)+Enc(m_1)&=[\vec{c}_0+\vec{c}_1]_{q_l} \nonumber \\ &=\left(m_0+m_1+b(v_0+v_1)+e'\right) \nonumber \\ &= Enc(m_0+m_1) \nonumber \end{align} Enc(m0)+Enc(m1)=[c 0+c 1]ql=(m0+m1+b(v0+v1)+e)=Enc(m0+m1)

与 BFV 方案类似,噪声增长较小。

乘法同态性

CKKS 加密方案具有乘法同态性,验证流程与 BFV 方案类似,不再赘述。注意 CKKS 方案执行完乘法后密文也会变成三维,因此也需要执行 Relinearisation (或者称之为密钥转换)将其转换为二维。

与此同时,考虑到 CKKS 在编码时数据放大了 Δ\DeltaΔ 倍,则执行完同态乘法后数据放大 Δ2\Delta^2Δ2 倍,同时噪声增长较大。CKKS 方案采用类似 BGV 方案的模数转换的技术来控制噪声并将放缩倍数调回 Δ\DeltaΔ 倍,这也是为什么密钥生成时选取 L+1L+1L+1 个模数需要满足 ql=ql−1⋅pq_l = q_{l-1} \cdot pql=ql1pp≈Δp\approx \DeltapΔ 的原因。

具体缩放操作可以参考 BGV 模数转换,简单来说相当于将密文放缩至 ql−1ql=1p\frac{q_{l-1}}{q_l}=\frac{1}{p}qlql1=p1 倍。ppp 不需要严格等于 Δ\DeltaΔ,乘法后的放缩相当于把由乘法导致的有效位数的增加大致去除掉,即时少去除或多去除一位也仅会产生较小的精度影响。

CKKS 方案每执行一次同态乘法计算都需要进行一次模数转换,因此在不执行 Bootstrapping 技术的情况下也属于有限级数全同态加密,由于 Bootstrapping 技术的实现较为复杂,且效率低,通常这类第二代全同态加密方案在实际应用中都被当作有限级数全同态加密使用。


下一部分将介绍 GSW、FHEW、TFHE 全同态加密方案。

参考文献(续)

  • [12] J. Fan and F. Vercauteren, “Somewhat Practical Fully Homomorphic Encryption,” 2012, 2012/144. Accessed: Jul. 15, 2025. [Online]. Available: https://eprint.iacr.org/2012/144

  • [13] J. H. Cheon, A. Kim, M. Kim, and Y. Song, “Homomorphic Encryption for Arithmetic of Approximate Numbers,” in Advances in Cryptology – ASIACRYPT 2017, Cham: Springer International Publishing, 2017, pp. 409–437.


本文为作者在学习相关知识时的一种记录,便于以后的回顾。作者并没有系统地学习过密码学,因此在表述上可能会存在不严谨甚至出错的地方,文章仅供参考,欢迎大家与我交流,一起进步!

其他平台:

  • 知乎(Totoro):https://www.zhihu.com/people/totoro-14-60
  • B站(Totoro_134):https://space.bilibili.com/279377771
  • Github(Totoro134):https://github.com/Totoro134
  • 公众号(知识长生所)
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐