Diffie-Hellman Key Exchange
Diffie-Hellman (DH) solves the key distribution problem over an insecure channel: two parties who share no secret can agree on one, while an eavesdropper sees only public values. Alice picks a private exponent a and publishes g^a mod p; Bob picks b and publishes g^b mod p; each side can then compute g^ab mod p - the shared secret - but deriving it from the two public values alone means solving the discrete logarithm problem.
The Math in Python
p = 23 # public prime
g = 5 # public generator
a, b = 6, 15 # private exponents (secret)
A = pow(g, a, p) # 8 - Alice's public value
B = pow(g, b, p) # 19 - Bob's public value
secret_alice = pow(B, a, p) # 2
secret_bob = pow(A, b, p) # 2
print(secret_alice == secret_bob) # True
The toy parameters make the arithmetic visible; production primes are hundreds of digits long, and the group (or curve) must be chosen from a vetted list - that is exactly what the standard curves and groups exist for.
X25519 in the cryptography Library
Modern protocols use elliptic-curve DH - ECDHE - with X25519 as the standard curve. The exchange method performs the whole computation:
from cryptography.hazmat.primitives.asymmetric import x25519
alice = x25519.X25519PrivateKey.generate()
bob = x25519.X25519PrivateKey.generate()
alice_secret = alice.exchange(bob.public_key())
bob_secret = bob.exchange(alice.public_key())
print(alice_secret == bob_secret) # True - 32 shared bytes
# feed the result through a KDF to derive the session key
Static vs Ephemeral Keys
Running DH with long-lived key pairs gives a shared secret but no forward secrecy: if the private key leaks later, all past sessions can be replayed. Ephemeral DH - a fresh key pair per handshake - means each session's key exists only in that exchange, so compromising the long-term identity key does not expose old traffic. TLS 1.3 mandates ECDHE, which is why exchange is the primitive behind every modern TLS handshake.
What DH Gives (and Does Not)
- Gives: agreement on a shared secret with no prior shared secret.
- Does not give: authentication - an active attacker can run two separate exchanges, one per side, and sit in the middle. DH must be paired with a signature over the public values (certificates) or a pre-shared key to bind them to identities.
Summary
Use X25519 exchange for key agreement in Python: ephemeral by default, fast, and the ECDHE primitive behind TLS 1.3. Run the 32-byte shared output through a KDF before using it as an encryption key, and remember that DH alone authenticates nothing - always pair it with signatures or certificates.