CKKS Part4: CKKS的乘法和重线性化
本文翻译于CKKS EXPLAINED, PART 4: MULTIPLICATION AND RELINEARIZATION,主要介绍CKKS方案中的密文乘法和重线性化技术
介绍
在上一篇 CKKS Part3: CKKS的加密和解密 ,我们看到了如何基于RLWE问题创建同态加密方案,实现同态加法和密文明文乘法。
虽然执行密文-明文乘法很容易,但正如我们将看到的,密文-密文要复杂得多。事实上,我们需要处理很多事情才能正确地完成它,比如找到正确的操作,这样一旦解密,我们就可以得到两个密文的乘积,以及管理密文的大小。
因此,本文将介绍密文乘法和重新线性化的概念,以减少生成的密文的大小。
基本概念
为了了解我们将如何在CKKS中执行密文-密文乘法,让我们回顾一下我们在前一篇文章中看到的内容。
首先,记住我们研究的是多项式空间\(R_{q}=\Zeta _{q}\left[ X \right]/\left( X^{N}+1 \right)\)。我们将s作为我们的私钥,然后我们可以安全地输出一个公钥p=(b,a)=(−a. s+e,a),其中a均匀取样\(R_{q}\)、 e是一个小的随机多项式。
然后我们有\(\mbox{E}ncrypt\left( u,s \right)=c=\left( c_{0},c_{1} \right)=\left( u,0 \right)+p=\left( b+u,a \right)\in R_{q}^{2}\)是明文\(u \in \Zeta _{q}\left[ X \right]/\left( X^{N}+1 \right)\)使用公钥p的加密操作。要使用私钥s解密密文c,我们执行以下操作:$$Decrypt\left( c,s \right)=c_{0}+c_{1}.s=u+e$$
然后我们发现定义一个在密文上的加法运算\(𝙲_{𝙰𝚍𝚍}(c,c′)\)很容易,所以一旦我们解密\(𝙲_{𝙰𝚍𝚍}\) 我们将大致得到两个基本明文的加法。
实现这一点的方法是定义\(𝙲_{𝙰𝚍𝚍}\) 具体如下:$$\mbox{C}{Add}\left( c,c' \right)=\left( c+c_{0}',c_{1}+c_{1}' \right)=c+c'=c_{add}$$
事实上,如果我们对其应用解密操作,我们会得到:$$Decrypt\left( c_{add},s \right)=c_{0}+c_{0}'+\left( c_{1}+c_{1}' \right).s=c_{0}+c_{1}.s+c_{0}'+c_{1}'.s=Decrypt\left( c,s \right)+Decrypt\left( c',s \right)约等于u+u'$$
这里我们看到,对密文做加法非常简单,我们只需要将两个密文相加,我们可以使用常规的解密操作来解密结果,以获得两个对应明文的相加。
我们将看到,在进行密文乘法时,乘法和解密操作都更加复杂。
密文-密文乘法
现在我们看到了这一点,我们看到我们的目标是找到操作\(𝙲_{𝙼𝚞𝚕𝚝},𝙳𝚎𝚌𝚛𝚢𝚙𝚝𝙼𝚞𝚕𝚝\), 对于两个密文c,c′我们有:\(DecryptMult\left( \mbox{C}_{Mult}\left( c,c' \right),s \right)=Decrypt\left( c,s \right).Decrypt\left( c',s \right)\),切记\(Decrypt\left( c,s \right)=c_{0}+c_{1}.s\),我们展开上面的式子得到:
其中\(d_{0}=c_{0}.c_{0}',d_{1}=\left( c_{0}.c_{1}'+c_{0}'c_{1} \right),d_{2}=c_{1}.c_{1}'\)
有趣的如果我们仔细想想,计算\(Decrypt\left( c,s \right)=c_{0}+c_{1}.s\),可以看作是关于私钥s的多项式求值,它是形式为\(c_0+c_1.S\)的一次多项式。S是多项式中的变量。
因此,如果我们看到两个密文乘积上的解密运算,它可以被看作是多项式$d_0+d_1.S+d_2.S^2,关于S的二次多项式
因此,我们可以使用以下操作来进行密文乘法:
使用这样的操作可能会有效,但有一个问题:密文的大小增加了!事实上,虽然密文通常只是几个多项式,但这里有3个多项式用于密文。通过使用与之前相同的推理,如果我们什么都不做,要正确解密下一个乘积,我们需要5个多项式,然后是9个,依此类推。因此,密文的大小将呈指数增长,如果我们这样定义密文-密文乘法,它在实践中将不可用。
我们需要找到一种不增加每一步密文大小的乘法方法。这就是重线性化的用武之地!
重线性化
我们可以把密文之间的乘法定义为运算:\(\mbox{C}_{Mult}\left( c,c' \right)=\left( d_{0},d_{1},d_{2} \right)\),问题是,现在的输出是一个维数为3的密文,如果我们在每次计算后继续增加密文的大小,那么在实践中使用它将变得不可行。
让我们想想,问题是什么?问题是我们需要第三个项\(d_2\),用于多项式解密\(DecryptMult\left( c_{mult},s \right)=d_{0}+d_{1}.s+d_{2}.s^{2}\),但如果我们能找到只有一个1次多项式作为解密去计算\(d_2.s^2\)的方法呢?那么在这种情况下,密文的大小将是恒定的,它们都将只是用到了两个多项式!
这就是重新线性化的本质:找到一对多项式\(\left( d_{0}',d_{1}' \right)=\mbox{Re}lin\left( c_{m\mu lt} \right)\),例如:$$Decrypt\left( \left( d_{0}',d_{1}' \right),s \right)=d_{0}'+d_{1}'.s=d_{0}+d_{1}.s+d_{2}.s^{2}=Decrypt\left( c,s \right).Decrypt\left( c',s \right)$$
具体来说,重线性化允许有一对多项式(s的一次方),而不是三对多项式(s的二次方),这样,解密时就只需要用到s,而不用s的平方,我们就可以得到两个明文的乘法。
因此,如果我们在每次密文-密文乘法后执行重线性化,我们将始终有相同大小的密文,具有相同的解密电路!
现在你可能想知道我们到底需要如何定义𝚁𝚎𝚕𝚒𝚗 。这个想法很简单,我们知道我们需要一对多项式,例如:\(d_{0}'+d_{1}'.s=d_{0}+d_{1}.s+d_{2}.s^{2}\),我们的想法是定义\(\left( d_{0}',d_{1}' \right)=\left( d_{0},d_{1} \right)+P\),其中P表示一对多项式,例如\(Decrypt\left( P,s \right)=d_{2}.s^{2}\)
这样,当我们用$(d′_0,d′_1)计算解密电路时,我们得到:
一种方法是提供一个计算密钥,用于计算P。使得\(evk=\left( -a_{0}.s+e_{0}+s^{2},a_{0} \right)\),其中\(e_0\)是一个小的随机多项式,\(a_0\)是一个在\(R_q\)上均匀采样的多项式,然后我们计算\(Decrypt\left( evk,s \right)=e_{0}+s^{2} 约等于 s^{2}\),太好了!我们可以看到,我们可以公开计算密钥,因为基于RLWE问题很难提取私钥,可以用来求s的平方项。
所以为了解密出\(d_{2}.s^{2}\), P可能是\(P=d_{2}.evk=\left( d_{2.}.\left( -a_{0}+e_{0}+s^{2} \right),d_{2}.a_{0} \right)\),的确正如我们所看到的那样\(Decrypt\left( P,s \right)=d_{2}.s^{2}+d_{2}.e_{0}\),这时我们可能会考虑\(d_{2}.s^{2}+d_{2}.e_{0}约等于d_{2}.s^{2}\)?
不幸的是,我们不能这样做,因为\(d_{2}.e_0\)项比我们通常得到的噪声要大得多。如果你之前注意到了,我们允许对结果进行近似,因为误差多项式很小,比如加入一个小多项,它不会对结果产生太大的影响。但问题是\(d_2\)很大,因为\(d_2=c_1.c_1'\),其中,每个\(c_1\)包括一个从\(R_q\)中采样的多项式a,因此,它比我们通常处理的小误差多项式要大得多。
那么,我们在实践中如何处理这个问题呢?诀窍是稍微修改计算密钥,并将其定义为\(evk=\left( -a_{0}.s+e_{0}+p.s^{2},a_{0} \right)(mod p.q)\),其中p是一个大整数,\(a_0\)从\(R_{q.p}\)中随机采样。这里的想法是,我们将除以p,以去除与\(d_2\)相乘时产生的噪声,即
,因此最后我们使得:$$P=\left\lfloor p^{-1}.d_{2}.evk \right\rfloor\left( \mbox{mod}\ q \right)$$,这意味着我们将除以p并将其四舍五入到最接近的整数,然后使用模q(而不是p.q)。
即
,因为\(p^{-1}.d_2.e_0\)很小,可以约去!
我们终于有了合适的方法了!因此,为了定义重线性化,我们需要一个计算密钥(可以在没有风险的情况下公开),我们将其定义为:\(\mbox{Re}lin\left( \left( d_{0},d_{1},d_{2},evk \right) \right)=\left( d_{0},d_{1} \right)+\left\lfloor p^{-1}.d_{2}.evk \right\rfloor\)。可以看到,重线性化后的密文由三维变二维。
因此,如果我们有两个密文c,c′,并且我们想要将它们相乘(可能几次),然后解密结果,那么工作流程将是:
1、相乘:\(c_{m\mu lt}=\mbox{C}_{Mult}\left( c,c' \right)=\left( d_{0},d_{1},d_{2} \right)\)
2、重线性化:\(c_{\mbox{re}lin}=\mbox{Re}lin\left( \left( d_{0},d_{1},d_{2} \right),evk \right)\)
3、解密输出:\(u_{m\mu lt}=Decrypt\left( c_{\mbox{re}lin},s \right)约等于u.u'\)
我在这里只给出了总体思路,但如果您有兴趣了解细节,我建议您阅读"Somewhat Practical Fully Homomorphic Encryption".一文中的解释。
现在我们知道了如何将两个密文相乘,并保持它们的大小不变。太好了!虽然你可能认为这一切都结束了,但我们会看到,要实现同态加密方案,还有最后一步要做:rescaling,重新缩放。在我们自己编写代码之前,我们将在下一篇文章中看到什么是重缩放,以及如何进行重缩放!