cdcq的密码学教程三——同态加密的Paillier算法

一、前言

什么是同态加密?

同态加密就是指对密文做某种运算后相当于对明文做某种运算。例如经典的 RSA 算法就是一个乘法同态的加密算法:

c1m1e mod nc2m2e mod nc1c2(m1m2)e mod nc_1 \equiv m_1 ^ e\ mod\ n \\ c_2 \equiv m_2 ^ e\ mod\ n \\ c_1 * c_2 \equiv (m_1 * m_2) ^ e\ mod\ n

一般地,如果一对加解密算法 E(m)E(m)D(c)D(c) 满足 D(F2(E(m1),E(m2)))=F1(m1,m2)D(F_2(E(m_1), E(m_2))) = F_1(m_1, m_2) ,那么我们就说这个算法是对操作 F1(x,y)F_1(x, y) 同态的。

同态加密有什么用?

如果你可以在本地就执行所有的操作,那当然是没有必要加密啦。但是许多场景是要在异地计算的,例如云计算,本地的算力不够,要提交到服务器计算,但是又不希望泄漏计算数据的隐私;或者是多方计算,一个计算涉及多台主机,就可以使用同态加密。

Paillier 是比较入门的一种同态加密算法,支持两个加密数字相加或者一个加密数字乘上一个明文数字,本文就主要介绍这个算法。

二、Paillier 公钥加密系统

Paillier 是一个公钥加密系统,由三部分组成:密钥生成算法、加密算法和解密算法。

密钥生成算法:

  1. 随机选取两个大质数 p 和 q ,保证 gcd(pq,(p1)(q1))=1gcd(pq, (p - 1)(q - 1)) = 1

  2. 模数 n=pqn = pq

  3. [1,n2][1, n^2] 中随机选取一个整数 gg 作为公钥,λ=lcm(p1,q1)\lambda = lcm(p - 1, q - 1) 为私钥。

  4. 定义 L(x)=x1nL(x) = \frac{x - 1}{n} ,计算 μ(L(gλ mod n2))1 mod n\mu \equiv (L(g^\lambda\ mod\ n^2))^{-1}\ mod\ n 。如果 μ\mu 不存在则重新执行密钥生成算法。

加密算法:

明文 mm 应该是区间 [0,n)[0, n) 中的一个整数。

  1. (0,n)(0, n) 中随机选取一个整数 rr

  2. 密文 cgmrn mod n2c \equiv g^mr^n\ mod\ n^2

解密算法:

密文 cc 应该是区间 (0,n2)(0, n^2) 中的一个整数

明文 mL(cλ mod n2)μ mod nm \equiv L(c^\lambda\ mod\ n^2) \cdot \mu\ mod\ n

三、解密算法的正确性证明

有些朋友可能看完加密算法一头雾水,为何会同时存在两个模数 nnn2n^2LL 函数这么一个奇怪的定义又是怎么回事?这事要从二项式定理说起。

我们都知道二项式定理:

(1+n)x=k=0x(kx)nk.(1 + n)^x = \sum_{k = 0}^x \binom{k}{x}n^k .

在模 n2n^2 意义下,就有

(1+n)x1+nx+(2x)n2+...1+nx mod n2.(1 + n)^x \equiv 1 + nx + \binom{2}{x}n^2 + ... \equiv 1+nx\ mod\ n^2 .

把两边变化一下,可以得到

x(1+n)x1n mod n2.x \equiv \frac{(1 + n)^x - 1}{n}\ mod\ n^2 .

这意味着我们可以轻易地计算形如 (1+kn)x(1 + kn)^x 的数在模 n2n^2 意义下关于 (1+kn)(1 + kn) 的对数,方法就是通过 LL 函数计算。

此外还需要知道一个结论,Carmichael 定理:ppqq 是大质数,n=pqn = pqλ=lcm(p1,q1)\lambda = lcm(p - 1, q - 1) ,对于任意整数 ww

{wλ1 mod nwnλ1 mod n2\left\{ \begin{aligned} w^\lambda \equiv 1\ mod\ n \\ w^{n\lambda} \equiv 1\ mod\ n^2 \\ \end{aligned} \right.

证明:

第一条很显然,利用欧拉定理得到。

由第一条可以知道 wλ=1+knw^\lambda = 1 + kn ,那么 wnλ=(1+kn)nw^{n\lambda} = (1 + kn)^n ,根据之前有关二项式定理的结论就有

wnλ(1+kn)n1+kn2+(2n)k2n2+...1 mod n2.w^{n\lambda} \equiv (1 + kn)^n \equiv 1 + kn^2 + \binom{2}{n}k^2n^2 + ... \equiv 1\ mod\ n^2 .

现在来看解密公式

L(cλ mod n2)μL(cλ mod n2)L(gλ mod n2) mod n.L(c^\lambda\ mod\ n^2) \cdot \mu \equiv \frac{L(c^\lambda\ mod\ n^2)}{L(g^\lambda\ mod\ n^2)}\ mod\ n .

其中

cλgmλrnλgmλ mod n2.c^\lambda \equiv g^{m\lambda}r^{n\lambda} \equiv g^{m\lambda}\ mod\ n^2 .

所以

L(cλ mod n2)L(gλ mod n2)L(gmλ mod n2)L(gλ mod n2) mod n.\frac{L(c^\lambda\ mod\ n^2)}{L(g^\lambda\ mod\ n^2)} \equiv \frac{L(g^{m\lambda}\ mod\ n^2)}{L(g^\lambda\ mod\ n^2)} \ mod\ n .

考察 gλg^\lambda ,有

gλ1 mod n.g^\lambda \equiv 1\ mod\ n .

所以

gλ1+kn mod n2gmλ(1+kn)m1+knm mod n2.g^\lambda \equiv 1 + kn\ mod\ n^2 \\ g^{m\lambda} \equiv (1 + kn)^m \equiv 1 + knm \ mod\ n^2 .

那么

L(gλ mod n2)=gλ1n=kL(gmλ mod n2)=gmλ1n=km.L(g^\lambda\ mod\ n^2) = \frac{g^\lambda - 1}{n} = k \\ L(g^{m\lambda}\ mod\ n^2) = \frac{g^{m\lambda} - 1}{n} = km .

因此

L(gmλ mod n2)L(gλ mod n2)kmkm mod n.\frac{L(g^{m\lambda}\ mod\ n^2)}{L(g^\lambda\ mod\ n^2)} \equiv \frac{km}{k} \equiv m\ mod\ n .

这样就证明了 Paillier 算法的正确性。

看到这里我们可以说:Paillier 本质是利用了计算某些离散对数很容易的问题。随机数 rr 是用来遮蔽明文的,但如果有私钥 λ\lambda ,就可以将 rr 消除掉,然后计算离散对数得到 mm

Paillier 原文采用的是另一种角度证明,先证明了加密函数是双射的,然后可以得到一些结论。此外原文还说用中国剩余定理可以加速解密过程,这里就不多说了。

四、Paillier 算法的同态操作

Paillier 的同态操作原理还是比较简单的,基本上自己都能推出来。

让密文相乘就可以使两个加密数相加:

c1=gm1r1nc2=gm2r2nc1c2=gm1+m2(r1r2)n.c_1 = g^{m_1}{r_1}^n \\ c_2 = g^{m_2}{r_2}^n \\ c_1c_2 = g^{m_1 + m_2}(r_1r_2)^n .

c1c2c_1c_2 解密就可以得到 m1+m2m_1 + m_2

对密文做 aa 次方就可以使一个加密数乘上 aa

c=gmrnca=gamran.c = g^mr^n \\ c^a = g^{am}r^{an} .

解密就得到 amam

由此可以看出 Paillier 算法不需要公钥就可以实现同态操作。

五、后记

学这个算法的过程也算比较坎坷,因为网络上没啥证明的教程。有一篇文章居然说为了方便起见,选 g=1+ng = 1 + n ,证明倒是方便了,但我觉得不合适。所幸有一片知乎文章写得很清楚,加上算法本身不算难,最后也是搞懂了。希望这篇文章能让后来者学得更轻松一些。

参考文章:

知乎教程,作者“民科局长”:https://zhuanlan.zhihu.com/p/106340045?utm_source=weibo

一篇英文教程,但是没有证明:https://blog.openmined.org/the-paillier-cryptosystem/

论文原文:https://www.cs.tau.ac.il/~fiat/crypt07/papers/Pai99pai.pdf