Paillier:最著名的半同态加密方案
何为同态加密(HE)?
HE是一种特殊的加密方法,它允许直接对加密数据执行计算,如加法和乘法,而计算过程不会泄露原文的任何信息。计算的结果仍然是加密的,拥有密钥的用户对处理过的密文数据进行解密后,得到的正好是处理后原文的结果
根据支持的计算类型和支持程度,同态加密可以分为以下三种类型:
半同态加密(Partially Homomorphic Encryption, PHE):只支持加法或乘法中的一种运算。其中,只支持加法运算的又叫 加法同态加密(Additive Homomorphic Encryption, AHE);
部分同态加密(Somewhat Homomorphic Encryption, SWHE):可同时支持加法和乘法运算,但支持的计算次数有限;
全同态加密(Fully Homomorphic Encryption, FHE):支持任意次的加法和乘法运算。
在同态加密概念被Rivest在1978年首次提出后,学术界出现了多个支持PHE的方案,如RSA、GM、Elgamal、Paillier。此后,SWHE方案也相继问世,如BGN。关于FHE如何实现,学术界在很长的时间都没有答案。直到2009年,Gentry使用理想格构造了第一个FHE方案,轰动了整个学术界,并引发了学者们对于FHE方案构造的研究热潮。此后相继涌现出多个优秀的FHE方案,包括BFV、BGV、CKKS等,以及多个优秀的开源算法库如SEAL、HELib等。
Paillier简介
Paillier是一个支持加法同态的公钥密码系统。由于其效率较高、安全性证明完备的特点,在各大顶会和实际应用中被广泛使用,是隐私计算场景中最常用的PHE实例化方案之一。
Paillier方案原理
前置知识
加法同态加密定义
在描述具体方案之前,我们先定义加法PHE。首先列举方案具有的所有算法。
KeyGen()
:密钥生成算法。用于产生加密数据的公钥PK(Public Key)和私钥SK(Secret Key),以及一些公开常数PP(Public Parameter);Encrypt()
:加密算法。使用PK对用户数据Data进行加密,得到密文CT(Ciphertext);Decrypt()
:解密算法。用于解密得到数据原文PT(Plaintext)。
HE除了加解密以外,还具有在密文上进行处理的能力,所以还应拥有“处理”算法。对于加法PHE,支持的算法有同态加以及同态标量乘(标量乘法可看作多次加法)。
Add()
:同态加算法。输入两个CT进行同态加运算。ScalaMul()
:同态标量乘算法。输入一个CT和一个标量PT,计算CT的标量乘结果。
Paillier方案描述
原版Paillier方案详见论文: Paillier P. Public-key cryptosystems based on composite degree residuosity classes[C] //International conference on the theory and applications of cryptographic techniques. Springer, Berlin, Heidelberg, 1999: 223-238
密钥生成
第一形式:
- 随机选择两个大素数p, q满足 gcd(pq,(p−1)(q−1))=1,且满足p,q长度相等。
- 计算n=pq及λ=lcm(p−1,q−1)=gcd(p−1,q−1)(p−1)(q−1),这里lcm表示最小公倍数,∣n∣为n的比特长度。
- 选择随机整数g←Zn2∗即0<g<n2。
- 定义L函数:L(x)=nx−1,计算μ=[L(gλ mod n2)]n−1。
公钥(n,g),私钥(λ,μ)。
第二形式(优化参数选择):
其余参数不变,主要改变g,λ,μ的定义。
g=n+1λ=ϕ(n)=(p−1)(q−1)μ=[ϕ(n)]n−1
加密
- 输入明文信息m,满足0≤m<n。
- 选择随机整数r,满足0≤r<n且r∈Zm∗。
- 计算密文c=gmrn mod n2。
解密
- 输入密文c,满足c∈Zn2∗。
- 计算明文信息m=L(cλ mod n2)⋅μ mod n。
同态加
对密文c1,c2,计算c=c1⋅c2 mod n2。
同态标量乘
对密文c1和标量a,计算c=c1a mod n2。
安全性
Paillier方案满足加密方案的标准安全定义:语义安全,即在选择明文攻击下的密文的不可区分性(IND-CPA)。直观地说,就是密文不会泄露明文中的任意信息。方案安全性可以归约到判定性合数剩余假设(Decisional Composite Residuosity Assumption, DCRA),即给定一个合数n和整数z,判定z是否在n^2下是否是n次剩余是困难的。这个假设经过了几十年的充分研究,到目前为止还没有多项式时间的算法可以攻破,所以Paillier加密方案的安全性被认为相当可靠。
CTF例题
DASCTF-2020四月-Crypto-not_RSA
from Crypto.Util.number import getPrime as getprime, long_to_bytes, bytes_to_long, inverse
from secret import flag, p, q
from sympy import isprime, nextprime
import random
m=bytes_to_long(flag)
n=p*q
g=n+1
r=random.randint(1,n)
c=(pow(g,m,n*n)*pow(r,n,n*n))%(n*n)
print "c=%d"%(c)
print "n=%d"%(n)
'''
c=29088911054711509252215615231015162998042579425917914434962376243477176757448053722602422672251758332052330100944900171067962180230120924963561223495629695702541446456981441239486190458125750543542379899722558637306740763104274377031599875275807723323394379557227060332005571272240560453811389162371812183549
n=6401013954612445818165507289870580041358569258817613282142852881965884799988941535910939664068503367303343695466899335792545332690862283029809823423608093
'''
思路
从Zn×Zn∗到Zn2∗存在双射关系(x,y)→gxyn(mod n2)
g∈Zn2∗,∴∃(a,b),s.t. g=(n+1)abn(mod n2)
cλ=(n+1)amλbnmλrnλ=(n+1)amλ=1+amλn(mod n2)
L(cλ mod n2)=amλ,同理L(gλ mod n2)=aλ,证毕
本题g=n+1,且n可以直接Fermat
分解得到p,q,按上述方法解密即可。
exp
from Crypto.Util.number import *
p = 80006336965345725157774618059504992841841040207998249416678435780577798937819
q = 80006336965345725157774618059504992841841040207998249416678435780577798937447
n = p * q
c = 29088911054711509252215615231015162998042579425917914434962376243477176757448053722602422672251758332052330100944900171067962180230120924963561223495629695702541446456981441239486190458125750543542379899722558637306740763104274377031599875275807723323394379557227060332005571272240560453811389162371812183549
lcm = ((p - 1) * (q - 1)) // GCD(p - 1, q - 1)
a = (pow(c, lcm, n * n) - 1) // n
b = (pow(n + 1, lcm, n * n) - 1) // n
m = long_to_bytes((a * inverse(b, n)) % n)
print(m)