Python Diffie-Hellman 交换加密库。共享密钥不一样

Python Diffie-Hellman exchange cryptography library. Shared key not the same

按照密码学库文档中列出的教程,我成功创建了一个演示 Diffie-Hellman 交换的函数。我现在正在尝试创建概念验证套接字服务器和套接字客户端。

此应用程序的一个未记录的要求是向客户端发送 public 密钥。这需要对 DHPublicKey 对象进行序列化和序列化,以便通过套接字发送它。

然而,通过这样做,共享密钥就不一样了!我尝试使用不同的编码格式(例如 PEM)来查看这是否有所不同。不幸的是它没有。我在双方都得到了不同的共享密钥。这是我的代码示例。

客户

parameters             = dh.generate_parameters(generator=2, key_size=1024, backend=default_backend())
client_private_key     = parameters.generate_private_key()
client_public_key      = client_private_key.public_key().public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo)

# Recv Server Pub key
length            = s.recv(2) # Prepend the length of the message
server_public_key = s.recv(int.from_bytes(length, "big"))
print("Got server public key: " + str(server_public_key))
server_public_key = load_der_public_key(server_public_key, default_backend())

# Send Pub key
s.send(len(client_public_key).to_bytes(2, "big") + client_public_key)

print("Generating shared key...")
shared_key = client_private_key.exchange(server_public_key)
print("Our shared key!: " + str(shared_key))

服务器

parameters = dh.generate_parameters(generator=2, key_size=1024, backend=default_backend())
server_private_key   = parameters.generate_private_key()
server_public_key    = server_private_key.public_key().public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo)

newsocket.send(len(server_public_key).to_bytes(2, "big") + server_public_key)
print("Sent server public key: " + str(server_public_key))

length            = newsocket.recv(2) # Prepend the length of the message
client_public_key = newsocket.recv(int.from_bytes(length, "big"))
client_public_key = load_der_public_key(client_public_key, default_backend())

# Send the public key to the client
shared_key = server_private_key.exchange(client_public_key)

print("Our shared key is: " + str(shared_key))

如前所述,我正在使用 Python 3 Library Cryptography 并使用以下导入

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import dh
from cryptography.hazmat.primitives.serialization import PublicFormat, Encoding, load_der_public_key

此外,将代码放入一个文件中(没有网络序列化)也可以!关键是一样的!这是工作代码的示例

print("SERVER: Performing DH exchange. DH 2048-bit key size")
parameters = dh.generate_parameters(generator=2, key_size=2048, backend=default_backend()) # Generate a 256-byte key

print("SERVER: Generating server private and public keys")
server_private_key     = parameters.generate_private_key()
server_peer_public_key = server_private_key.public_key()

print("CLIENT: Generating private and public keys")
client_private_key     = parameters.generate_private_key()
client_peer_public_key = client_private_key.public_key()

print("SERVER: Sending public key to client")
print("CLIENT: Sending public key to server")

server_shared_key = server_private_key.exchange(client_peer_public_key)
client_shared_key = client_private_key.exchange(server_peer_public_key)
print("server key is: " + str(server_shared_key))
print("client key is: " + str(client_shared_key))

序列化或反序列化密钥时我做错了什么?

您的问题与序列化和反序列化密钥无关,这是因为您在服务器和客户端上生成了不同的 DH 参数。它们必须相同,Diffie Hellman 才能工作。

您可以在服务器上生成参数并将它们发送到客户端,但更好的选择是使用一组预定义参数,例如 group 14 defined in RFC 3526.

为此,更改行

parameters = dh.generate_parameters(generator=2, key_size=1024, backend=default_backend())

在客户端和服务器中:

p = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF
g = 2

params_numbers = dh.DHParameterNumbers(p,g)
parameters = params_numbers.parameters(default_backend())

现在客户端和服务器将使用同一组参数,并且密钥协议将起作用。它也会快得多,参数生成是一个昂贵的过程。

您在单个文件中的代码可以工作,因为您只生成了一组供交易双方使用的参数。