同态加密_学习笔记
半同态加密
Paillier加密系统
基本介绍
1.密钥生成 Paillier加密系统的密钥生成过程需要选择两个大素数,并使用它们来生成公钥和私钥。
选择两个大素数 $ p $ 和 $ q $。
计算模数 $ n = p \times q $,其中 $ n $ 是模数,公钥中的一个部分。
计算加密系统的秘密参数 $ \lambda(n) = \text{lcm}(p-1, q-1) $,其中 $ \text{lcm} $ 是最小公倍数,$ \lambda(n) $ 是加密系统的秘密参数。
- 选择一个随机整数 $ g $,要求 $ g $ 的阶为 $ n $ 的整数倍,$g^\lambda=1+an\ mod\ n^2$,$gcd(L(g^\lambda\ mod\ n^2),n)=1$,一般而言$g=n+1$是一个比较选择
- 计算 $ \mu = \left( L(g^{\lambda(n)} \mod n^2) \right)^{-1} \mod n $,其中 $ L(x) = \frac{x - 1}{n} $ 是一个辅助函数。
最终,Paillier的公钥是$(n,g)$,私钥是$(\lambda,\mu)$
2.加密 要求密文$m < n$
选择一个随机整数 $ r $,要求$ r < n $
加密 $ c=g^m\cdot r^n mod\ n^2 $
3.解密
- 解密 $m=L(c^\lambda \ mod\ n^2)\cdot\mu \ mod\ n $
4.同态性 这个系统仅有加法同态性 对密文$m1\ m2$
- $c_1=g^{m_1}\cdot r_1^{n}\ mod\ n^2$
- $c_2=g^{m_2}\cdot r_2^{n}\ mod\ n^2$
同态加法
- $c_3=c_1 \cdot c_2\ mod\ n^2 $
证明:
- $c_3=g^{m_1+m_2}\cdot (r_1\cdot r_2)^{n}\ mod\ n^2$
设$r_3=r_1\cdot r_2$
- 则$c_3=g^{m_1+m_2}\cdot (r_3)^{n}\ mod\ n^2$
对$c_3$解密:
- $m_3=L(c_3^\lambda \ mod\ n^2)\cdot \mu \ mod\ n $
- $m_3=L((g^{m_1+m_2}\cdot (r_3)^{n}\ mod\ n^2)^\lambda \ mod\ n^2)\cdot \mu \ mod\ n$
- $m_3=L((g^{(m_1+m_2)\cdot \lambda}\cdot (r_3)^{n\cdot \lambda}) \ mod\ n^2)\cdot \mu \ mod\ n$
利用$r^{n\cdot \lambda}=1\ mod\ n^2$
- $m_3=L((g^{(m_1+m_2)\cdot \lambda}) \ mod\ n^2)\cdot \mu \ mod\ n$
代入解密函数$L(x)=(x-1)/n$,注意以下就$g=n+1$进行讨论 分析$g^{m\cdot \lambda}\ mod\ n^2$
- $g^{m\cdot \lambda}\ mod\ n^2=(n+1)^{m\cdot \lambda}\ mod\ n^2$
二项式定理
- $(n+1)^{m\cdot \lambda}\ mod\ n^2=1+(m\cdot \lambda)\cdot n \ mod\ n^2$ #高阶项被约掉了
代入$L(x)=(x-1)/n$
- $L((g^{(m_1+m_2)\cdot \lambda}) \ mod\ n^2)=L(1+(m\cdot \lambda)\cdot n \ mod\ n^2)=m\cdot \lambda\ mod\ n$
所以
- $L((g^{(m_1+m_2)\cdot \lambda}) \ mod\ n^2)=m\cdot \lambda\ mod\ n$
- $m_3=L((g^{(m_1+m_2)\cdot \lambda}) \ mod\ n^2)\cdot \mu \ mod\ n=(m_1+m_2)\cdot \lambda\cdot \mu\ mod\ n$
利用$\mu$的定义$ \mu = \left( L(g^{\lambda(n)} \mod n^2) \right)^{-1} \mod n $
- $m_3=m_1+m_2\ mod\ n$
得证 其实上面的证明就是对解密的证明,如果解密已被证明,在令$m_3=L((g^{(m_1+m_2)\cdot \lambda}\cdot (r_3)^{n\cdot \lambda}) \ mod\ n^2)\cdot \mu \ mod\ n$已经可以有$m_3=m_1+m_2$
python实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
from gmpy2 import *
import libnum
from Crypto.Util.number import *
import random
# 密钥生成函数
def generate_keys(n):
"""
生成 Paillier 加密系统的公钥和私钥。
参数:
n (int): 素数的位数。
返回:
public_key (tuple): 公钥 (n, g)。
private_key (tuple): 私钥 (lambda_n, mu)。
"""
p = getPrime(n)
q = getPrime(n)
while p == q:
q = getPrime(n)
n = p * q
lambda_n = lcm(p - 1, q - 1)
g = n + 1
mu = gmpy2.invert((pow(g, lambda_n, n**2) - 1) // n, n)
return (n, g), (lambda_n, mu)
# 加密函数
def encrypt(m, public_key):
"""
使用公钥加密明文 m。
参数:
m (int): 明文。
public_key (tuple): 公钥 (n, g)。
返回:
c (int): 密文。
"""
n, g = public_key
r = random.randint(1, n - 1)
c = (pow(g, m, n**2) * pow(r, n, n**2)) % n**2
return c
# 解密函数
def decrypt(c, private_key, public_key):
"""
使用私钥解密密文 c。
参数:
c (int): 密文。
private_key (tuple): 私钥 (lambda_n, mu)。
public_key (tuple): 公钥 (n, g)。
返回:
m (int): 解密后的明文。
"""
n, g = public_key
lambda_n, mu = private_key
m = ((pow(c, lambda_n, n**2) - 1) // n * mu) % n
return m
# 同态加法函数
def evaladd(c1, c2, public_key):
"""
对两个密文进行同态加法运算。
参数:
c1 (int): 第一个密文。
c2 (int): 第二个密文。
public_key (tuple): 公钥 (n, g)。
返回:
c (int): 同态加法后的密文。
"""
n, g = public_key
c = (c1 * c2) % n**2
return c
# 主程序
if __name__ == '__main__':
# 生成公钥和私钥
public_key, private_key = generate_keys(128)
# 生成两个随机明文
m_1 = random.randint(1, 100321331)
m_2 = random.randint(1, 100321331)
m = m_1 + m_2 # 计算明文的和
# 加密明文
c_1 = encrypt(m_1, public_key)
c_2 = encrypt(m_2, public_key)
# 对密文进行同态加法
c = evaladd(c_1, c_2, public_key)
# 解密密文
decrypted_m = decrypt(c, private_key, public_key)
# 输出结果
print(f"明文: {m_1}+{m_2}={m}, 加密后: {c}, 解密后: {decrypted_m}")
ElGamal加密系统
基本介绍
它基于 Diffie-Hellman 密钥交换协议,主要用于加密和数字签名。ElGamal 算法的安全性依赖于离散对数问题的难解性。
1.密钥生成
选择一个大素数 $ p $
选择一个生成元 $ g $,生成元$g$是$p$的一个原根即$g$的阶是$\phi(p)=p-1 $
选择一个私钥整数$x$,$1<x<p-1$
计算公钥,$y=g^x\ mod\ p$ 最终公钥是$(p,g,y)$,私钥为$x$
2.加密过程
- 选择一个随机整数$k,1< k < p-1 $
- 计算密文的第一部分$c_1,c_1=g^k\ mod\ p$
- 计算密文的第二部分$c_2,c_2=M*y^k\ mod\ p$ 密文为$(c_1,c_2)$
3.解密过程
- 计算$s=c_1^x\ mod\ p$
- 计算密文$M=s^{-1}*c_2\ mod\ p$
4.同态验证(乘法)
- 记消息$m^1,m^2$,有对应密文对$(c_1^1,c_2^1),(c_1^2,c_2^2)$
- 同态乘法为对应的模乘法,有$c_1^3=c_1^1c_1^2,\ \ c_2^3=c_2^1c_2^2$
- 代入加密,有 $c_1^3=g^{k_1}g^{k_2}\ mod\ p=g^{k_3}\ mod\ p,k_3=k_1k_2$ $c_2^3=m_1m_2y^{g_3}\ mod\ p$
- 分析对应关系显然$m_3=m_1*m_2$,得证
python实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from gmpy2 import *
from Crypto.Util.number import *
import random
from sage.all import *
class ElGama:
def __init__(self,n):
self.p = getPrime(n)
self.g=primitive_root(self.p)
self.x=randint(1,(self.p-1))
self.y=pow(self.g,self.x,self.p)
def encrypt(self,m):
k=randint(1,self.p-1)
c_1=pow(self.g,k,self.p)
c_2=pow(self.y,k,self.p)*m%self.p
return (c_1,c_2)
def decrypt(self,c):
c_1,c_2=c
s = pow(c_1, self.x, self.p)
s_inv=gmpy2.invert(s,self.p)
m=c_2*s_inv%self.p
return m
elg=ElGama(32)
print(elg.decrypt(elg.encrypt(123)))