Diffie-Hellman密钥交换
Diffie-Hellman的有效性是建立在计算离散对数很困难的这一基础上的。
算法:
第一步,选定一个素数q和它的原根a,并公开。
第二步,用户A和用户B分别选定私钥和(),并用公布的q和a分别计算
和作为A和B的公钥向对方公开。
第三步,A和B通过对方公开的公钥Y分别通过下式计算得出K,K便成了双方约定的密钥。
对A:
对B:
原理:
拿A的密钥生成式来分析
可以看出双方的K是相等的,至此双方完成了密钥的交换
如果用群的语言来描述,可以看出DH是在群上做操作,其中q为素数,a为群的生成元。
Python代码实现:
# /DF.py
# 计算a^b mod p
def mod_exp(a, b, p):
res = 1
while (b):
if b & 1:
res = (res * a) % p
b >>= 1
a = (a * a) % p
return res
# 通过给定的素数q、它的原根a、选定的私钥X
# 生成公钥Y
def generate_Y(q, a, X):
return mod_exp(a, X, q)
# 通过给定的素数q、它的原根a、选定的私钥X以及对方的公钥Y
# 生成密钥K
def df(q, a, X, Y):
return mod_exp(Y, X, q)
ElGamal密码体系
Elgamal是一种基于离散对数的公钥加密体制,与Diffie-Hellman密切相关。个人认为EG是基于DH的“密钥交换”而进行加密的,我也将ElGamal的加密算法分为 密钥交换 与 明文加密 两部分来理解。而其中,密钥交换部分采用的就是DF的方法。
算法:
加密:
用户A和用户B共同选择一个素数q,以及它的原根a。
用户A要做以下步骤:
1.随机生成整数(), 作为A的私钥。
2.计算。
3.将三元组作为用户A的公钥,其他用户可通过此公钥对信息进行加密。
其他任何用户B通过A的公开密钥可以加密信息。
用户B要做以下步骤进行数据加密:
1.选择任意整数
2.计算密钥
3.将信息表示为一个整数.
4.计算
5.计算
6.将完整密文发送给用户A
解密:
用户A收到,按如下步骤进行解密:
1.计算
2.计算,得到明文。
以上便是ElGamal的完整算法。
乍一看,似乎不太能看得懂这算法是在干嘛,为什么最后发送的不只是加密后的密文,而是一个二元组?
仔细分析,正如加密过后得到的二元组,其实Elgamal的加密算法包含了两个部分。
A.密钥交换:
首先,用户A与B共享了素数q与其原根a。
用户A做了以下步骤:
1.随机生成整数(), 作为A的私钥。
2.计算,并把提供给了用户B。
用户B也做了以下步骤:
1.选择任意整数
2.计算,并把提供给了用户A。
用户A通过计算得到K ,来解密信息
用户B通过计算得到K, 来加密信息
眼熟吗?对,这就是上面讲的Diffie-Hellman密钥交换算法。要是还是看不出来,只需要将上述的换成, 换成就与上面DH算法书写一模一样了。
既然用户A与B已经通过共享的信息确认了共享的密钥K,那么A和B就可以分别通过K来解密和加密信息了。
B.明文加密:
理解了密钥交换部分后,这一部分就显得很简单了。
用户B为了将明文加密,计算,这便是明文的密文。
为了能让用户A顺利的解密信息,用户B需要提供有关密钥K的信息发送给用户A,而这信息就是上述的。知道了,用户A就能计算出密钥K的数值,从而可以通过密文求出明文M.
这就是为什么用户B需要发送一个二元组发送给A。
Python代码实现:
# /EG.py
from DF import df, mod_exp
# 扩展欧几里得算法
def egcd(x, y):
a1, b1, c1 = 1, 0, x
a2, b2, c2 = 0, 1, y
while (c2):
d = c1 // c2
t1, t2, t3 = a1-d*a2, b1-d*b2, c1-d*c2
a1, b1, c1, a2, b2, c2 = a2, b2, c2, t1, t2, t3
return a1, b1, c1 # x模y的逆元 y模x的逆元 gcd(x, y)
# 求x的模p逆元
def inverse(x, p):
if x < p:
_, i, _ = egcd(p, x)
return i if i > 0 else p + i
else:
i, _, _ = egcd(p, x)
return i if i > 0 else p + i
#通过公钥三元组(q, a, Y)以及私钥X, 对明文M进行加密
def encrypt(q, a, Y, k, M):
K = df(q, a, k, Y)
CK = mod_exp(a, k, q)
CM = (K * M) % q
return (CK, CM)
#通过公钥三元组(q, a, Y)以及私钥X, 对密文D(CK, CM)进行加密
def decrypt(q, a, X, D):
CK = D[0]
CM = D[1]
K = df(q, a, X, CK)
M = (inverse(K, q) * CM) % q
return M
def test(q, a, XA, k, M):
print("原始明文为 M = ",M)
YA = mod_exp(a, XA, q)
D = encrypt(q, a, YA, k, M)
print("加密得明文密文 D = ", D)
m = decrypt(q, a, XA, D)
print("解密得明文 M = ", m)
q = 19
a = 10
XA = 5
k = 6
M = 17
test(q, a, XA, k, M)