diff options
Diffstat (limited to 'docs/hazmat/primitives/asymmetric/dh.rst')
| -rw-r--r-- | docs/hazmat/primitives/asymmetric/dh.rst | 403 |
1 files changed, 330 insertions, 73 deletions
diff --git a/docs/hazmat/primitives/asymmetric/dh.rst b/docs/hazmat/primitives/asymmetric/dh.rst index dde18cf7..edfe6143 100644 --- a/docs/hazmat/primitives/asymmetric/dh.rst +++ b/docs/hazmat/primitives/asymmetric/dh.rst @@ -5,114 +5,282 @@ Diffie-Hellman key exchange .. currentmodule:: cryptography.hazmat.primitives.asymmetric.dh +.. note:: + For security and performance reasons we suggest using + :class:`~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. + + +Exchange Algorithm +~~~~~~~~~~~~~~~~~~ + +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. + +.. code-block:: pycon + + >>> from cryptography.hazmat.backends import default_backend + >>> 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, + ... backend=default_backend()) + >>> # 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', + ... backend=default_backend() + ... ).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', + ... backend=default_backend() + ... ).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 :func:`~DHParameters.generate_private_key` for +each :meth:`~DHPrivateKey.exchange` when performing an DHE key exchange. An +example of the ephemeral form: + +.. code-block:: pycon + + >>> from cryptography.hazmat.backends import default_backend + >>> 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, + ... backend=default_backend()) + >>> # 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', + ... backend=default_backend() + ... ).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', + ... backend=default_backend() + ... ).derive(shared_key_2) + +To assemble a :class:`~DHParameters` and a :class:`~DHPublicKey` from +primitive integers, you must first create the +:class:`~DHParameterNumbers` and :class:`~DHPublicNumbers` objects. For +example, if **p**, **g**, and **y** are :class:`int` objects received from a +peer:: + + pn = dh.DHParameterNumbers(p, g) + parameters = pn.parameters(default_backend()) + peer_public_numbers = dh.DHPublicNumbers(y, pn) + peer_public_key = peer_public_numbers.public_key(default_backend()) + + +See also the :class:`~cryptography.hazmat.backends.interfaces.DHBackend` +API for additional functionality. + +Group parameters +~~~~~~~~~~~~~~~~ + +.. function:: generate_parameters(generator, key_size, backend) + + .. versionadded:: 1.7 + + Generate a new DH parameter group for use with ``backend``. + + :param generator: The :class:`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: A + :class:`~cryptography.hazmat.backends.interfaces.DHBackend` + instance. + + :returns: DH parameters as a new instance of + :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`. + + :raises ValueError: If ``key_size`` is not at least 512. -Numbers -~~~~~~~ -.. class:: DHPrivateNumbers(x, public_numbers) +.. class:: DHParameters - .. versionadded:: 0.8 + .. versionadded:: 1.7 - The collection of integers that make up a Diffie-Hellman private key. - .. attribute:: public_numbers + .. method:: generate_private_key() - :type: :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers` + Generate a DH private key. This method can be used to generate many + new private keys from a single set of parameters. - The :class:`DHPublicNumbers` which makes up the DH public - key associated with this DH private key. + :return: An instance of + :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`. - .. attribute:: x + .. method:: parameter_numbers() - :type: int + Return the numbers that make up this set of parameters. - The private value. + :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers`. + .. method:: parameter_bytes(encoding, format) -.. class:: DHPublicNumbers(parameters, y) + .. versionadded:: 2.0 - .. versionadded:: 0.8 + Allows serialization of the parameters to bytes. Encoding ( + :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or + :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`) and + format ( + :attr:`~cryptography.hazmat.primitives.serialization.ParameterFormat.PKCS3`) + are chosen to define the exact serialization. - The collection of integers that make up a Diffie-Hellman public key. + :param encoding: A value from the + :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum. - .. attribute:: parameter_numbers + :param format: A value from the + :class:`~cryptography.hazmat.primitives.serialization.ParameterFormat` + enum. At the moment only ``PKCS3`` is supported. - :type: :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers` + :return bytes: Serialized parameters. - The parameters for this DH group. +.. class:: DHParametersWithSerialization - .. attribute:: y + .. versionadded:: 1.7 - :type: int + Alias for :class:`DHParameters`. - The public value. +Key interfaces +~~~~~~~~~~~~~~ -.. class:: DHParameterNumbers(p, g) +.. class:: DHPrivateKey - .. versionadded:: 0.8 + .. versionadded:: 1.7 - The collection of integers that define a Diffie-Hellman group. + A DH private key that is not an :term:`opaque key` also implements + :class:`DHPrivateKeyWithSerialization` to provide serialization methods. - .. attribute:: p + .. attribute:: key_size - :type: int + The bit length of the prime modulus. - The prime modulus value. + .. method:: public_key() - .. attribute:: g + Return the public key associated with this private key. - :type: int + :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`. - The generator value. + .. method:: parameters() + Return the parameters associated with this private key. -Key interfaces -~~~~~~~~~~~~~~ + :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`. -.. class:: DHParameters + .. method:: exchange(peer_public_key) - .. versionadded:: 0.9 + .. versionadded:: 1.7 + :param DHPublicKey peer_public_key: The public key for + the peer. - .. method:: generate_private_key() + :return bytes: The agreed key. The bytes are ordered in 'big' endian. - .. versionadded:: 0.9 - Generate a DH private key. This method can be used to generate many - new private keys from a single set of parameters. +.. class:: DHPrivateKeyWithSerialization - :return: A - :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey` - provider. + .. versionadded:: 1.7 + This interface contains additional methods relating to serialization. + Any object with this interface also has all the methods from + :class:`DHPrivateKey`. -.. class:: DHParametersWithSerialization + .. method:: private_numbers() - .. versionadded:: 0.9 + Return the numbers that make up this private key. - Inherits from :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`. + :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateNumbers`. - .. method:: parameter_numbers() + .. method:: private_bytes(encoding, format, encryption_algorithm) - Return the numbers that make up this set of parameters. + .. versionadded:: 1.8 - :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers`. + Allows serialization of the key to bytes. Encoding ( + :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or + :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`), + format ( + :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`) + and encryption algorithm (such as + :class:`~cryptography.hazmat.primitives.serialization.BestAvailableEncryption` + or :class:`~cryptography.hazmat.primitives.serialization.NoEncryption`) + are chosen to define the exact serialization. + :param encoding: A value from the + :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum. -.. class:: DHPrivateKey + :param format: A value from the + :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat` + enum. - .. versionadded:: 0.9 + :param encryption_algorithm: An instance of an object conforming to the + :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption` + interface. - .. attribute:: key_size + :return bytes: Serialized key. - The bit length of the prime modulus. - .. method:: public_key() +.. class:: DHPublicKey - Return the public key associated with this private key. + .. versionadded:: 1.7 - :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`. + .. attribute:: key_size + + The bit length of the prime modulus. .. method:: parameters() @@ -120,43 +288,132 @@ Key interfaces :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`. + .. method:: public_numbers() -.. class:: DHPrivateKeyWithSerialization + Return the numbers that make up this public key. - .. versionadded:: 0.9 + :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers`. - Inherits from :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`. + .. method:: public_bytes(encoding, format) - .. method:: private_numbers() + .. versionadded:: 1.8 - Return the numbers that make up this private key. + Allows serialization of the key to bytes. Encoding ( + :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or + :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`) and + format ( + :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`) + are chosen to define the exact serialization. - :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateNumbers`. + :param encoding: A value from the + :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum. + :param format: A value from the + :class:`~cryptography.hazmat.primitives.serialization.PublicFormat` enum. -.. class:: DHPublicKey + :return bytes: Serialized key. - .. versionadded:: 0.9 +.. class:: DHPublicKeyWithSerialization - .. attribute:: key_size + .. versionadded:: 1.7 - The bit length of the prime modulus. + Alias for :class:`DHPublicKey`. - .. method:: parameters() - Return the parameters associated with this private key. +Numbers +~~~~~~~ - :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`. +.. class:: DHParameterNumbers(p, g, q=None) + .. versionadded:: 0.8 -.. class:: DHPublicKeyWithSerialization + The collection of integers that define a Diffie-Hellman group. - .. versionadded:: 0.9 + .. attribute:: p - Inherits from :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`. + :type: int - .. method:: public_numbers() + The prime modulus value. - Return the numbers that make up this public key. + .. attribute:: g - :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers`. + :type: int + + The generator value. Must be 2 or greater. + + .. attribute:: q + + .. versionadded:: 1.8 + + :type: int + + p subgroup order value. + + .. method:: parameters(backend) + + .. versionadded:: 1.7 + + :param backend: An instance of + :class:`~cryptography.hazmat.backends.interfaces.DHBackend`. + + :returns: A new instance of :class:`DHParameters`. + +.. class:: DHPrivateNumbers(x, public_numbers) + + .. versionadded:: 0.8 + + The collection of integers that make up a Diffie-Hellman private key. + + .. attribute:: public_numbers + + :type: :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicNumbers` + + The :class:`DHPublicNumbers` which makes up the DH public + key associated with this DH private key. + + .. attribute:: x + + :type: int + + The private value. + + .. method:: private_key(backend) + + .. versionadded:: 1.7 + + :param backend: An instance of + :class:`~cryptography.hazmat.backends.interfaces.DHBackend`. + + :returns: A new instance of :class:`DHPrivateKey`. + + +.. class:: DHPublicNumbers(y, parameter_numbers) + + .. versionadded:: 0.8 + + The collection of integers that make up a Diffie-Hellman public key. + + .. attribute:: parameter_numbers + + :type: :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameterNumbers` + + The parameters for this DH group. + + .. attribute:: y + + :type: int + + The public value. + + .. method:: public_key(backend) + + .. versionadded:: 1.7 + + :param backend: An instance of + :class:`~cryptography.hazmat.backends.interfaces.DHBackend`. + + :returns: A new instance of :class:`DHPublicKey`. + + +.. _`Diffie-Hellman key exchange`: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange +.. _`forward secrecy`: https://en.wikipedia.org/wiki/Forward_secrecy |
