cryptography.hazmat.primitives.asymmetric.dh
Note
For security and performance reasons we suggest using ~cryptography.hazmat.primitives.asymmetric.ec.ECDH
instead of DH where possible.
Diffie-Hellman key exchange (D–H) is a method that allows two parties to jointly agree on a shared secret using an insecure channel.
For most applications the shared_key
should be passed to a key derivation function. This allows mixing of additional information into the key, derivation of multiple keys, and destroys any structure that may be present.
Warning
This example does not give forward secrecy and is only provided as a demonstration of the basic Diffie-Hellman construction. For real world applications always use the ephemeral form described after this example.
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import dh
>>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
>>> # Generate some parameters. These can be reused.
>>> parameters = dh.generate_parameters(generator=2, key_size=2048)
>>> # Generate a private key for use in the exchange.
>>> server_private_key = parameters.generate_private_key()
>>> # In a real handshake the peer is a remote client. For this
>>> # example we'll generate another local private key though. Note that in
>>> # a DH handshake both peers must agree on a common set of parameters.
>>> peer_private_key = parameters.generate_private_key()
>>> shared_key = server_private_key.exchange(peer_private_key.public_key())
>>> # Perform key derivation.
>>> derived_key = HKDF(
... algorithm=hashes.SHA256(),
... length=32,
... salt=None,
... info=b'handshake data',
... ).derive(shared_key)
>>> # And now we can demonstrate that the handshake performed in the
>>> # opposite direction gives the same final value
>>> same_shared_key = peer_private_key.exchange(
... server_private_key.public_key()
... )
>>> same_derived_key = HKDF(
... algorithm=hashes.SHA256(),
... length=32,
... salt=None,
... info=b'handshake data',
... ).derive(same_shared_key)
>>> derived_key == same_derived_key
DHE (or EDH), the ephemeral form of this exchange, is strongly preferred over simple DH and provides forward secrecy when used. You must generate a new private key using ~DHParameters.generate_private_key
for each ~DHPrivateKey.exchange
when performing an DHE key exchange. An example of the ephemeral form:
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import dh
>>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
>>> # Generate some parameters. These can be reused.
>>> parameters = dh.generate_parameters(generator=2, key_size=2048)
>>> # Generate a private key for use in the exchange.
>>> private_key = parameters.generate_private_key()
>>> # In a real handshake the peer_public_key will be received from the
>>> # other party. For this example we'll generate another private key and
>>> # get a public key from that. Note that in a DH handshake both peers
>>> # must agree on a common set of parameters.
>>> peer_public_key = parameters.generate_private_key().public_key()
>>> shared_key = private_key.exchange(peer_public_key)
>>> # Perform key derivation.
>>> derived_key = HKDF(
... algorithm=hashes.SHA256(),
... length=32,
... salt=None,
... info=b'handshake data',
... ).derive(shared_key)
>>> # For the next handshake we MUST generate another private key, but
>>> # we can reuse the parameters.
>>> private_key_2 = parameters.generate_private_key()
>>> peer_public_key_2 = parameters.generate_private_key().public_key()
>>> shared_key_2 = private_key_2.exchange(peer_public_key_2)
>>> derived_key_2 = HKDF(
... algorithm=hashes.SHA256(),
... length=32,
... salt=None,
... info=b'handshake data',
... ).derive(shared_key_2)
To assemble a ~DHParameters
and a ~DHPublicKey
from primitive integers, you must first create the ~DHParameterNumbers
and ~DHPublicNumbers
objects. For example, if p, g, and y are int
objects received from a peer:
pn = dh.DHParameterNumbers(p, g)
parameters = pn.parameters()
peer_public_numbers = dh.DHPublicNumbers(y, pn)
peer_public_key = peer_public_numbers.public_key()
See also the ~cryptography.hazmat.backends.interfaces.DHBackend
API for additional functionality.
generate_parameters(generator, key_size, backend=None)
1.7
Generate a new DH parameter group for use with backend
.
- param generator
The
int
to use as a generator. Must be 2 or 5.- param key_size
The bit length of the prime modulus to generate.
- param backend
An optional
~cryptography.hazmat.backends.interfaces.DHBackend
instance.- returns
DH parameters as a new instance of
~cryptography.hazmat.primitives.asymmetric.dh.DHParameters
.- raises ValueError
If
key_size
is not at least 512.
1.7
generate_private_key()
Generate a DH private key. This method can be used to generate many new private keys from a single set of parameters.
- return
An instance of
~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey
.
parameter_numbers()
Return the numbers that make up this set of parameters.
- return
A
~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers
.
parameter_bytes(encoding, format)
2.0
Allows serialization of the parameters to bytes. Encoding ( ~cryptography.hazmat.primitives.serialization.Encoding.PEM
or ~cryptography.hazmat.primitives.serialization.Encoding.DER
) and format ( ~cryptography.hazmat.primitives.serialization.ParameterFormat.PKCS3
) are chosen to define the exact serialization.
- param encoding
A value from the
~cryptography.hazmat.primitives.serialization.Encoding
enum.- param format
A value from the
~cryptography.hazmat.primitives.serialization.ParameterFormat
enum. At the moment onlyPKCS3
is supported.- return bytes
Serialized parameters.
1.7
Alias for DHParameters
.
1.7
A DH private key that is not an opaque key
also implements DHPrivateKeyWithSerialization
to provide serialization methods.
key_size
The bit length of the prime modulus.
public_key()
Return the public key associated with this private key.
- return
A
~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey
.
parameters()
Return the parameters associated with this private key.
- return
A
~cryptography.hazmat.primitives.asymmetric.dh.DHParameters
.
exchange(peer_public_key)
1.7
- param DHPublicKey peer_public_key
The public key for the peer.
- return bytes
The agreed key. The bytes are ordered in 'big' endian.
1.7
This interface contains additional methods relating to serialization. Any object with this interface also has all the methods from DHPrivateKey
.
private_numbers()
Return the numbers that make up this private key.
- return
A
~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateNumbers
.
private_bytes(encoding, format, encryption_algorithm)
1.8
Allows serialization of the key to bytes. Encoding ( ~cryptography.hazmat.primitives.serialization.Encoding.PEM
or ~cryptography.hazmat.primitives.serialization.Encoding.DER
), format ( ~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8
) and encryption algorithm (such as ~cryptography.hazmat.primitives.serialization.BestAvailableEncryption
or ~cryptography.hazmat.primitives.serialization.NoEncryption
) are chosen to define the exact serialization.
- param encoding
A value from the
~cryptography.hazmat.primitives.serialization.Encoding
enum.- param format
A value from the
~cryptography.hazmat.primitives.serialization.PrivateFormat
enum.- param encryption_algorithm
An instance of an object conforming to the
~cryptography.hazmat.primitives.serialization.KeySerializationEncryption
interface.- return bytes
Serialized key.
1.7
key_size
The bit length of the prime modulus.
parameters()
Return the parameters associated with this private key.
- return
A
~cryptography.hazmat.primitives.asymmetric.dh.DHParameters
.
public_numbers()
Return the numbers that make up this public key.
- return
A
~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers
.
public_bytes(encoding, format)
1.8
Allows serialization of the key to bytes. Encoding ( ~cryptography.hazmat.primitives.serialization.Encoding.PEM
or ~cryptography.hazmat.primitives.serialization.Encoding.DER
) and format ( ~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo
) are chosen to define the exact serialization.
- param encoding
A value from the
~cryptography.hazmat.primitives.serialization.Encoding
enum.- param format
A value from the
~cryptography.hazmat.primitives.serialization.PublicFormat
enum.- return bytes
Serialized key.
1.7
Alias for DHPublicKey
.
0.8
The collection of integers that define a Diffie-Hellman group.
p
- type
int
The prime modulus value.
g
- type
int
The generator value. Must be 2 or greater.
q
1.8
- type
int
p subgroup order value.
parameters(backend=None)
1.7
- param backend
An optional instance of
~cryptography.hazmat.backends.interfaces.DHBackend
.- returns
A new instance of
DHParameters
.
0.8
The collection of integers that make up a Diffie-Hellman private key.
public_numbers
- type
~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers
The DHPublicNumbers
which makes up the DH public key associated with this DH private key.
x
- type
int
The private value.
private_key(backend=None)
1.7
- param backend
An optional instance of
~cryptography.hazmat.backends.interfaces.DHBackend
.- returns
A new instance of
DHPrivateKey
.
0.8
The collection of integers that make up a Diffie-Hellman public key.
parameter_numbers
- type
~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers
The parameters for this DH group.
y
- type
int
The public value.
public_key(backend=None)
1.7
- param backend
An optional instance of
~cryptography.hazmat.backends.interfaces.DHBackend
.- returns
A new instance of
DHPublicKey
.