Back
Featured image of post 同态加密(3) BGV方案

同态加密(3) BGV方案

BGV方案是由Zvika Brakersi, Graig Gentry与Vinod Vaikuntanathan于2012年提出的同态加密方案, 发表于论文[BGV12]中.

BGV同态加密方案是由Zvika Brakerski, Graig Gentry, Vindo Vaikuntanathan提出于[BGV12] 1. 该方案是BV11b方案基础上一个较大的改进. 该方案挖掘出BV11b方案中模数切换可以降低密文的绝对噪声这一特点, 将其发扬广大, 使得在加密在无需Bootstrapping的情况下可以做到较多层数的同态乘法运算.

如果需要实现全同态加密, 该方案仍需要引入Circular Security假设和Boostrapping. 但是由于模数切换使得我们可以在不进行Bootstrapping的情况下做较多次数的同态运算, 并且使得Bootstrapping之前的密文模数变得非常小, 因此Bootstrapping是非常容易的. 因此该方法能够显著降低Bootstrapping的次数和难度.

简介

我们在介绍BV11b方案的时候, 介绍过密文的格式为(v,w), 此处我们忽略了密文的同态层数. 密钥的解密可以表示为

  • Dec(sk=s,(v,w)): 计算并输出

    (wv,smodq)mod2

我们将采用另一种形式的LWE加密来表示上述问题(在LWE介绍性文章(写成后地址将被更新到这里)以及本文之后的内容会有介绍), 用c表示密文, 用s表述明文, 上述解密过程可以被简化为[[c,s]q]2, 其中[]k表示模k运算. 这种形式的密文噪声体现在哪里呢? 其实本身就是大[c,s]q概的噪声.

BV11b的核心思想之一是在最后同态计算结束后, 需要将大密文(即维数和模数较大的密文)转换为小密文(即模数和维数较小的密文). 其中, 维数切换的操作是平凡, 而模数切换的操作需要一定的技巧性, 且其安全性依赖于稀疏子集和假设. 一个不太让人感觉到的惊奇的现象是, 在进行模数切换的时, 噪声也成比例减小了. 即我们有如下引理:

引理1pq是两个奇数模数, c是一个整数向量. 令c为一个距离(p/q)c最近的一个整数向量满足c=cmod2. 则对于任意的s使得|[c,s]q|<q/2(q/p)1(s)[c,s]p=[c,s]qmod2|[c,s]p|<(p/q)|[c,s]|+1(s) 其中1(s)s的第一范数.

第一个结果能够保持我们在输入正确密钥时解密结果的正确性, 而第二个结果则表明我们确实几乎在模数切换的同时几乎时等比例缩小了噪声, 这是由于从噪声分布中选择s的LWE具有从均匀分布中选择s的LWE具有几乎相当的平均意义下的困难性, 这使得我们的加密方案中s可以选自噪声分布χn使得1(s)较小. 下面我们来证明上述引理.

证明: 根据假设, 对于某个整数k[c,s]q=c,skq. 假设ep=c,skp, 我们现在证明ep大概就是c的噪声, 即ep=[c,s]p. 由于c=cmod2p=qmod2, 因此ep=[c,s]qmod2. 由于 ep=c,skp=c,skqpq=c,s+pq([c,s]qc,s)=pq[c,s]q+c(p/q)c,s|ep|(p/q)[c,s]q+1(s)<p/2. 从第二个不等式中, 我们得出, ep大概就是c的噪声, 因此有|[c,s]p|<(p/q)|[c,s]|+1(s).

从上式的证明中, 我们也可以看出额外的噪声是如何引入的, 即从c(p/q)c,s中产生.

到了这里你也许就明白这个方案的工作原理了: 虽然噪声是和模数等比例缩小的, 但是如果噪声本身就比较小, 那么通过模数切换, 它将变得非常小, 使得一次乘法同态运算后噪声也不会变得太大. 例如两个模q噪声为B的密文进行同态乘法运算, 其结果噪声将会达到约B2, 而将其模数切换为p后噪声为约pB/q. 再做乘法同态运算, 则噪声是(pB/q)2. 我们发现, 虽然B/q(pB/q)/p, 但是做同态乘法运算后, 小密文产生的结果噪声占比约为(pB/q)2/q=p2B/q3, 而原先的大密文噪声扎占比约为B2/q, 显然小密文更占优势.

基于如上的思想, 我们可以从一开始就选择非常大的模数q0, 使得模数可以接受多次模数切换操作, 这样每次对噪声上界为B得密文做乘法后我们就进行一次模数切换, 将模数变成qiqi1/B, 即模数变为原来的大概1/B, 来使得噪声不变得更大, 我们就可以在做到多次同态后, 使得噪声上界始终维持在一个较为稳定的范围内. 这个过程可以一直持续到我们将模数下降得太小(使得B>qL/2)之前.

如果不进行模数切换, 噪声是双指数倍数增长的, B噪声的密文经过L次同态变成B2L很快就能接近q0/2, 而做模切换噪声则是指数下降的, 使得qiq0/Bi满足B>qi/2显然要比原来的方案慢得多, 因此我们就可以进行更多次的同态乘法运算.

GLWE介绍

在本文中, 作者将LWE与RLWE统一为了GLWE, 使得在介绍方案的时候不用重复劳动. 我们按照作者的思路, 对GLWE一些介绍.

GLWE (General Learning with Errors) 是一种将LWE与RLWE统一的表示方式. 我们知道, LWE的元组都是Zqn×Zq, 而RLWE的元组都是来自Rq×Rq, 我们注意到有一个维数n来描述元组中第一个选自均匀分布的元. 如果我们将Z也视作是一个环, 那么LWE的元组基于的环是Zq=Z/qZ, 而RLWE基于的则是Rq=R/qR, 即可将二者也统一起来. 这样, 我们通过两个参数就可以确定我们选择的是LWE还是RLWE, 即元组中第一个元的维数n (对于LWE来说, n=poly(n), 对于RLWE来说n=1), 以及元组所基于的环R. 我们用这种记法表示统一表示二者, 即GLWE.

定义2 GLWE

设安全参数为λ, 令n=n(λ)为一个整数维数, 令f(x)=xd+1其中d=d(λ)是一个2的指数幂, ling q=q(λ)2是一个素数2, 令R=Z[x]/(f(x))Rq=R/qR, 令χ=χ(λ)是一个R上的分布. GLWEn,f,q,χ问题, 定义为区分如下两个分布:

  • Rqn+1上的均匀分布.
  • 由如下方式产生的分布: 首选均匀生成a$Rqns$Rqn, 选择eχ, 然后输出(a,b=a,s+e).

现在我们介绍GLWE困难的参数假设. 我们认为, 满足参数nd=Ω(λlog(q/B))的GLWE问题是安全的, 其中B表示χ输出的元素的长度上界. 目前该假设还未被证明, 但是也没有出现分析结果. 这里需要再次重申一下: GLWE的定义仅仅是为了我们的描述方便, 即我们实际上还是在基于LWE假设RLWE假设构造公钥加密方案和全同态加密方案. 也就是说, 你无需关心那些最终参数使得GLWE不是LWE或RLWE的参数.

Leveled FHE构造

现在, 我们就来构造安全性基于GLWE的Leveled FHE方案. 这个方案采用了模数切换来控制噪声, 使得噪声始终维持在较小的水平, 而使得我们可以进行较多次的乘法同态运算. 不过在此之前, 我们还是像BV11b基于LWE的公钥加密方案一样, 我们先构造好基于GLWE的公钥加密方案.

基于GLWE假设的公钥加密方案

该方案在选择n=1和环R=Z时, 得到的加密方案实际上是同BV11b中的LWE公钥加密方案是类似的, 但是有两点不同:

  1. 由于换了一种LWE的形式, 密钥的形式和最终解密的形式看起来略有不同.
  2. 基础密钥s的选择来自于χn, 则是为了保证s的第一范数较小, 从而使得我们在模数切换的时候能够有效控制噪声.

对于第一点不同, 熟悉LWE的读者可以立即看出来, 这仅仅是由于我们不再单独写出b=As+2e, 而是将它作为矩阵的一列写进了A=[b|A].

基于GLWE假设的公钥加密方案:

  • E.Setup(1λ,1μ,b): 由比特b来确定我们是构造LWE假设下的方案(b=0)还是RLWE假设下的方案(b=1). 选择一个μ比特的模数q和参数 d=d(λ,μ,b),n=n(λ,μ,b),N=(2n+1)logq,χ=χ(λ,μ,b) 此处要求最终的参数使得GLWE问题实例具有安全性. 令R=Z[x]/(xd+1), 并令参数集合params=(q,d,n,N,χ).

  • E.SecretKeyGen(params): 选择sχn, 输出sk=s=(1,s[1],,s[n])Rqn+1.

  • E.PublicKeyGen(params,sk): 均匀选择A$RqN×n, 选择eχN并令b=As+2e. 并令pk=A=[b|A].

  • E.Enc(params,pk,m{0,1}): 令m=(m,0,,0)Rqn+1, 选择r$RqN, 输出密文c=m+ATrRqn+1.

  • E.Dec(params,sk,c): 输出m[[c,s]q]2.

现在我们来看一下这个加密及解密过程为什么同BV11b中的方案是一样的. 对于加密来说, c=m+[b|A]Tr=(bTr+m,ATr) 可见, 这就是把BV11b中密文的两部分写在了一起. 而解密操作也是类似 c,s=bTr+mATr,s=bTr+m(As)Tr=bTr+m(b2e)Tr=m+2e 其中e=eTr. 可见, 解密过程也是和BV11b中的方案是相同的.

其他符号介绍

这里使用的技术喝BV11b中基本是一样的, 只是由于模数切换的原因, 我们需要经常处理不同的模数, 因此几个函数中多了模数这一个参数. 此外, 结果的顺序也由有所不同.

  • BitDecomp(xRqn,q): 即将x拆解成其二进制表示, x=j=0logq2juj, 其中ujR2n. 输出(u0,u1,,ulogq).

显然有x[i]=j=0logq2juj[i]. 类似的, 定义

  • Powerof2(xRqn,q): 输出(x,2x,,2logqx).

根据以上的定义, 我们有 BitDecomp(c,q),Powerof2(s,q)=c,s

密钥切换

现在我们来介绍密钥切换的具体过程. 与其说是介绍, 不如说是熟悉我们的新记号. 回顾一下我们要将密钥s1下的密文c1切换的到密钥s2下的密文c2, 我们就要用s2作为私钥来生成一个LWE公钥并"加密"s1的每个项的每个Powerof2, 即需要每个2τs1[i]的"密文". 我们将这些"密文"项的集合记作τs1s2. 第二部就是将τs1s2带入到c1中来生成密文c2. 我们将这两个过程形式化. 首先第一步是要生成τs1s2, 即

  • SwitchKeyGen(s1,s2,n1,n2,q):
    1. 对于每个N=n1logq, 执行AE.PublicKeyGen(s2,N).
    2. B=A+[Powerof2(s1)|0]. 输出τs1s2=B.

其中第二步是一个批量操作, 此处是在将Powerof2(s1)加到A的第一列上去.

看到这里你也许会觉得蹊跷, 为什么没有二次项了? 实际上这里作者又换了一种写法, 将s1就视作是含有二次项的项. 在之前的BV11b方案中, 假设两个密文c,c均为s的密文, 那么他们做第一步同态运算但不替换密钥时, 则新的多项式函数(由新密文c表示的多项式函数)会包含s[i]s[j]项. 实际上, 我们大可不必这么认为, 我们可以认为有一个新的密钥向量s1包含了所有的s[i]s[j]项, 我们只需要认为s=ss即可. 实际上作者比我们还要更激进一点, 此时作者认为还可以将c进行Powerof2操作, 得到c1=Powerof2(c), 该密文就应该是s1=BitDecomp(s)下的密文. 同态运算第一步之后的结果即可认为是新密钥下的密文, 而我们的"加密"了所有的2τs1[i]项就是相当于时"加密"了所有的2τsi,j项了. 我们用τs1s2即可进行下一步的私钥切换.

  • SwitchKey(τs1s2,c1): 输出c2=BitDecomp(c1)TBRqn2.

模数切换

模数切换的方法我们也已经在前文中介绍完毕, 现在将其形式化

  • Scale(x,q,p,r): 输出距离(p/q)x最近且满足x=xmodr的向量x.

很明显, 这里我们是要将q模数下的密文x切换到p模数下的密文p. 而一般来说, 我们只加密一个比特, 即选择r=2.

我们之前已经估计了对于LWE下的密文, 这么做会导致噪声如何变化, 那么对于RLWE, 有类似的结果吗? 有的, 正如如下引理

引理3d是多项式环的次数. 令q>p>r为满足p=q=1modr的正整数. 令cRnc=Scale(c,q,p,r). 则对于任意sRn满足|[c,s]q|<q/2(q/p)(r/2)dγ(R)1(R)(s), 则有 [c,s]p=[c,s]q|[c,s]p|<(p/q)|[c,s]q|+(r/2)dγ(R)q(R)(s)

其中γ(R)为仅与R相关的任何函数, 而q(R)表示环R上定义的第一范数. 这个地方在介绍了RLWE后我将会回来补充. 这个引理的证明方式和引理1类似, 就不在这里赘述, 希望知道具体过程的读者可以翻阅[BGV12]论文中Lemma 4的证明.

Leveled FHE方案

铺垫到这里, 我们终于可以拿出LWE方案了. 实际上这里相比BV11b并没有多少新内容, 我们做的大部分工作是在带大家适应新的符号和解释模数切换的好处.

首先和其他的Leveled FHE一样, 有个Setup阶段

  • FHE.Setup(1λ,1L,b): 设μ=μ(λ,L,b)=θ(logλ+logL). 对于每个j=L to 0:

    1. 执行paramsjE.Setup(1λ,1(j+1)μ,b), 其中paramsj中的模数逐渐从qL降低到q0.

    对于每个j=L1 to 0

    1. dj=dL, χj=χL

这里的qL大概有(L+1)μ位, 其维数逐层降低到q0μ位. 此外, 每一层的d,χ参数需要与L层统一, 而维数n则没有这个要求. 这是由于在q变小时, 维数的减少不会影响方案的安全性, 毕竟当q下降时, 维数的减小不会然破解变得容易.

  • FHE.KeyGen({paramsj}): 对于每个j=L to 0, 执行:
    1. 执行sjE.SecretKeyGen(paramssj)AjE.PublicKeyGen(paramsj,sj)
    2. sjsjsj.
    3. sjBitDecomp(sj,qj).
    4. τsjsj1SwitchKeyGen(sj,sj1)3. (当j=L时不执行该步骤)

实际上上述算法中, 我们就生成了每一层的公私钥, 并且做好了每一层的τsjsj1, 则一部分在BV11b中被称为计算密钥. 注意我们先前已经说过了, 作者比较激进, 这里直接就将张量积后的密文做了BitDecomp再来生成密钥切换时的计算密钥, 那么对应的密文也要做Powerof2操作.

  • FHE.Enc(params,pk,m{0,1}): 计算并输出E.Enc(AL,m).
  • FHE.Dec(params,sk,c): 根据密钥的层数选择sj, 计算并输出E.Dec(sj,c).

此处我们忽略了确定密文层数的参数来化简表示. 接下来我们演示同态计算. 同态计算中, 需要用到密钥切换过程, 该过程包括模数切换过程和维数切换过程, 我们将其统一为一个Refresh过程, 首先要根据计算密钥的格式, 将乘法(或加法)得到的结果进行Powerof2操作, 然后依次进行模数切换和密钥切换, 总的来说是把一个$\mathbf s_j'=\mathbf{s}j\otimes\mathbf s_j\mathbf s{j-1}$下得密文. 我们将整个模数切换过程形式化.

  • FHE.Refresh(c,τsjsj1,qj,qj1):
    1. 计算c1Powerof2(c,qj)
    2. 计算c2Scale(c1,qj,qj1,2)
    3. 计算并输出c3SwitchKey(τsjsj1,c2,qj1)

最后我们补充完同态借助Refresh完成的同态运算过程:

  • FHE.Add(pk,c1,c2): 首先计算c3=c1+c2, 再计算输出c4=FHE.Refresh(c3,qj,qj1).
  • FHE.Mult(pk,c1,c2): 首先计算c3, 即由c1,c2所表示的多项式函数相乘得到的多项式函数对应的密文, 再计算并输出c4=FHE.Refresh(c3,qj,qj1).

这里要注意的是, 加法的密文后完全可以看做是sj=sjsj下的密文, 只需要令二次项表示的位为0就可以了.

其他

在作者阅读完代数数论和RLWE的知识后, 将会带各位阅读Batching部分的操作, 该部分内容可以极大地提升本方案的效率, 也被CKKS方案借鉴. Bootstrapping和安全性证明也将在之后完成.

注释


  1. Zvika Brakerski, Graig Gentry and Vindo Vaikuntanathan. Fully homomorphic encryption without bootstrapping. In Innovations in Theoretical Computer Science (ITCS'12), 2012. ↩︎

  2. 实际上LWE和RLWE的模数都不需要是素数, 而且后文中也没有提到是素数. 此处存疑. ↩︎

  3. 此处eprint上版本的原文中有笔误. ↩︎

Built with Hugo
Theme Stack designed by Jimmy