这篇文章主要介绍LattiGo团队搞出来的一个多方同态加密的工作。个人觉得比较优雅,而且有库支持,方便把玩,所以记一下。
在攒毕业论文的时候整了这么个看上去很烂,但是(个人觉得)有一点意思的烂活,没心思写那么多的公式,各位dalao凑合看,欢迎轻喷。
实现了CKKS方案的一个多方计算版本(对BFV也适用)。这个多方版本的方案将私钥拆分成了 n n n份分给 n n n个计算方,一方一个。
对应的安全性:只要这 n n n方别都是内鬼(比如所有方都沆瀣一气,沟通私钥),这个同态加密方案就具有语义安全性。
可以基于上述私钥拆分的想法设计一些有趣的多方解密/自举方案。
引个流,看这儿。
首先定义 n n n 个计算方: P = P 1 , . . . , P N \mathcal P = P_1, ..., P_N P=P1,...,PN。
参与计算的 n n n方都随机生成一个私钥碎片 s k i , for i = 1 , . . . , n sk_i, \textit{for}\ i=1,...,n ski,for i=1,...,n。最后 s k = ∑ s k i sk = \sum sk_i sk=∑ski就是完整的私钥多项式。这意味着每一方都持有一个私钥的碎片。
在具体操作中,可以让客户端先线下生成 n n n个私钥碎片再分发给 n n n个计算方,或者每个计算方先生成私钥碎片再发送给客户端。
在方案运行过程中,各个计算方持有一个私钥碎片和全部的公钥。
我们先假设客户端持有私钥。那么客户端其实已经可以根据私钥计算出一系列的公钥,比如加密公钥、重线性化钥、旋转钥blablabla,然后公布给 n n n个计算方使用。
至于 n n n个计算方如何派生出这一系列公钥,可以在看完下面多方解密和多方自举部分后留作文末习题(doge
我们先通过介绍多方解密和多方自举方案来阐明文章里的一些核心想法。
对于密文多项式对 c = ( c 0 , c 1 ) c=(c_0, c_1) c=(c0,c1),解密方案就是求解 m = c 0 + c 1 ⋅ s k m = c_0+c_1\cdot sk m=c0+c1⋅sk。
这里,多方参与完成解密就是计算 c 0 + c 1 ⋅ ∑ s k i c_0+c_1\cdot \sum sk_i c0+c1⋅∑ski。
解密方法如下:
各方计算 c 1 ⋅ s k i + e i c_1 \cdot sk_i + e_i c1⋅ski+ei,其中 e i e_i ei是噪声。然后计算
c 0 + ∑ ( c 1 ⋅ s k i + e i ) c_0+ \sum (c_1 \cdot sk_i+e_i) c0+∑(c1⋅ski+ei)
就完成了解密(虽然带了点噪声)。
在这个方案中,RLWE问题的语义安全性保证了 s k i sk_i ski很难被爆破,于是只要至少有一个计算方不是内鬼(不是内鬼:指保护好自己的私钥碎片),那么私钥就不会被破解。
在实现多方自举之前,我们首先让各个计算方生成一个公有的密文 d d d。
首先各方生成随机密文 d i d_i di,然后各方共同参与求和,得到 d = ∑ d i d = \sum d_i d=∑di。 d d d被对外公布。
在这个过程中,只要计算方不是全员内鬼,那么 d i d_i di和 d d d就是语义安全的。
基于上述这些秘密 d i d_i di和 d d d,我们可以设计多方自举方案。
对于密文多项式对 c = ( c 0 , c 1 ) c=(c_0, c_1) c=(c0,c1):
首先,各方计算 c 1 ⋅ s k i + d i + e i c_1\cdot sk_i +d_i + e_i c1⋅ski+di+ei,其中 e i e_i ei是噪声。
求和得到 m = c 0 + ∑ ( c 1 ⋅ s k i + d i + e i ) m = c_0 + \sum(c_1\cdot sk_i +d_i + e_i) m=c0+∑(c1⋅ski+di+ei)。
然后,计算 m − d m - d m−d。
于是多方自举就完成了。
本质上是对解密后的明文加上一层mask,然后再把它抹掉就完事了。
课后习题:
n n n个计算方如何派生出加密公钥、重线性化钥、旋转钥blablabla一系列公钥呢?