SEAL全同态加密库(六)
一.同态的加法
全同态加法的代码是这样的
public void Add(Ciphertext encrypted1, Ciphertext encrypted2, Ciphertext destination)
{
if (null == encrypted1)
throw new ArgumentNullException(nameof(encrypted1));
if (null == encrypted2)
throw new ArgumentNullException(nameof(encrypted2));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.Evaluator_Add(NativePtr, encrypted1.NativePtr, encrypted2.NativePtr, destination.NativePtr);
}
public void AddMany(IEnumerable<Ciphertext> encrypteds, Ciphertext destination)
{
if (null == encrypteds)
throw new ArgumentNullException(nameof(encrypteds));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr[] encarray = encrypteds.Select(c => c.NativePtr).ToArray();
NativeMethods.Evaluator_AddMany(NativePtr, (ulong)encarray.Length, encarray, destination.NativePtr);
}
二.加法的具体过程
最简单的情况是两个加密数字的加法。假设我们已经用相同的公钥加密了两个多项式m1和m2:
注意,我们需要使用两个不同的、小的多项式u1和u2,以及4个小的噪音多项式e1…e4。
如果我们仅仅是将密文中的元素相加,就会得到一个新的密文
由于消息仅存在于具有缩放的密文中,所以加法的结果与m1 + m2加密的形式相同,只是增加了新的噪音:
近似解密(舍入之前)将是
这意味着只要新的噪音不是太大,消息m1 + m2将正确解密。噪音有三种类型:
我们担心的是,当这些项变得足够大,以至于噪音多项式中的一个系数大于q/(2t)时,解密就会失败,因为解密过程结束时的四舍五入操作会四舍五入到错误的数字。
如果我们只考虑第一项,那么我们就把来自离散高斯分布的多项式中的系数相加。这意味着,在某些情况下,我们会把一个负系数加到一个正系数上,结果会更接近于零。在其他情况下,系数会有相同的符号,所以结果会更大。我们可以做很多的同态加法,看看噪音是如何随着加法的数量增加而增加的,这是很有指导意义的。系数的分布如下图所示,其中我们添加了1、5和30个噪音多项式(随机地进行了数百次试验)。
当我们添加了30个噪音多项式时,某些系数有可能会大于64,即超过了q/t的一半,所以解密不会产生正确的结果。
另外两项表示不同的情况——第二项是一个噪音多项式乘以一些“小的多项式”(系数为-1、0或1)的总和。这种乘法会产生更大的噪音。一个噪音多项式和一个小的多项式的乘积的系数大约将是随机正负号的噪音多项式系数的2/3rds的总和。这意味着这个噪音与多项式的最高次的平方根√n一致。
对这一项绘制与上面相同的分布可以看出,它比第一项大得多,而且即使对于我们示例中的参数,也存在错误解密的危险,即使只是添加了几个参数。
第三项是类似的——一组噪音多项式之和,乘以一个“小的多项式”。它的噪音分布是这样的:
结合起来,我们可以画出这三项的最大系数的增长,作为已经发生的加法数量的函数。这是一个须状图,给出了这些最大值的可变性。(注意噪音的均值接近于零,这是最大系数的幅值分布。)
这表明,对于我们所选择的参数,由两个以上加法产生的密文,解码错误的概率很高,而且两次加法失败的概率也很高。这是因为有时最大错误大于64,当q/t = 128时,会导致不正确的解密,就像这里一样。为了给这样的操作提供更多的空间,我们需要使用更大的q/t比值,这可以应对通常由所执行的操作数量引入的噪音量。