简述

何为DH密钥间换协议?

DH密钥交换是1976年由Diffie和Hellman共同发明的一种算法。使用这种算法,通信双方仅通过交换一些可以公开的信息就能够生成出共享的密码数字,而这一密码数字就可以被用作对称密码的密钥。IPsec中就使用了经过改良的DH密钥交换。

虽然这种方法的名字叫“密钥交换”,但实际上双方并没有真正交换密钥,而是通过计算生成出一个相同的共享密钥。因此,这种方法也称DH密钥协商。

DH内容

DH协议内容如下:

  • 协议使用一个质数p的整数模n乘法群以及其原根g
    Alice与Bob协定使用 p以及base g
    Alice选择一个秘密整数a, 计算A = g^a mod p并发送给Bob。
    Bob选择一个秘密整数b, 计算B = g^b mod p并发送给Alice。
    Alice计算alice_key = B a mod p
    Bob计算bob_key = A b mod p

这样就实现了密钥的交换,互相可以计算出会话密钥。

代码实现

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
#!/usr/bin/python3.7
# -*- coding: utf-8 -*-
# @Time : 2019/12/25 17:01
# @Software: PyCharm

from random import randrange, choice

# 判断素数
def judgePrimeNumber(num):
# 不能被2~sqrt(m)(取整)之间的整数整除的数即素数
sqrtResult = int(num ** 0.5)
for i in range(2, sqrtResult + 1):
if num % i == 0:
return False
return True

# 判断互质
def judgeCoPrime(a, b):
# 求最大公因数
def maxCommonFactor(m, n):
result = 0
while m % n > 0:
result = m % n
m = n
n = result
return result
if maxCommonFactor(a, b) == 1:
return True
return False

# 求所有本原根
def getPrimitiveRoot(primeNumber):
primeList = []
primitiveRootList = []
# 求出所有互素元素
for i in range(1, primeNumber):
if judgeCoPrime(i, primeNumber):
primeList.append(i)
for i in primeList:
tmpList = []
for j in range(1, len(primeList) + 1):
tmpList.append(i ** j % primeNumber)
# 排序判断是否相同,相同则为
tmpList.sort()
if primeList == tmpList:
primitiveRootList.append(i)
return primitiveRootList

# 产生公钥
def createPubKey(primeNumber, primitiveRoot, randNum1, randNum2):
pubKey1 = primitiveRoot ** randNum1 % primeNumber
pubKey2 = primitiveRoot ** randNum2 % primeNumber
return pubKey1, pubKey2

# 得到会话密钥
def createSubKey(primeNumber, pubKey1, pubKey2, randNum1, randNum2):
subKey1 = pubKey2 ** randNum1 % primeNumber
subKey2 = pubKey1 ** randNum2 % primeNumber
return subKey1, subKey2

if __name__ == "__main__":
print("—————Diffie-Hellman密钥交换—————")
while True:
primeNumber = int(input("输入共同素数:"))
if judgePrimeNumber(primeNumber):
break
# 两个随机数
randNum1 = randrange(primeNumber)
randNum2 = randrange(primeNumber)
print("A随机数:", randNum1, "\nB随机数:", randNum2)
# 挑选一个本原根
primitiveRootList = getPrimitiveRoot(primeNumber)
primitiveRoot = choice(primitiveRootList)
print("所有本原根:", primitiveRootList)
print("本次的本原根:", primitiveRoot)
# 双方公钥和会话密钥
pubKey1, pubKey2 = createPubKey(primeNumber, primitiveRoot, randNum1, randNum2)
print("A公钥:", pubKey1, "\nB公钥:", pubKey2)
subKey1, subKey2 = createSubKey(primeNumber, pubKey1, pubKey2, randNum1, randNum2)
if subKey1 == subKey2: # 必然成立
print("AB共同会话密钥:", subKey1)

运行结果:
在这里插入图片描述