| .. hazmat:: |
| |
| X25519 key exchange |
| =================== |
| |
| .. currentmodule:: cryptography.hazmat.primitives.asymmetric.x25519 |
| |
| |
| X25519 is an elliptic curve `Diffie-Hellman key exchange`_ using `Curve25519`_. |
| It 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. |
| |
| .. doctest:: |
| |
| >>> from cryptography.hazmat.backends import default_backend |
| >>> from cryptography.hazmat.primitives import hashes |
| >>> from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey |
| >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF |
| >>> # Generate a private key for use in the exchange. |
| >>> private_key = X25519PrivateKey.generate() |
| >>> # 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 = X25519PrivateKey.generate().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. |
| >>> private_key_2 = X25519PrivateKey.generate() |
| >>> peer_public_key_2 = X25519PrivateKey.generate().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) |
| |
| Key interfaces |
| ~~~~~~~~~~~~~~ |
| |
| .. class:: X25519PrivateKey |
| |
| .. versionadded:: 2.0 |
| |
| .. classmethod:: generate() |
| |
| Generate an X25519 private key. |
| |
| :returns: :class:`X25519PrivateKey` |
| |
| .. classmethod:: from_private_bytes(data) |
| |
| .. versionadded:: 2.5 |
| |
| A class method for loading an X25519 key encoded as |
| :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`. |
| |
| :param bytes data: 32 byte private key. |
| |
| :returns: :class:`X25519PrivateKey` |
| |
| .. doctest:: |
| |
| >>> from cryptography.hazmat.primitives import serialization |
| >>> from cryptography.hazmat.primitives.asymmetric import x25519 |
| >>> private_key = x25519.X25519PrivateKey.generate() |
| >>> private_bytes = private_key.private_bytes( |
| ... encoding=serialization.Encoding.Raw, |
| ... format=serialization.PrivateFormat.Raw, |
| ... encryption_algorithm=serialization.NoEncryption() |
| ... ) |
| >>> loaded_private_key = x25519.X25519PrivateKey.from_private_bytes(private_bytes) |
| |
| .. method:: public_key() |
| |
| :returns: :class:`X25519PublicKey` |
| |
| .. method:: exchange(peer_public_key) |
| |
| :param X25519PublicKey peer_public_key: The public key for the |
| peer. |
| |
| :returns bytes: A shared key. |
| |
| .. method:: private_bytes(encoding, format, encryption_algorithm) |
| |
| .. versionadded:: 2.5 |
| |
| Allows serialization of the key to bytes. Encoding ( |
| :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`, |
| :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or |
| :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and |
| format ( |
| :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8` |
| or |
| :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw` |
| ) are chosen to define the exact serialization. |
| |
| :param encoding: A value from the |
| :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum. |
| |
| :param format: A value from the |
| :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat` |
| enum. If the ``encoding`` is |
| :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw` |
| then ``format`` must be |
| :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw` |
| , otherwise it must be |
| :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`. |
| |
| :param encryption_algorithm: An instance of an object conforming to the |
| :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption` |
| interface. |
| |
| :return bytes: Serialized key. |
| |
| .. class:: X25519PublicKey |
| |
| .. versionadded:: 2.0 |
| |
| .. classmethod:: from_public_bytes(data) |
| |
| :param bytes data: 32 byte public key. |
| |
| :returns: :class:`X25519PublicKey` |
| |
| .. doctest:: |
| |
| >>> from cryptography.hazmat.primitives.asymmetric import x25519 |
| >>> private_key = x25519.X25519PrivateKey.generate() |
| >>> public_key = private_key.public_key() |
| >>> public_bytes = public_key.public_bytes( |
| ... encoding=serialization.Encoding.Raw, |
| ... format=serialization.PublicFormat.Raw |
| ... ) |
| >>> loaded_public_key = x25519.X25519PublicKey.from_public_bytes(public_bytes) |
| |
| .. method:: public_bytes(encoding, format) |
| |
| Allows serialization of the key to bytes. Encoding ( |
| :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`, |
| :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or |
| :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and |
| format ( |
| :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo` |
| or |
| :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw` |
| ) are chosen to define the exact serialization. |
| |
| :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. If the ``encoding`` is |
| :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw` |
| then ``format`` must be |
| :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw` |
| , otherwise it must be |
| :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`. |
| |
| :returns bytes: The public key bytes. |
| |
| |
| .. _`Diffie-Hellman key exchange`: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange |
| .. _`Curve25519`: https://en.wikipedia.org/wiki/Curve25519 |