aboutsummaryrefslogtreecommitdiffstats
path: root/docs/hazmat/primitives/asymmetric
diff options
context:
space:
mode:
Diffstat (limited to 'docs/hazmat/primitives/asymmetric')
-rw-r--r--docs/hazmat/primitives/asymmetric/dh.rst403
-rw-r--r--docs/hazmat/primitives/asymmetric/dsa.rst264
-rw-r--r--docs/hazmat/primitives/asymmetric/ec.rst767
-rw-r--r--docs/hazmat/primitives/asymmetric/ed25519.rst166
-rw-r--r--docs/hazmat/primitives/asymmetric/ed448.rst131
-rw-r--r--docs/hazmat/primitives/asymmetric/index.rst10
-rw-r--r--docs/hazmat/primitives/asymmetric/interfaces.rst32
-rw-r--r--docs/hazmat/primitives/asymmetric/rsa.rst307
-rw-r--r--docs/hazmat/primitives/asymmetric/serialization.rst328
-rw-r--r--docs/hazmat/primitives/asymmetric/utils.rst70
-rw-r--r--docs/hazmat/primitives/asymmetric/x25519.rst184
-rw-r--r--docs/hazmat/primitives/asymmetric/x448.rst179
12 files changed, 2303 insertions, 538 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
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index 179bb8d1..7b059869 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -17,19 +17,18 @@ Generation
Generate a DSA private key from the given key size. This function will
generate a new set of parameters and key in one step.
- :param int key_size: The length of the modulus in bits. It should be
- either 1024, 2048 or 3072. For keys generated in 2015 this should
+ :param int key_size: The length of the modulus in :term:`bits`. It should
+ be either 1024, 2048 or 3072. For keys generated in 2015 this should
be `at least 2048`_ (See page 41). Note that some applications
(such as SSH) have not yet gained support for larger key sizes
specified in FIPS 186-3 and are still restricted to only the
1024-bit keys specified in FIPS 186-2.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
- :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
- provider.
+ :return: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
the provided ``backend`` does not implement
@@ -41,19 +40,18 @@ Generation
Generate DSA parameters using the provided ``backend``.
- :param int key_size: The length of the modulus in bits. It should be
- either 1024, 2048 or 3072. For keys generated in 2015 this should
- be `at least 2048`_ (See page 41). Note that some applications
+ :param int key_size: The length of :attr:`~DSAParameterNumbers.q`. It
+ should be either 1024, 2048 or 3072. For keys generated in 2015 this
+ should be `at least 2048`_ (See page 41). Note that some applications
(such as SSH) have not yet gained support for larger key sizes
specified in FIPS 186-3 and are still restricted to only the
1024-bit keys specified in FIPS 186-2.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
- :return: A :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`
- provider.
+ :return: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
the provided ``backend`` does not implement
@@ -63,7 +61,7 @@ Signing
~~~~~~~
Using a :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
-provider.
+instance.
.. doctest::
@@ -74,34 +72,77 @@ provider.
... key_size=1024,
... backend=default_backend()
... )
- >>> signer = private_key.signer(hashes.SHA256())
>>> data = b"this is some data I'd like to sign"
- >>> signer.update(data)
- >>> signature = signer.finalize()
+ >>> signature = private_key.sign(
+ ... data,
+ ... hashes.SHA256()
+ ... )
The ``signature`` is a ``bytes`` object, whose contents is DER encoded as
-described in :rfc:`6979`. This can be decoded using
-:func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_rfc6979_signature`.
+described in :rfc:`3279`. This can be decoded using
+:func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`.
+
+If your data is too large to be passed in a single call, you can hash it
+separately and pass that value using
+:class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+.. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric import utils
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> sig = private_key.sign(
+ ... digest,
+ ... utils.Prehashed(chosen_hash)
+ ... )
Verification
~~~~~~~~~~~~
-Using a :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`
-provider.
+Verification is performed using a
+:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` instance.
+You can get a public key object with
+:func:`~cryptography.hazmat.primitives.serialization.load_pem_public_key`,
+:func:`~cryptography.hazmat.primitives.serialization.load_der_public_key`,
+:meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers.public_key`
+, or
+:meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey.public_key`.
.. doctest::
>>> public_key = private_key.public_key()
- >>> verifier = public_key.verifier(signature, hashes.SHA256())
- >>> verifier.update(data)
- >>> verifier.verify()
+ >>> public_key.verify(
+ ... signature,
+ ... data,
+ ... hashes.SHA256()
+ ... )
-``verifier()`` takes the signature in the same format as is returned by
-``signer.finalize()``.
+``verify()`` takes the signature in the same format as is returned by
+``sign()``.
``verify()`` will raise an :class:`~cryptography.exceptions.InvalidSignature`
exception if the signature isn't valid.
+If your data is too large to be passed in a single call, you can hash it
+separately and pass that value using
+:class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+.. doctest::
+
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> public_key.verify(
+ ... sig,
+ ... digest,
+ ... utils.Prehashed(chosen_hash)
+ ... )
+
Numbers
~~~~~~~
@@ -131,13 +172,11 @@ Numbers
.. method:: parameters(backend)
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
- :returns: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`
- provider.
+ :returns: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`.
.. class:: DSAPublicNumbers(y, parameter_numbers)
@@ -160,13 +199,11 @@ Numbers
.. method:: public_key(backend)
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
- :returns: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`
- provider.
+ :returns: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`.
.. class:: DSAPrivateNumbers(x, public_numbers)
@@ -194,13 +231,11 @@ Numbers
.. method:: private_key(backend)
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
- :returns: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
- provider.
+ :returns: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`.
Key interfaces
~~~~~~~~~~~~~~
@@ -218,9 +253,8 @@ Key interfaces
Generate a DSA private key. This method can be used to generate many
new private keys from a single set of parameters.
- :return: A
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
- provider.
+ :return: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`.
.. class:: DSAParametersWithNumbers
@@ -244,7 +278,9 @@ Key interfaces
.. versionadded:: 0.3
- A `DSA`_ private key.
+ A `DSA`_ private key. A DSA private key that is not an
+ :term:`opaque key` also implements :class:`DSAPrivateKeyWithSerialization`
+ to provide serialization methods.
.. method:: public_key()
@@ -258,54 +294,39 @@ Key interfaces
The DSAParameters object associated with this private key.
- .. method:: signer(algorithm, backend)
-
- .. versionadded:: 0.4
-
- Sign data which can be verified later by others using the public key.
- The signature is formatted as DER-encoded bytes, as specified in
- :rfc:`6979`.
-
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
-
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
-
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext`
-
.. attribute:: key_size
:type: int
- The bit length of the modulus.
+ The bit length of :attr:`~DSAParameterNumbers.q`.
+ .. method:: sign(data, algorithm)
-.. class:: DSAPrivateKeyWithNumbers
+ .. versionadded:: 1.5
+ .. versionchanged:: 1.6
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ can now be used as an ``algorithm``.
- .. versionadded:: 0.5
+ Sign one block of data which can be verified later by others using the
+ public key.
- Extends :class:`DSAPrivateKey`.
+ :param bytes data: The message string to sign.
- .. method:: private_numbers()
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ if the ``data`` you want to sign has already been hashed.
- Create a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateNumbers`
- object.
-
- :returns: A
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateNumbers`
- instance.
+ :return bytes: Signature.
.. class:: DSAPrivateKeyWithSerialization
.. versionadded:: 0.8
- Extends :class:`DSAPrivateKey`.
+ This interface contains additional methods relating to serialization.
+ Any object with this interface also has all the methods from
+ :class:`DSAPrivateKey`.
.. method:: private_numbers()
@@ -355,7 +376,7 @@ Key interfaces
:type: int
- The bit length of the modulus.
+ The bit length of :attr:`~DSAParameterNumbers.q`.
.. method:: parameters()
@@ -363,50 +384,6 @@ Key interfaces
The DSAParameters object associated with this public key.
- .. method:: verifier(signature, algorithm, backend)
-
- .. versionadded:: 0.4
-
- Verify data was signed by the private key associated with this public
- key.
-
- :param bytes signature: The signature to verify. DER encoded as
- specified in :rfc:`6979`.
-
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
-
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
-
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext`
-
-
-.. class:: DSAPublicKeyWithNumbers
-
- .. versionadded:: 0.5
-
- Extends :class:`DSAPublicKey`.
-
- .. method:: public_numbers()
-
- Create a
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers`
- object.
-
- :returns: A
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers`
- instance.
-
-.. class:: DSAPublicKeyWithSerialization
-
- .. versionadded:: 0.8
-
- Extends :class:`DSAPublicKey`.
-
.. method:: public_numbers()
Create a
@@ -434,8 +411,37 @@ Key interfaces
:return bytes: Serialized key.
+ .. method:: verify(signature, data, algorithm)
+
+ .. versionadded:: 1.5
+ .. versionchanged:: 1.6
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ can now be used as an ``algorithm``.
+
+ Verify one block of data was signed by the private key
+ associated with this public key.
+
+ :param bytes signature: The signature to verify.
+
+ :param bytes data: The message string that was signed.
+
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ if the ``data`` you want to sign has already been hashed.
+
+ :raises cryptography.exceptions.InvalidSignature: If the signature does
+ not validate.
+
+
+.. class:: DSAPublicKeyWithSerialization
+
+ .. versionadded:: 0.8
+
+ Alias for :class:`DSAPublicKey`.
+
.. _`DSA`: https://en.wikipedia.org/wiki/Digital_Signature_Algorithm
.. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography
-.. _`FIPS 186-4`: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
-.. _`at least 2048`: http://www.ecrypt.eu.org/ecrypt2/documents/D.SPA.20.pdf
+.. _`FIPS 186-4`: https://csrc.nist.gov/publications/detail/fips/186/4/final
+.. _`at least 2048`: https://www.cosic.esat.kuleuven.be/ecrypt/ecrypt2/documents/D.SPA.20.pdf
diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst
index 71f6e6fd..bd52aeee 100644
--- a/docs/hazmat/primitives/asymmetric/ec.rst
+++ b/docs/hazmat/primitives/asymmetric/ec.rst
@@ -12,13 +12,29 @@ Elliptic curve cryptography
Generate a new private key on ``curve`` for use with ``backend``.
- :param backend: A :class:`EllipticCurve` provider.
+ :param curve: An instance of :class:`EllipticCurve`.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
- :returns: A new instance of a :class:`EllipticCurvePrivateKey` provider.
+ :returns: A new instance of :class:`EllipticCurvePrivateKey`.
+
+
+.. function:: derive_private_key(private_value, curve, backend)
+
+ .. versionadded:: 1.6
+
+ Derive a private key from ``private_value`` on ``curve`` for use with
+ ``backend``.
+
+ :param int private_value: The secret scalar value.
+
+ :param curve: An instance of :class:`EllipticCurve`.
+
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
+
+ :returns: A new instance of :class:`EllipticCurvePrivateKey`.
Elliptic Curve Signature Algorithms
@@ -31,9 +47,8 @@ Elliptic Curve Signature Algorithms
The ECDSA signature algorithm first standardized in NIST publication
`FIPS 186-3`_, and later in `FIPS 186-4`_.
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
.. doctest::
@@ -43,15 +58,71 @@ Elliptic Curve Signature Algorithms
>>> private_key = ec.generate_private_key(
... ec.SECP384R1(), default_backend()
... )
- >>> signer = private_key.signer(ec.ECDSA(hashes.SHA256()))
- >>> signer.update(b"this is some data I'd like")
- >>> signer.update(b" to sign")
- >>> signature = signer.finalize()
+ >>> data = b"this is some data I'd like to sign"
+ >>> signature = private_key.sign(
+ ... data,
+ ... ec.ECDSA(hashes.SHA256())
+ ... )
+
+ The ``signature`` is a ``bytes`` object, whose contents are DER encoded as
+ described in :rfc:`3279`. This can be decoded using
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`.
+
+ If your data is too large to be passed in a single call, you can hash it
+ separately and pass that value using
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric import utils
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> sig = private_key.sign(
+ ... digest,
+ ... ec.ECDSA(utils.Prehashed(chosen_hash))
+ ... )
+
+
+ Verification requires the public key, the DER-encoded signature itself, the
+ signed data, and knowledge of the hashing algorithm that was used when
+ producing the signature:
- The ``signature`` is a ``bytes`` object, whose contents is DER encoded as
- described in :rfc:`6979`. This can be decoded using
- :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_rfc6979_signature`.
+ >>> public_key = private_key.public_key()
+ >>> public_key.verify(signature, data, ec.ECDSA(hashes.SHA256()))
+ As above, the ``signature`` is a ``bytes`` object whose contents are DER
+ encoded as described in :rfc:`3279`. It can be created from a raw ``(r,s)``
+ pair by using
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.encode_dss_signature`.
+
+ If the signature is not valid, an
+ :class:`~cryptography.exceptions.InvalidSignature` exception will be raised.
+
+ If your data is too large to be passed in a single call, you can hash it
+ separately and pass that value using
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+ .. doctest::
+
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> public_key.verify(
+ ... sig,
+ ... digest,
+ ... ec.ECDSA(utils.Prehashed(chosen_hash))
+ ... )
+
+ .. note::
+ Although in this case the public key was derived from the private one,
+ in a typical setting you will not possess the private key. The
+ `Key loading`_ section explains how to load the public key from other
+ sources.
.. class:: EllipticCurvePrivateNumbers(private_value, public_numbers)
@@ -78,16 +149,21 @@ Elliptic Curve Signature Algorithms
Convert a collection of numbers into a private key suitable for doing
actual cryptographic operations.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
- :returns: A new instance of a :class:`EllipticCurvePrivateKey`
- provider.
+ :returns: A new instance of :class:`EllipticCurvePrivateKey`.
.. class:: EllipticCurvePublicNumbers(x, y, curve)
+ .. warning::
+ The point represented by this object is not validated in any way until
+ :meth:`EllipticCurvePublicNumbers.public_key` is called and may not
+ represent a valid point on the curve. You should not attempt to perform
+ any computations using the values from this class until you have either
+ validated it yourself or called ``public_key()`` successfully.
+
.. versionadded:: 0.5
The collection of integers that make up an EC public key.
@@ -115,148 +191,330 @@ Elliptic Curve Signature Algorithms
Convert a collection of numbers into a public key suitable for doing
actual cryptographic operations.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
+
+ :raises ValueError: Raised if the point is invalid for the curve.
+ :returns: A new instance of :class:`EllipticCurvePublicKey`.
+
+ .. method:: encode_point()
+
+ .. warning::
+
+ This method is deprecated as of version 2.5. Callers should migrate
+ to using
+ :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.public_bytes`.
+
+ .. versionadded:: 1.1
+
+ Encodes an elliptic curve point to a byte string as described in
+ `SEC 1 v2.0`_ section 2.3.3. This method only supports uncompressed
+ points.
+
+ :return bytes: The encoded point.
+
+ .. classmethod:: from_encoded_point(curve, data)
+
+ .. versionadded:: 1.1
- :returns: A new instance of a :class:`EllipticCurvePublicKey`
- provider.
+ .. note::
+
+ This has been deprecated in favor of
+ :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.from_encoded_point`
+
+ Decodes a byte string as described in `SEC 1 v2.0`_ section 2.3.3 and
+ returns an :class:`EllipticCurvePublicNumbers`. This method only
+ supports uncompressed points.
+
+ :param curve: An
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`
+ instance.
+
+ :param bytes data: The serialized point byte string.
+
+ :returns: An :class:`EllipticCurvePublicNumbers` instance.
+
+ :raises ValueError: Raised on invalid point type or data length.
+
+ :raises TypeError: Raised when curve is not an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`.
+
+Elliptic Curve Key Exchange algorithm
+-------------------------------------
+
+.. class:: ECDH()
+
+ .. versionadded:: 1.1
+
+ The Elliptic Curve Diffie-Hellman Key Exchange algorithm first standardized
+ in NIST publication `800-56A`_, and later in `800-56Ar2`_.
+
+ 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.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import ec
+ >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+ >>> # Generate a private key for use in the exchange.
+ >>> server_private_key = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... )
+ >>> # In a real handshake the peer is a remote client. For this
+ >>> # example we'll generate another local private key though.
+ >>> peer_private_key = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... )
+ >>> shared_key = server_private_key.exchange(
+ ... ec.ECDH(), 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(
+ ... ec.ECDH(), server_private_key.public_key())
+ >>> # Perform key derivation.
+ >>> 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
+ True
+
+ ECDHE (or EECDH), the ephemeral form of this exchange, is **strongly
+ preferred** over simple ECDH and provides `forward secrecy`_ when used.
+ You must generate a new private key using :func:`generate_private_key` for
+ each :meth:`~EllipticCurvePrivateKey.exchange` when performing an ECDHE key
+ exchange. An example of the ephemeral form:
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import ec
+ >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+ >>> # Generate a private key for use in the exchange.
+ >>> private_key = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... )
+ >>> # 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.
+ >>> peer_public_key = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... ).public_key()
+ >>> shared_key = private_key.exchange(ec.ECDH(), 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 = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... )
+ >>> peer_public_key_2 = ec.generate_private_key(
+ ... ec.SECP384R1(), default_backend()
+ ... ).public_key()
+ >>> shared_key_2 = private_key_2.exchange(ec.ECDH(), 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)
Elliptic Curves
---------------
Elliptic curves provide equivalent security at much smaller key sizes than
-asymmetric cryptography systems such as RSA or DSA. For some operations they
-can also provide higher performance at every security level. According to NIST
-they can have as much as a `64x lower computational cost than DH`_.
+other asymmetric cryptography systems such as RSA or DSA. For many operations
+elliptic curves are also significantly faster; `elliptic curve diffie-hellman
+is faster than diffie-hellman`_.
.. note::
Curves with a size of `less than 224 bits`_ should not be used. You should
- strongly consider using curves of at least 224 bits.
+ strongly consider using curves of at least 224 :term:`bits`.
Generally the NIST prime field ("P") curves are significantly faster than the
other types suggested by NIST at both signing and verifying with ECDSA.
Prime fields also `minimize the number of security concerns for elliptic-curve
-cryptography`_. However there is `some concern`_ that both the prime field and
+cryptography`_. However, there is `some concern`_ that both the prime field and
binary field ("B") NIST curves may have been weakened during their generation.
Currently `cryptography` only supports NIST curves, none of which are
considered "safe" by the `SafeCurves`_ project run by Daniel J. Bernstein and
Tanja Lange.
-All named curves are providers of :class:`EllipticCurve`.
+All named curves are instances of :class:`EllipticCurve`.
-.. class:: SECT571K1
+.. class:: SECP256R1
.. versionadded:: 0.5
- SECG curve ``sect571k1``. Also called NIST K-571.
+ SECG curve ``secp256r1``. Also called NIST P-256.
-.. class:: SECT409K1
+.. class:: SECP384R1
.. versionadded:: 0.5
- SECG curve ``sect409k1``. Also called NIST K-409.
+ SECG curve ``secp384r1``. Also called NIST P-384.
-.. class:: SECT283K1
+.. class:: SECP521R1
.. versionadded:: 0.5
- SECG curve ``sect283k1``. Also called NIST K-283.
+ SECG curve ``secp521r1``. Also called NIST P-521.
-.. class:: SECT233K1
+.. class:: SECP224R1
.. versionadded:: 0.5
- SECG curve ``sect233k1``. Also called NIST K-233.
+ SECG curve ``secp224r1``. Also called NIST P-224.
-.. class:: SECT163K1
+.. class:: SECP192R1
.. versionadded:: 0.5
- SECG curve ``sect163k1``. Also called NIST K-163.
+ SECG curve ``secp192r1``. Also called NIST P-192.
-.. class:: SECT571R1
+.. class:: SECP256K1
- .. versionadded:: 0.5
+ .. versionadded:: 0.9
- SECG curve ``sect571r1``. Also called NIST B-571.
+ SECG curve ``secp256k1``.
-.. class:: SECT409R1
+.. class:: BrainpoolP256R1
+
+ .. versionadded:: 2.2
+
+ Brainpool curve specified in :rfc:`5639`. These curves are discouraged
+ for new systems.
+
+.. class:: BrainpoolP384R1
+
+ .. versionadded:: 2.2
+
+ Brainpool curve specified in :rfc:`5639`. These curves are discouraged
+ for new systems.
+
+.. class:: BrainpoolP512R1
+
+ .. versionadded:: 2.2
+
+ Brainpool curve specified in :rfc:`5639`. These curves are discouraged
+ for new systems.
+
+.. class:: SECT571K1
.. versionadded:: 0.5
- SECG curve ``sect409r1``. Also called NIST B-409.
+ SECG curve ``sect571k1``. Also called NIST K-571. These binary curves are
+ discouraged for new systems.
-.. class:: SECT283R1
+.. class:: SECT409K1
.. versionadded:: 0.5
- SECG curve ``sect283r1``. Also called NIST B-283.
+ SECG curve ``sect409k1``. Also called NIST K-409. These binary curves are
+ discouraged for new systems.
-.. class:: SECT233R1
+.. class:: SECT283K1
.. versionadded:: 0.5
- SECG curve ``sect233r1``. Also called NIST B-233.
+ SECG curve ``sect283k1``. Also called NIST K-283. These binary curves are
+ discouraged for new systems.
-.. class:: SECT163R2
+.. class:: SECT233K1
.. versionadded:: 0.5
- SECG curve ``sect163r2``. Also called NIST B-163.
+ SECG curve ``sect233k1``. Also called NIST K-233. These binary curves are
+ discouraged for new systems.
-.. class:: SECP521R1
+.. class:: SECT163K1
.. versionadded:: 0.5
- SECG curve ``secp521r1``. Also called NIST P-521.
+ SECG curve ``sect163k1``. Also called NIST K-163. These binary curves are
+ discouraged for new systems.
-.. class:: SECP384R1
+.. class:: SECT571R1
.. versionadded:: 0.5
- SECG curve ``secp384r1``. Also called NIST P-384.
+ SECG curve ``sect571r1``. Also called NIST B-571. These binary curves are
+ discouraged for new systems.
-.. class:: SECP256R1
+.. class:: SECT409R1
.. versionadded:: 0.5
- SECG curve ``secp256r1``. Also called NIST P-256.
+ SECG curve ``sect409r1``. Also called NIST B-409. These binary curves are
+ discouraged for new systems.
-.. class:: SECT224R1
+.. class:: SECT283R1
.. versionadded:: 0.5
- SECG curve ``secp224r1``. Also called NIST P-224.
+ SECG curve ``sect283r1``. Also called NIST B-283. These binary curves are
+ discouraged for new systems.
-.. class:: SECP192R1
+.. class:: SECT233R1
.. versionadded:: 0.5
- SECG curve ``secp192r1``. Also called NIST P-192.
+ SECG curve ``sect233r1``. Also called NIST B-233. These binary curves are
+ discouraged for new systems.
-.. class:: SECP256K1
+.. class:: SECT163R2
+
+ .. versionadded:: 0.5
+
+ SECG curve ``sect163r2``. Also called NIST B-163. These binary curves are
+ discouraged for new systems.
- .. versionadded:: 0.9
- SECG curve ``secp256k1``.
Key Interfaces
@@ -270,7 +528,7 @@ Key Interfaces
.. attribute:: name
- :type: string
+ :type: str
The name of the curve. Usually the name used for the ASN.1 OID such as
``secp256k1``.
@@ -279,18 +537,23 @@ Key Interfaces
:type: int
- The bit length of the curve's base point.
+ Size (in :term:`bits`) of a secret scalar for the curve (as generated
+ by :func:`generate_private_key`).
.. class:: EllipticCurveSignatureAlgorithm
.. versionadded:: 0.5
+ .. versionchanged:: 1.6
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ can now be used as an ``algorithm``.
A signature algorithm for use with elliptic curve keys.
.. attribute:: algorithm
- :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ :type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
The digest algorithm to be used with the signature scheme.
@@ -300,19 +563,30 @@ Key Interfaces
.. versionadded:: 0.5
An elliptic curve private key for use with an algorithm such as `ECDSA`_ or
- `EdDSA`_.
+ `EdDSA`_. An elliptic curve private key that is not an
+ :term:`opaque key` also implements
+ :class:`EllipticCurvePrivateKeyWithSerialization` to provide serialization
+ methods.
+
+ .. method:: exchange(algorithm, peer_public_key)
- .. method:: signer(signature_algorithm)
+ .. versionadded:: 1.1
- Sign data which can be verified later by others using the public key.
- The signature is formatted as DER-encoded bytes, as specified in
- :rfc:`6979`.
+ Performs a key exchange operation using the provided algorithm with
+ the peer's public key.
- :param signature_algorithm: An instance of a
- :class:`EllipticCurveSignatureAlgorithm` provider.
+ 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.
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext`
+ :param algorithm: The key exchange algorithm, currently only
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.ECDH` is
+ supported.
+ :param EllipticCurvePublicKey peer_public_key: The public key for the
+ peer.
+
+ :returns bytes: A shared key.
.. method:: public_key()
@@ -320,25 +594,46 @@ Key Interfaces
The EllipticCurvePublicKey object for this private key.
+ .. method:: sign(data, signature_algorithm)
-.. class:: EllipticCurvePrivateKeyWithNumbers
+ .. versionadded:: 1.5
- .. versionadded:: 0.6
+ Sign one block of data which can be verified later by others using the
+ public key.
- Extends :class:`EllipticCurvePrivateKey`.
+ :param bytes data: The message string to sign.
- .. method:: private_numbers()
+ :param signature_algorithm: An instance of
+ :class:`EllipticCurveSignatureAlgorithm`, such as :class:`ECDSA`.
- Create a :class:`EllipticCurvePrivateNumbers` object.
+ :return bytes: The signature as a ``bytes`` object, whose contents are
+ DER encoded as described in :rfc:`3279`. This can be decoded using
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`,
+ which returns the decoded tuple ``(r, s)``.
- :returns: An :class:`EllipticCurvePrivateNumbers` instance.
+ .. attribute:: curve
+
+ :type: :class:`EllipticCurve`
+
+ The EllipticCurve that this key is on.
+
+ .. attribute:: key_size
+
+ .. versionadded:: 1.9
+
+ :type: int
+
+ Size (in :term:`bits`) of a secret scalar for the curve (as generated
+ by :func:`generate_private_key`).
.. class:: EllipticCurvePrivateKeyWithSerialization
.. versionadded:: 0.8
- Extends :class:`EllipticCurvePrivateKey`.
+ This interface contains additional methods relating to serialization.
+ Any object with this interface also has all the methods from
+ :class:`EllipticCurvePrivateKey`.
.. method:: private_numbers()
@@ -379,76 +674,300 @@ Key Interfaces
An elliptic curve public key.
- .. method:: verifier(signature, signature_algorithm)
+ .. attribute:: curve
- Verify data was signed by the private key associated with this public
- key.
+ :type: :class:`EllipticCurve`
- :param bytes signature: The signature to verify. DER encoded as
- specified in :rfc:`6979`.
+ The elliptic curve for this key.
- :param signature_algorithm: An instance of a
- :class:`EllipticCurveSignatureAlgorithm` provider.
+ .. method:: public_numbers()
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext`
+ Create a :class:`EllipticCurvePublicNumbers` object.
- .. attribute:: curve
+ :returns: An :class:`EllipticCurvePublicNumbers` instance.
- :type: :class:`EllipticCurve`
+ .. method:: public_bytes(encoding, format)
- The elliptic curve for this key.
+ Allows serialization of the key data to bytes. When encoding the public
+ key the encodings (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`)
+ are chosen to define the exact serialization. When encoding the point
+ the encoding
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.X962`
+ should be used with the formats (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.UncompressedPoint`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.CompressedPoint`
+ ).
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
-.. class:: EllipticCurvePublicKeyWithNumbers
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PublicFormat` enum.
- .. versionadded:: 0.6
+ :return bytes: Serialized data.
- Extends :class:`EllipticCurvePublicKey`.
+ .. method:: verify(signature, data, signature_algorithm)
- .. method:: public_numbers()
+ .. versionadded:: 1.5
- Create a :class:`EllipticCurvePublicNumbers` object.
+ Verify one block of data was signed by the private key associated
+ with this public key.
- :returns: An :class:`EllipticCurvePublicNumbers` instance.
+ :param bytes signature: The DER-encoded signature to verify.
+ A raw signature may be DER-encoded by splitting it into the ``r``
+ and ``s`` components and passing them into
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.encode_dss_signature`.
+
+ :param bytes data: The message string that was signed.
+
+ :param signature_algorithm: An instance of
+ :class:`EllipticCurveSignatureAlgorithm`.
+
+ :raises cryptography.exceptions.InvalidSignature: If the signature does
+ not validate.
+
+ .. attribute:: key_size
+
+ .. versionadded:: 1.9
+
+ :type: int
+
+ Size (in :term:`bits`) of a secret scalar for the curve (as generated
+ by :func:`generate_private_key`).
+
+ .. classmethod:: from_encoded_point(curve, data)
+
+ .. versionadded:: 2.5
+
+ Decodes a byte string as described in `SEC 1 v2.0`_ section 2.3.3 and
+ returns an :class:`EllipticCurvePublicKey`. This class method supports
+ compressed points.
+
+ :param curve: An
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`
+ instance.
+
+ :param bytes data: The serialized point byte string.
+
+ :returns: An :class:`EllipticCurvePublicKey` instance.
+
+ :raises ValueError: Raised when an invalid point is supplied.
+
+ :raises TypeError: Raised when curve is not an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve`.
.. class:: EllipticCurvePublicKeyWithSerialization
.. versionadded:: 0.6
- Extends :class:`EllipticCurvePublicKey`.
+ Alias for :class:`EllipticCurvePublicKey`.
- .. method:: public_numbers()
- Create a :class:`EllipticCurvePublicNumbers` object.
- :returns: An :class:`EllipticCurvePublicNumbers` instance.
+Serialization
+~~~~~~~~~~~~~
- .. method:: public_bytes(encoding, format)
+This sample demonstrates how to generate a private key and serialize it.
- 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.
- :param encoding: A value from the
- :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+.. doctest::
- :param format: A value from the
- :class:`~cryptography.hazmat.primitives.serialization.PublicFormat` enum.
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import ec
- :return bytes: Serialized key.
+ >>> private_key = ec.generate_private_key(ec.SECP384R1(), default_backend())
+
+ >>> serialized_private = private_key.private_bytes(
+ ... encoding=serialization.Encoding.PEM,
+ ... format=serialization.PrivateFormat.PKCS8,
+ ... encryption_algorithm=serialization.BestAvailableEncryption(b'testpassword')
+ ... )
+ >>> serialized_private.splitlines()[0]
+ b'-----BEGIN ENCRYPTED PRIVATE KEY-----'
+
+You can also serialize the key without a password, by relying on
+:class:`~cryptography.hazmat.primitives.serialization.NoEncryption`.
+
+The public key is serialized as follows:
+
+
+.. doctest::
+
+ >>> public_key = private_key.public_key()
+ >>> serialized_public = public_key.public_bytes(
+ ... encoding=serialization.Encoding.PEM,
+ ... format=serialization.PublicFormat.SubjectPublicKeyInfo
+ ... )
+ >>> serialized_public.splitlines()[0]
+ b'-----BEGIN PUBLIC KEY-----'
+
+This is the part that you would normally share with the rest of the world.
+
+
+Key loading
+~~~~~~~~~~~
+
+This extends the sample in the previous section, assuming that the variables
+``serialized_private`` and ``serialized_public`` contain the respective keys
+in PEM format.
+
+.. doctest::
+
+ >>> loaded_public_key = serialization.load_pem_public_key(
+ ... serialized_public,
+ ... backend=default_backend()
+ ... )
+
+ >>> loaded_private_key = serialization.load_pem_private_key(
+ ... serialized_private,
+ ... # or password=None, if in plain text
+ ... password=b'testpassword',
+ ... backend=default_backend()
+ ... )
+
+
+Elliptic Curve Object Identifiers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. class:: EllipticCurveOID
+
+ .. versionadded:: 2.4
+
+ .. attribute:: SECP192R1
+
+ Corresponds to the dotted string ``"1.2.840.10045.3.1.1"``.
+
+ .. attribute:: SECP224R1
+
+ Corresponds to the dotted string ``"1.3.132.0.33"``.
+
+ .. attribute:: SECP256K1
+
+ Corresponds to the dotted string ``"1.3.132.0.10"``.
+
+ .. attribute:: SECP256R1
+
+ Corresponds to the dotted string ``"1.2.840.10045.3.1.7"``.
+
+ .. attribute:: SECP384R1
+
+ Corresponds to the dotted string ``"1.3.132.0.34"``.
+
+ .. attribute:: SECP521R1
+
+ Corresponds to the dotted string ``"1.3.132.0.35"``.
+
+ .. attribute:: BRAINPOOLP256R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.36.3.3.2.8.1.1.7"``.
+
+ .. attribute:: BRAINPOOLP384R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.36.3.3.2.8.1.1.11"``.
+
+ .. attribute:: BRAINPOOLP512R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.36.3.3.2.8.1.1.13"``.
+
+ .. attribute:: SECT163K1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.1"``.
+
+ .. attribute:: SECT163R2
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.15"``.
+
+ .. attribute:: SECT233K1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.26"``.
+
+ .. attribute:: SECT233R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.27"``.
+
+ .. attribute:: SECT283K1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.16"``.
+
+ .. attribute:: SECT283R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.17"``.
+
+ .. attribute:: SECT409K1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.36"``.
+
+ .. attribute:: SECT409R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.37"``.
+
+ .. attribute:: SECT571K1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.38"``.
+
+ .. attribute:: SECT571R1
+
+ .. versionadded:: 2.5
+
+ Corresponds to the dotted string ``"1.3.132.0.39"``.
+
+.. function:: get_curve_for_oid(oid)
+
+ .. versionadded:: 2.6
+
+ A function that takes an :class:`~cryptography.x509.ObjectIdentifier`
+ and returns the associated elliptic curve class.
+
+ :param oid: An instance of
+ :class:`~cryptography.x509.ObjectIdentifier`.
+
+ :returns: The matching elliptic curve class. The returned class conforms
+ to the :class:`EllipticCurve` interface.
+ :raises LookupError: Raised if no elliptic curve is found that matches
+ the provided object identifier.
-.. _`FIPS 186-3`: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
-.. _`FIPS 186-4`: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
+.. _`FIPS 186-3`: https://csrc.nist.gov/csrc/media/publications/fips/186/3/archive/2009-06-25/documents/fips_186-3.pdf
+.. _`FIPS 186-4`: https://csrc.nist.gov/publications/detail/fips/186/4/final
+.. _`800-56A`: https://csrc.nist.gov/publications/detail/sp/800-56a/revised/archive/2007-03-14
+.. _`800-56Ar2`: https://csrc.nist.gov/publications/detail/sp/800-56a/rev-2/final
.. _`some concern`: https://crypto.stackexchange.com/questions/10263/should-we-trust-the-nist-recommended-ecc-parameters
-.. _`less than 224 bits`: http://www.ecrypt.eu.org/ecrypt2/documents/D.SPA.20.pdf
-.. _`64x lower computational cost than DH`: https://www.nsa.gov/business/programs/elliptic_curve.shtml
-.. _`minimize the number of security concerns for elliptic-curve cryptography`: http://cr.yp.to/ecdh/curve25519-20060209.pdf
-.. _`SafeCurves`: http://safecurves.cr.yp.to/
+.. _`less than 224 bits`: https://www.cosic.esat.kuleuven.be/ecrypt/ecrypt2/documents/D.SPA.20.pdf
+.. _`elliptic curve diffie-hellman is faster than diffie-hellman`: https://digitalcommons.unl.edu/cgi/viewcontent.cgi?article=1100&context=cseconfwork
+.. _`minimize the number of security concerns for elliptic-curve cryptography`: https://cr.yp.to/ecdh/curve25519-20060209.pdf
+.. _`SafeCurves`: https://safecurves.cr.yp.to/
.. _`ECDSA`: https://en.wikipedia.org/wiki/ECDSA
.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
+.. _`forward secrecy`: https://en.wikipedia.org/wiki/Forward_secrecy
+.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf
diff --git a/docs/hazmat/primitives/asymmetric/ed25519.rst b/docs/hazmat/primitives/asymmetric/ed25519.rst
new file mode 100644
index 00000000..f9e007c5
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/ed25519.rst
@@ -0,0 +1,166 @@
+.. hazmat::
+
+Ed25519 signing
+===============
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.ed25519
+
+
+Ed25519 is an elliptic curve signing algorithm using `EdDSA`_ and
+`Curve25519`_. If you do not have legacy interoperability concerns then you
+should strongly consider using this signature algorithm.
+
+
+Signing & Verification
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
+ >>> private_key = Ed25519PrivateKey.generate()
+ >>> signature = private_key.sign(b"my authenticated message")
+ >>> public_key = private_key.public_key()
+ >>> # Raises InvalidSignature if verification fails
+ >>> public_key.verify(signature, b"my authenticated message")
+
+Key interfaces
+~~~~~~~~~~~~~~
+
+.. class:: Ed25519PrivateKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: generate()
+
+ Generate an Ed25519 private key.
+
+ :returns: :class:`Ed25519PrivateKey`
+
+ .. classmethod:: from_private_bytes(data)
+
+ :param data: 32 byte private key.
+ :type data: :term:`bytes-like`
+
+ :returns: :class:`Ed25519PrivateKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import ed25519
+ >>> private_key = ed25519.Ed25519PrivateKey.generate()
+ >>> private_bytes = private_key.private_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PrivateFormat.Raw,
+ ... encryption_algorithm=serialization.NoEncryption()
+ ... )
+ >>> loaded_private_key = ed25519.Ed25519PrivateKey.from_private_bytes(private_bytes)
+
+
+ .. method:: public_key()
+
+ :returns: :class:`Ed25519PublicKey`
+
+ .. method:: sign(data)
+
+ :param bytes data: The data to sign.
+
+ :returns bytes: The 64 byte signature.
+
+ .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+ 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:: Ed25519PublicKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: from_public_bytes(data)
+
+ :param bytes data: 32 byte public key.
+
+ :returns: :class:`Ed25519PublicKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import ed25519
+ >>> private_key = ed25519.Ed25519PrivateKey.generate()
+ >>> public_key = private_key.public_key()
+ >>> public_bytes = public_key.public_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PublicFormat.Raw
+ ... )
+ >>> loaded_public_key = ed25519.Ed25519PublicKey.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`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.OpenSSH`,
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`,
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.OpenSSH`
+ , 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`.
+ If ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.OpenSSH`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.OpenSSH`.
+ In all other cases ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`.
+
+ :returns bytes: The public key bytes.
+
+ .. method:: verify(signature, data)
+
+ :param bytes signature: The signature to verify.
+
+ :param bytes data: The data to verify.
+
+ :raises cryptography.exceptions.InvalidSignature: Raised when the
+ signature cannot be verified.
+
+
+
+.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
+.. _`Curve25519`: https://en.wikipedia.org/wiki/Curve25519
diff --git a/docs/hazmat/primitives/asymmetric/ed448.rst b/docs/hazmat/primitives/asymmetric/ed448.rst
new file mode 100644
index 00000000..fb79dcb6
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/ed448.rst
@@ -0,0 +1,131 @@
+.. hazmat::
+
+Ed448 signing
+=============
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.ed448
+
+
+Ed448 is an elliptic curve signing algorithm using `EdDSA`_.
+
+
+Signing & Verification
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PrivateKey
+ >>> private_key = Ed448PrivateKey.generate()
+ >>> signature = private_key.sign(b"my authenticated message")
+ >>> public_key = private_key.public_key()
+ >>> # Raises InvalidSignature if verification fails
+ >>> public_key.verify(signature, b"my authenticated message")
+
+Key interfaces
+~~~~~~~~~~~~~~
+
+.. class:: Ed448PrivateKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: generate()
+
+ Generate an Ed448 private key.
+
+ :returns: :class:`Ed448PrivateKey`
+
+ .. classmethod:: from_private_bytes(data)
+
+ :param data: 57 byte private key.
+ :type data: :term:`bytes-like`
+
+ :returns: :class:`Ed448PrivateKey`
+
+ .. method:: public_key()
+
+ :returns: :class:`Ed448PublicKey`
+
+ .. method:: sign(data)
+
+ :param bytes data: The data to sign.
+
+ :returns bytes: The 114 byte signature.
+
+ .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+ 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:: Ed448PublicKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: from_public_bytes(data)
+
+ :param bytes data: 57 byte public key.
+
+ :returns: :class:`Ed448PublicKey`
+
+ .. 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.
+
+ .. method:: verify(signature, data)
+
+ :param bytes signature: The signature to verify.
+
+ :param bytes data: The data to verify.
+
+ :raises cryptography.exceptions.InvalidSignature: Raised when the
+ signature cannot be verified.
+
+
+
+.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
diff --git a/docs/hazmat/primitives/asymmetric/index.rst b/docs/hazmat/primitives/asymmetric/index.rst
index 4242a0bd..c27e1781 100644
--- a/docs/hazmat/primitives/asymmetric/index.rst
+++ b/docs/hazmat/primitives/asymmetric/index.rst
@@ -20,18 +20,18 @@ symmetric encryption. Someone with the public key is able to encrypt a message,
providing confidentiality, and then only the person in possession of the
private key is able to decrypt it.
-Cryptography supports three different sets of asymmetric algorithms: RSA, DSA,
-and Elliptic Curve.
-
.. toctree::
:maxdepth: 1
- dsa
+ ed25519
+ x25519
+ ed448
+ x448
ec
rsa
dh
+ dsa
serialization
- interfaces
utils
diff --git a/docs/hazmat/primitives/asymmetric/interfaces.rst b/docs/hazmat/primitives/asymmetric/interfaces.rst
deleted file mode 100644
index c4f176c6..00000000
--- a/docs/hazmat/primitives/asymmetric/interfaces.rst
+++ /dev/null
@@ -1,32 +0,0 @@
-.. hazmat::
-
-.. module:: cryptography.hazmat.primitives.asymmetric
-
-Signature Interfaces
-====================
-
-.. class:: AsymmetricSignatureContext
-
- .. versionadded:: 0.2
-
- .. method:: update(data)
-
- :param bytes data: The data you want to sign.
-
- .. method:: finalize()
-
- :return bytes signature: The signature.
-
-
-.. class:: AsymmetricVerificationContext
-
- .. versionadded:: 0.2
-
- .. method:: update(data)
-
- :param bytes data: The data you wish to verify using the signature.
-
- .. method:: verify()
-
- :raises cryptography.exceptions.InvalidSignature: If the signature does
- not validate.
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index 3b5b677b..dab90964 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -19,11 +19,12 @@ mathematical properties`_.
.. versionadded:: 0.5
Generates a new RSA private key using the provided ``backend``.
- ``key_size`` describes how many bits long the key should be, larger keys
- provide more security, currently ``1024`` and below are considered
- breakable, and ``2048`` or ``4096`` are reasonable default key sizes for
+ ``key_size`` describes how many :term:`bits` long the key should be. Larger
+ keys provide more security; currently ``1024`` and below are considered
+ breakable while ``2048`` or ``4096`` are reasonable default key sizes for
new keys. The ``public_exponent`` indicates what one mathematical property
- of the key generation will be, ``65537`` should almost always be used.
+ of the key generation will be. Unless you have a specific reason to do
+ otherwise, you should always `use 65537`_.
.. doctest::
@@ -39,12 +40,12 @@ mathematical properties`_.
Usually one of the small Fermat primes 3, 5, 17, 257, 65537. If in
doubt you should `use 65537`_.
- :param int key_size: The length of the modulus in bits. For keys
+ :param int key_size: The length of the modulus in :term:`bits`. For keys
generated in 2015 it is strongly recommended to be
`at least 2048`_ (See page 41). It must not be less than 512.
Some backends may have additional limitations.
- :param backend: A backend which provides
+ :param backend: A backend which implements
:class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
:return: An instance of
@@ -63,6 +64,7 @@ markers), you can load it:
.. code-block:: pycon
+ >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import serialization
>>> with open("path/to/key.pem", "rb") as key_file:
@@ -98,7 +100,7 @@ to serialize the key.
... encryption_algorithm=serialization.BestAvailableEncryption(b'mypassword')
... )
>>> pem.splitlines()[0]
- '-----BEGIN ENCRYPTED PRIVATE KEY-----'
+ b'-----BEGIN ENCRYPTED PRIVATE KEY-----'
It is also possible to serialize without encryption using
:class:`~cryptography.hazmat.primitives.serialization.NoEncryption`.
@@ -111,12 +113,10 @@ It is also possible to serialize without encryption using
... encryption_algorithm=serialization.NoEncryption()
... )
>>> pem.splitlines()[0]
- '-----BEGIN RSA PRIVATE KEY-----'
+ b'-----BEGIN RSA PRIVATE KEY-----'
-Similarly, if your public key implements
-:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization`
-interface you can use
-:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization.public_bytes`
+For public keys you can use
+:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey.public_bytes`
to serialize the key.
.. doctest::
@@ -128,7 +128,7 @@ to serialize the key.
... format=serialization.PublicFormat.SubjectPublicKeyInfo
... )
>>> pem.splitlines()[0]
- '-----BEGIN PUBLIC KEY-----'
+ b'-----BEGIN PUBLIC KEY-----'
Signing
~~~~~~~
@@ -143,17 +143,15 @@ secure hash function and padding:
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import padding
-
- >>> signer = private_key.signer(
+ >>> message = b"A message I want to sign"
+ >>> signature = private_key.sign(
+ ... message,
... padding.PSS(
... mgf=padding.MGF1(hashes.SHA256()),
... salt_length=padding.PSS.MAX_LENGTH
... ),
... hashes.SHA256()
... )
- >>> message = b"A message I want to sign"
- >>> signer.update(message)
- >>> signature = signer.finalize()
Valid paddings for signatures are
:class:`~cryptography.hazmat.primitives.asymmetric.padding.PSS` and
@@ -161,31 +159,78 @@ Valid paddings for signatures are
is the recommended choice for any new protocols or applications, ``PKCS1v15``
should only be used to support legacy protocols.
+If your data is too large to be passed in a single call, you can hash it
+separately and pass that value using
+:class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+.. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric import utils
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> sig = private_key.sign(
+ ... digest,
+ ... padding.PSS(
+ ... mgf=padding.MGF1(hashes.SHA256()),
+ ... salt_length=padding.PSS.MAX_LENGTH
+ ... ),
+ ... utils.Prehashed(chosen_hash)
+ ... )
+
Verification
~~~~~~~~~~~~
The previous section describes what to do if you have a private key and want to
-sign something. If you have a public key, a message, and a signature, you can
-check that the public key genuinely was used to sign that specific message. You
-also need to know which signing algorithm was used:
+sign something. If you have a public key, a message, a signature, and the
+signing algorithm that was used you can check that the private key associated
+with a given public key was used to sign that specific message. You can obtain
+a public key to use in verification using
+:func:`~cryptography.hazmat.primitives.serialization.load_pem_public_key`,
+:func:`~cryptography.hazmat.primitives.serialization.load_der_public_key`,
+:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers.public_key`
+, or
+:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey.public_key`.
.. doctest::
>>> public_key = private_key.public_key()
- >>> verifier = public_key.verifier(
+ >>> public_key.verify(
... signature,
+ ... message,
... padding.PSS(
... mgf=padding.MGF1(hashes.SHA256()),
... salt_length=padding.PSS.MAX_LENGTH
... ),
... hashes.SHA256()
... )
- >>> verifier.update(message)
- >>> verifier.verify()
If the signature does not match, ``verify()`` will raise an
:class:`~cryptography.exceptions.InvalidSignature` exception.
+If your data is too large to be passed in a single call, you can hash it
+separately and pass that value using
+:class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`.
+
+.. doctest::
+
+ >>> chosen_hash = hashes.SHA256()
+ >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher.update(b"data & ")
+ >>> hasher.update(b"more data")
+ >>> digest = hasher.finalize()
+ >>> public_key.verify(
+ ... sig,
+ ... digest,
+ ... padding.PSS(
+ ... mgf=padding.MGF1(hashes.SHA256()),
+ ... salt_length=padding.PSS.MAX_LENGTH
+ ... ),
+ ... utils.Prehashed(chosen_hash)
+ ... )
+
Encryption
~~~~~~~~~~
@@ -202,8 +247,8 @@ options. Here's an example using a secure padding and hash function:
>>> ciphertext = public_key.encrypt(
... message,
... padding.OAEP(
- ... mgf=padding.MGF1(algorithm=hashes.SHA1()),
- ... algorithm=hashes.SHA1(),
+ ... mgf=padding.MGF1(algorithm=hashes.SHA256()),
+ ... algorithm=hashes.SHA256(),
... label=None
... )
... )
@@ -225,8 +270,8 @@ Once you have an encrypted message, it can be decrypted using the private key:
>>> plaintext = private_key.decrypt(
... ciphertext,
... padding.OAEP(
- ... mgf=padding.MGF1(algorithm=hashes.SHA1()),
- ... algorithm=hashes.SHA1(),
+ ... mgf=padding.MGF1(algorithm=hashes.SHA256()),
+ ... algorithm=hashes.SHA256(),
... label=None
... )
... )
@@ -267,7 +312,7 @@ Padding
Pass this attribute to ``salt_length`` to get the maximum salt length
available.
-.. class:: OAEP(mgf, label)
+.. class:: OAEP(mgf, algorithm, label)
.. versionadded:: 0.4
@@ -279,6 +324,9 @@ Padding
:param mgf: A mask generation function object. At this time the only
supported MGF is :class:`MGF1`.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
:param bytes label: A label to apply. This is a rarely used field and
should typically be set to ``None`` or ``b""``, which are equivalent.
@@ -294,6 +342,20 @@ Padding
:class:`OAEP` should be preferred for encryption and :class:`PSS` should be
preferred for signatures.
+
+.. function:: calculate_max_pss_salt_length(key, hash_algorithm)
+
+ .. versionadded:: 1.5
+
+ :param key: An RSA public or private key.
+ :param hash_algorithm: A
+ :class:`cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+ :returns int: The computed salt length.
+
+ Computes the length of the salt that :class:`PSS` will use if
+ :data:`PSS.MAX_LENGTH` is used.
+
+
Mask generation functions
-------------------------
@@ -305,11 +367,10 @@ Mask generation functions
Removed the deprecated ``salt_length`` parameter.
MGF1 (Mask Generation Function 1) is used as the mask generation function
- in :class:`PSS` padding. It takes a hash algorithm and a salt length.
+ in :class:`PSS` and :class:`OAEP` padding. It takes a hash algorithm.
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
Numbers
~~~~~~~
@@ -340,13 +401,11 @@ is unavailable.
.. method:: public_key(backend)
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
- :returns: A new instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`
- provider.
+ :returns: A new instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`.
.. class:: RSAPrivateNumbers(p, q, d, dmp1, dmq1, iqmp, public_numbers)
@@ -409,13 +468,11 @@ is unavailable.
.. method:: private_key(backend)
- :param backend: A new instance of a
- :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
- provider.
+ :param backend: A new instance of
+ :class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
- :returns: A
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`
- provider.
+ :returns: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`.
Handling partial RSA private keys
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -423,7 +480,7 @@ Handling partial RSA private keys
If you are trying to load RSA private keys yourself you may find that not all
parameters required by ``RSAPrivateNumbers`` are available. In particular the
`Chinese Remainder Theorem`_ (CRT) values ``dmp1``, ``dmq1``, ``iqmp`` may be
-missing or present in a different form. For example `OpenPGP`_ does not include
+missing or present in a different form. For example, `OpenPGP`_ does not include
the ``iqmp``, ``dmp1`` or ``dmq1`` parameters.
The following functions are provided for users who want to work with keys like
@@ -440,15 +497,15 @@ this without having to do the math themselves.
.. versionadded:: 0.4
- Computes the ``dmp1`` parameter from the RSA private exponent and prime
- ``p``.
+ Computes the ``dmp1`` parameter from the RSA private exponent (``d``) and
+ prime ``p``.
.. function:: rsa_crt_dmq1(private_exponent, q)
.. versionadded:: 0.4
- Computes the ``dmq1`` parameter from the RSA private exponent and prime
- ``q``.
+ Computes the ``dmq1`` parameter from the RSA private exponent (``d``) and
+ prime ``q``.
.. function:: rsa_recover_prime_factors(n, e, d)
@@ -460,7 +517,9 @@ this without having to do the math themselves.
.. note::
When recovering prime factors this algorithm will always return ``p``
- and ``q`` such that ``p < q``.
+ and ``q`` such that ``p > q``. Note: before 1.5, this function always
+ returned ``p`` and ``q`` such that ``p < q``. It was changed because
+ libraries commonly require ``p > q``.
:return: A tuple ``(p, q)``
@@ -472,24 +531,9 @@ Key interfaces
.. versionadded:: 0.2
- An `RSA`_ private key.
-
- .. method:: signer(padding, algorithm)
-
- .. versionadded:: 0.3
-
- Sign data which can be verified later by others using the public key.
-
- :param padding: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
- provider.
-
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
-
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext`
+ An `RSA`_ private key. An RSA private key that is not an
+ :term:`opaque key` also implements :class:`RSAPrivateKeyWithSerialization`
+ to provide serialization methods.
.. method:: decrypt(ciphertext, padding)
@@ -499,9 +543,8 @@ Key interfaces
:param bytes ciphertext: The ciphertext to decrypt.
- :param padding: An instance of an
- :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
- provider.
+ :param padding: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`.
:return bytes: Decrypted data.
@@ -517,29 +560,36 @@ Key interfaces
The bit length of the modulus.
+ .. method:: sign(data, padding, algorithm)
-.. class:: RSAPrivateKeyWithNumbers
+ .. versionadded:: 1.4
+ .. versionchanged:: 1.6
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ can now be used as an ``algorithm``.
- .. versionadded:: 0.5
+ Sign one block of data which can be verified later by others using the
+ public key.
- Extends :class:`RSAPrivateKey`.
+ :param bytes data: The message string to sign.
- .. method:: private_numbers()
+ :param padding: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`.
- Create a
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers`
- object.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ if the ``data`` you want to sign has already been hashed.
- :returns: An
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers`
- instance.
+ :return bytes: Signature.
.. class:: RSAPrivateKeyWithSerialization
.. versionadded:: 0.8
- Extends :class:`RSAPrivateKey`.
+ This interface contains additional methods relating to serialization.
+ Any object with this interface also has all the methods from
+ :class:`RSAPrivateKey`.
.. method:: private_numbers()
@@ -585,26 +635,6 @@ Key interfaces
An `RSA`_ public key.
- .. method:: verifier(signature, padding, algorithm)
-
- .. versionadded:: 0.3
-
- Verify data was signed by the private key associated with this public
- key.
-
- :param bytes signature: The signature to verify.
-
- :param padding: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
- provider.
-
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
- provider.
-
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext`
-
.. method:: encrypt(plaintext, padding)
.. versionadded:: 0.4
@@ -613,9 +643,8 @@ Key interfaces
:param bytes plaintext: The plaintext to encrypt.
- :param padding: An instance of a
- :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`
- provider.
+ :param padding: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`.
:return bytes: Encrypted data.
@@ -625,30 +654,6 @@ Key interfaces
The bit length of the modulus.
-
-.. class:: RSAPublicKeyWithNumbers
-
- .. versionadded:: 0.5
-
- Extends :class:`RSAPublicKey`.
-
- .. method:: public_numbers()
-
- Create a
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers`
- object.
-
- :returns: An
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers`
- instance.
-
-
-.. class:: RSAPublicKeyWithSerialization
-
- .. versionadded:: 0.8
-
- Extends :class:`RSAPublicKey`.
-
.. method:: public_numbers()
Create a
@@ -678,14 +683,46 @@ Key interfaces
:return bytes: Serialized key.
+ .. method:: verify(signature, data, padding, algorithm)
+
+ .. versionadded:: 1.4
+ .. versionchanged:: 1.6
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ can now be used as an ``algorithm``.
+
+ Verify one block of data was signed by the private key
+ associated with this public key.
+
+ :param bytes signature: The signature to verify.
+
+ :param bytes data: The message string that was signed.
+
+ :param padding: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`.
+
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+ if the ``data`` you want to verify has already been hashed.
+
+ :raises cryptography.exceptions.InvalidSignature: If the signature does
+ not validate.
+
+
+.. class:: RSAPublicKeyWithSerialization
+
+ .. versionadded:: 0.8
+
+ Alias for :class:`RSAPublicKey`.
+
.. _`RSA`: https://en.wikipedia.org/wiki/RSA_(cryptosystem)
.. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography
.. _`specific mathematical properties`: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Key_generation
-.. _`use 65537`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
-.. _`at least 2048`: http://www.ecrypt.eu.org/ecrypt2/documents/D.SPA.20.pdf
+.. _`use 65537`: https://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
+.. _`at least 2048`: https://www.cosic.esat.kuleuven.be/ecrypt/ecrypt2/documents/D.SPA.20.pdf
.. _`OpenPGP`: https://en.wikipedia.org/wiki/Pretty_Good_Privacy
.. _`Chinese Remainder Theorem`: https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29#Using_the_Chinese_remainder_algorithm
-.. _`security proof`: http://eprint.iacr.org/2001/062.pdf
-.. _`recommended padding algorithm`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
-.. _`proven secure`: http://cseweb.ucsd.edu/~mihir/papers/oae.pdf
+.. _`security proof`: https://eprint.iacr.org/2001/062.pdf
+.. _`recommended padding algorithm`: https://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
+.. _`proven secure`: https://cseweb.ucsd.edu/~mihir/papers/oae.pdf
diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst
index 7839f346..7c1fc82e 100644
--- a/docs/hazmat/primitives/asymmetric/serialization.rst
+++ b/docs/hazmat/primitives/asymmetric/serialization.rst
@@ -63,6 +63,20 @@ Key Serialization
def sign_with_dsa_key(key, message):
return b""
+ parameters_pem_data = b"""
+ -----BEGIN DH PARAMETERS-----
+ MIGHAoGBALsrWt44U1ojqTy88o0wfjysBE51V6Vtarjm2+5BslQK/RtlndHde3gx
+ +ccNs+InANszcuJFI8AHt4743kGRzy5XSlul4q4dDJENOHoyqYxueFuFVJELEwLQ
+ XrX/McKw+hS6GPVQnw6tZhgGo9apdNdYgeLQeQded8Bum8jqzP3rAgEC
+ -----END DH PARAMETERS-----
+ """.strip()
+
+ parameters_der_data = base64.b64decode(
+ b"MIGHAoGBALsrWt44U1ojqTy88o0wfjysBE51V6Vtarjm2+5BslQK/RtlndHde3gx+ccNs+In"
+ b"ANsz\ncuJFI8AHt4743kGRzy5XSlul4q4dDJENOHoyqYxueFuFVJELEwLQXrX/McKw+hS6GP"
+ b"VQnw6tZhgG\no9apdNdYgeLQeQded8Bum8jqzP3rAgEC"
+ )
+
There are several common schemes for serializing asymmetric private and public
keys to bytes. They generally support encryption of private keys and additional
key metadata.
@@ -85,6 +99,16 @@ methods.
... else:
... raise TypeError
+Key dumping
+~~~~~~~~~~~
+
+The ``serialization`` module contains functions for loading keys from
+``bytes``. To dump a ``key`` object to ``bytes``, you must call the appropriate
+method on the key object. Documentation for these methods in found in the
+:mod:`~cryptography.hazmat.primitives.asymmetric.rsa`,
+:mod:`~cryptography.hazmat.primitives.asymmetric.dsa`, and
+:mod:`~cryptography.hazmat.primitives.asymmetric.ec` module documentation.
+
PEM
~~~
@@ -97,8 +121,8 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
.. note::
A PEM block which starts with ``-----BEGIN CERTIFICATE-----`` is not a
- public or private key, it's an :doc:`X.509 Certificate </x509>`. You can
- load it using :func:`~cryptography.x509.load_pem_x509_certificate` and
+ public or private key, it's an :doc:`X.509 Certificate </x509/index>`. You
+ can load it using :func:`~cryptography.x509.load_pem_x509_certificate` and
extract the public key with
:meth:`Certificate.public_key <cryptography.x509.Certificate.public_key>`.
@@ -109,16 +133,23 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
Deserialize a private key from PEM encoded data to one of the supported
asymmetric private key types.
- :param bytes data: The PEM encoded key data.
+ :param data: The PEM encoded key data.
+ :type data: :term:`bytes-like`
- :param bytes password: The password to use to decrypt the data. Should
+ :param password: The password to use to decrypt the data. Should
be ``None`` if the private key is not encrypted.
+ :type data: :term:`bytes-like`
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
- :returns: A new instance of a private key.
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`,
+ or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+ depending on the contents of ``data``.
:raises ValueError: If the PEM data could not be decrypted or if its
structure could not be decoded successfully.
@@ -136,7 +167,8 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
.. versionadded:: 0.6
Deserialize a public key from PEM encoded data to one of the supported
- asymmetric public key types.
+ asymmetric public key types. The PEM encoded data is typically a
+ ``subjectPublicKeyInfo`` payload as specified in :rfc:`5280`.
.. doctest::
@@ -147,11 +179,17 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
:param bytes data: The PEM encoded key data.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
- :returns: A new instance of a public key.
+
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`,
+ or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+ depending on the contents of ``data``.
:raises ValueError: If the PEM data's structure could not be decoded
successfully.
@@ -159,6 +197,37 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
:raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key
is of a type that is not supported by the backend.
+.. function:: load_pem_parameters(data, backend)
+
+ .. versionadded:: 2.0
+
+ Deserialize parameters from PEM encoded data to one of the supported
+ asymmetric parameters types.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives.serialization import load_pem_parameters
+ >>> from cryptography.hazmat.primitives.asymmetric import dh
+ >>> parameters = load_pem_parameters(parameters_pem_data, backend=default_backend())
+ >>> isinstance(parameters, dh.DHParameters)
+ True
+
+ :param bytes data: The PEM encoded parameters data.
+
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
+
+
+ :returns: Currently only
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`
+ supported.
+
+ :raises ValueError: If the PEM data's structure could not be decoded
+ successfully.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized parameters
+ is of a type that is not supported by the backend.
+
DER
~~~
@@ -174,16 +243,23 @@ the rest.
Deserialize a private key from DER encoded data to one of the supported
asymmetric private key types.
- :param bytes data: The DER encoded key data.
+ :param data: The DER encoded key data.
+ :type data: :term:`bytes-like`
- :param bytes password: The password to use to decrypt the data. Should
+ :param password: The password to use to decrypt the data. Should
be ``None`` if the private key is not encrypted.
+ :type password: :term:`bytes-like`
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
- :returns: A new instance of a private key.
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKey`,
+ or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+ depending on the contents of ``data``.
:raises ValueError: If the DER data could not be decrypted or if its
structure could not be decoded successfully.
@@ -210,15 +286,21 @@ the rest.
.. versionadded:: 0.8
Deserialize a public key from DER encoded data to one of the supported
- asymmetric public key types.
+ asymmetric public key types. The DER encoded data is typically a
+ ``subjectPublicKeyInfo`` payload as specified in :rfc:`5280`.
:param bytes data: The DER encoded key data.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`
- provider.
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
- :returns: A new instance of a public key.
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`,
+ or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+ depending on the contents of ``data``.
:raises ValueError: If the DER data's structure could not be decoded
successfully.
@@ -235,6 +317,37 @@ the rest.
>>> isinstance(key, rsa.RSAPublicKey)
True
+.. function:: load_der_parameters(data, backend)
+
+ .. versionadded:: 2.0
+
+ Deserialize parameters from DER encoded data to one of the supported
+ asymmetric parameters types.
+
+ :param bytes data: The DER encoded parameters data.
+
+ :param backend: An instance of
+ :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
+
+ :returns: Currently only
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParameters`
+ supported.
+
+ :raises ValueError: If the DER data's structure could not be decoded
+ successfully.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key is of a type that
+ is not supported by the backend.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives.asymmetric import dh
+ >>> from cryptography.hazmat.primitives.serialization import load_der_parameters
+ >>> parameters = load_der_parameters(parameters_der_data, backend=default_backend())
+ >>> isinstance(parameters, dh.DHParameters)
+ True
+
OpenSSH Public Key
~~~~~~~~~~~~~~~~~~
@@ -263,19 +376,21 @@ DSA keys look almost identical but begin with ``ssh-dss`` rather than
Deserialize a public key from OpenSSH (:rfc:`4253`) encoded data to an
instance of the public key type for the specified backend.
- .. note::
-
- Currently Ed25519 keys are not supported.
-
:param bytes data: The OpenSSH encoded key data.
- :param backend: A backend providing
+ :param backend: A backend which implements
:class:`~cryptography.hazmat.backends.interfaces.RSABackend`,
:class:`~cryptography.hazmat.backends.interfaces.DSABackend`, or
:class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
depending on the key's type.
- :returns: A new instance of a public key type.
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+ , or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey`,
+ depending on the contents of ``data``.
:raises ValueError: If the OpenSSH data could not be properly decoded or
if the key is not in the proper format.
@@ -283,9 +398,48 @@ DSA keys look almost identical but begin with ``ssh-dss`` rather than
:raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized
key is of a type that is not supported.
+PKCS12
+~~~~~~
+
+.. currentmodule:: cryptography.hazmat.primitives.serialization.pkcs12
+
+PKCS12 is a binary format described in :rfc:`7292`. It can contain
+certificates, keys, and more. PKCS12 files commonly have a ``pfx`` or ``p12``
+file suffix.
+
+.. note::
+
+ ``cryptography`` only supports a single private key and associated
+ certificates when parsing PKCS12 files at this time.
+
+.. function:: load_key_and_certificates(data, password, backend)
+
+ .. versionadded:: 2.5
+
+ Deserialize a PKCS12 blob.
+
+ :param data: The binary data.
+ :type data: :term:`bytes-like`
+
+ :param password: The password to use to decrypt the data. ``None``
+ if the PKCS12 is not encrypted.
+ :type password: :term:`bytes-like`
+
+ :param backend: A backend instance.
+
+ :returns: A tuple of
+ ``(private_key, certificate, additional_certificates)``.
+ ``private_key`` is a private key type or ``None``, ``certificate``
+ is either the :class:`~cryptography.x509.Certificate` whose public key
+ matches the private key in the PKCS 12 object or ``None``, and
+ ``additional_certificates`` is a list of all other
+ :class:`~cryptography.x509.Certificate` instances in the PKCS12 object.
+
Serialization Formats
~~~~~~~~~~~~~~~~~~~~~
+.. currentmodule:: cryptography.hazmat.primitives.serialization
+
.. class:: PrivateFormat
.. versionadded:: 0.8
@@ -295,6 +449,7 @@ Serialization Formats
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization`
,
:class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization`
+ , :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKeyWithSerialization`
and
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`.
@@ -303,12 +458,31 @@ Serialization Formats
Frequently known as PKCS#1 format. Still a widely used format, but
generally considered legacy.
+ A PEM encoded RSA key will look like::
+
+ -----BEGIN RSA PRIVATE KEY-----
+ ...
+ -----END RSA PRIVATE KEY-----
+
.. attribute:: PKCS8
A more modern format for serializing keys which allows for better
encryption. Choose this unless you have explicit legacy compatibility
requirements.
+ A PEM encoded key will look like::
+
+ -----BEGIN PRIVATE KEY-----
+ ...
+ -----END PRIVATE KEY-----
+
+ .. attribute:: Raw
+
+ .. versionadded:: 2.5
+
+ A raw format used by :doc:`/hazmat/primitives/asymmetric/x448`. It is a
+ binary format and is invalid for other key types.
+
.. class:: PublicFormat
.. versionadded:: 0.8
@@ -318,6 +492,7 @@ Serialization Formats
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization`
,
:class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKeyWithSerialization`
+ , :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKeyWithSerialization`
, and
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKeyWithSerialization`.
@@ -327,38 +502,116 @@ Serialization Formats
identifier and the public key as a bit string. Choose this unless
you have specific needs.
+ A PEM encoded key will look like::
+
+ -----BEGIN PUBLIC KEY-----
+ ...
+ -----END PUBLIC KEY-----
+
.. attribute:: PKCS1
Just the public key elements (without the algorithm identifier). This
format is RSA only, but is used by some older systems.
+ A PEM encoded key will look like::
+
+ -----BEGIN RSA PUBLIC KEY-----
+ ...
+ -----END RSA PUBLIC KEY-----
+
+ .. attribute:: OpenSSH
+
+ .. versionadded:: 1.4
+
+ The public key format used by OpenSSH (e.g. as found in
+ ``~/.ssh/id_rsa.pub`` or ``~/.ssh/authorized_keys``).
+
+ .. attribute:: Raw
+
+ .. versionadded:: 2.5
+
+ A raw format used by :doc:`/hazmat/primitives/asymmetric/x448`. It is a
+ binary format and is invalid for other key types.
+
+ .. attribute:: CompressedPoint
+
+ .. versionadded:: 2.5
+
+ A compressed elliptic curve public key as defined in ANSI X9.62 section
+ 4.3.6 (as well as `SEC 1 v2.0`_).
+
+ .. attribute:: UncompressedPoint
+
+ .. versionadded:: 2.5
+
+ An uncompressed elliptic curve public key as defined in ANSI X9.62
+ section 4.3.6 (as well as `SEC 1 v2.0`_).
+
+.. class:: ParameterFormat
+
+ .. versionadded:: 2.0
+
+ An enumeration for parameters formats. Used with the ``parameter_bytes``
+ method available on
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHParametersWithSerialization`.
+
+ .. attribute:: PKCS3
+
+ ASN1 DH parameters sequence as defined in `PKCS3`_.
+
Serialization Encodings
~~~~~~~~~~~~~~~~~~~~~~~
.. class:: Encoding
- .. versionadded:: 0.8
-
An enumeration for encoding types. Used with the ``private_bytes`` method
available on
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization`
,
:class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization`
+ , :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKeyWithSerialization`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`,
and
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`
+ :class:`~cryptography.hazmat.primitives.asymmetric.x448.X448PrivateKey`
as well as ``public_bytes`` on
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization`
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
and
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKeyWithSerialization`.
+ :class:`~cryptography.hazmat.primitives.asymmetric.x448.X448PublicKey`.
.. attribute:: PEM
+ .. versionadded:: 0.8
+
For PEM format. This is a base64 format with delimiters.
.. attribute:: DER
+ .. versionadded:: 0.9
+
For DER format. This is a binary format.
+ .. attribute:: OpenSSH
+
+ .. versionadded:: 1.4
+
+ The format used by OpenSSH public keys. This is a text format.
+
+ .. attribute:: Raw
+
+ .. versionadded:: 2.5
+
+ A raw format used by :doc:`/hazmat/primitives/asymmetric/x448`. It is a
+ binary format and is invalid for other key types.
+
+ .. attribute:: X962
+
+ .. versionadded:: 2.5
+
+ The format used by elliptic curve point encodings. This is a binary
+ format.
+
Serialization Encryption Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -370,6 +623,7 @@ Serialization Encryption Types
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization`
,
:class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization`
+ , :class:`~cryptography.hazmat.primitives.asymmetric.dh.DHPrivateKeyWithSerialization`
and
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`.
All other classes in this section represent the available choices for
@@ -387,3 +641,7 @@ Serialization Encryption Types
.. class:: NoEncryption
Do not encrypt.
+
+
+.. _`PKCS3`: https://www.teletrust.de/fileadmin/files/oid/oid_pkcs-3v1-4.pdf
+.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf
diff --git a/docs/hazmat/primitives/asymmetric/utils.rst b/docs/hazmat/primitives/asymmetric/utils.rst
index 7380f0b5..f46acb2e 100644
--- a/docs/hazmat/primitives/asymmetric/utils.rst
+++ b/docs/hazmat/primitives/asymmetric/utils.rst
@@ -6,10 +6,11 @@ Asymmetric Utilities
.. currentmodule:: cryptography.hazmat.primitives.asymmetric.utils
-.. function:: decode_rfc6979_signature(signature)
+.. function:: decode_dss_signature(signature)
- Takes in :rfc:`6979` signatures generated by the DSA/ECDSA signers and
- returns a tuple ``(r, s)``.
+ Takes in signatures generated by the DSA/ECDSA signers and returns a
+ tuple ``(r, s)``. These signatures are ASN.1 encoded ``Dss-Sig-Value``
+ sequences (as defined in :rfc:`3279`)
:param bytes signature: The signature to decode.
@@ -17,12 +18,71 @@ Asymmetric Utilities
:raises ValueError: Raised if the signature is malformed.
-.. function:: encode_rfc6979_signature(r, s)
+.. function:: encode_dss_signature(r, s)
- Creates an :rfc:`6979` byte string from raw signature values.
+ Creates an ASN.1 encoded ``Dss-Sig-Value`` (as defined in :rfc:`3279`) from
+ raw ``r`` and ``s`` values.
:param int r: The raw signature value ``r``.
:param int s: The raw signature value ``s``.
:return bytes: The encoded signature.
+
+.. class:: Prehashed(algorithm)
+
+ .. versionadded:: 1.6
+
+ ``Prehashed`` can be passed as the ``algorithm`` in the RSA
+ :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey.sign`
+ and
+ :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey.verify`
+ as well as DSA
+ :meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey.sign`
+ and
+ :meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey.verify`
+ methods.
+
+ For elliptic curves it can be passed as the ``algorithm`` in
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.ECDSA` and then used
+ with
+ :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey.sign`
+ and
+ :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.verify`
+ .
+
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
+ .. doctest::
+
+ >>> import hashlib
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import (
+ ... padding, rsa, utils
+ ... )
+ >>> private_key = rsa.generate_private_key(
+ ... public_exponent=65537,
+ ... key_size=2048,
+ ... backend=default_backend()
+ ... )
+ >>> prehashed_msg = hashlib.sha256(b"A message I want to sign").digest()
+ >>> signature = private_key.sign(
+ ... prehashed_msg,
+ ... padding.PSS(
+ ... mgf=padding.MGF1(hashes.SHA256()),
+ ... salt_length=padding.PSS.MAX_LENGTH
+ ... ),
+ ... utils.Prehashed(hashes.SHA256())
+ ... )
+ >>> public_key = private_key.public_key()
+ >>> public_key.verify(
+ ... signature,
+ ... prehashed_msg,
+ ... padding.PSS(
+ ... mgf=padding.MGF1(hashes.SHA256()),
+ ... salt_length=padding.PSS.MAX_LENGTH
+ ... ),
+ ... utils.Prehashed(hashes.SHA256())
+ ... )
diff --git a/docs/hazmat/primitives/asymmetric/x25519.rst b/docs/hazmat/primitives/asymmetric/x25519.rst
new file mode 100644
index 00000000..ea01fbaa
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/x25519.rst
@@ -0,0 +1,184 @@
+.. 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
diff --git a/docs/hazmat/primitives/asymmetric/x448.rst b/docs/hazmat/primitives/asymmetric/x448.rst
new file mode 100644
index 00000000..4e1f0421
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/x448.rst
@@ -0,0 +1,179 @@
+.. hazmat::
+
+X448 key exchange
+===================
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.x448
+
+
+X448 is an elliptic curve `Diffie-Hellman key exchange`_ using `Curve448`_.
+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.x448 import X448PrivateKey
+ >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+ >>> # Generate a private key for use in the exchange.
+ >>> private_key = X448PrivateKey.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 = X448PrivateKey.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 = X448PrivateKey.generate()
+ >>> peer_public_key_2 = X448PrivateKey.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:: X448PrivateKey
+
+ .. versionadded:: 2.5
+
+ .. classmethod:: generate()
+
+ Generate an X448 private key.
+
+ :returns: :class:`X448PrivateKey`
+
+ .. classmethod:: from_private_bytes(data)
+
+ :param data: 56 byte private key.
+ :type data: :term:`bytes-like`
+
+ :returns: :class:`X448PrivateKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import x448
+ >>> private_key = x448.X448PrivateKey.generate()
+ >>> private_bytes = private_key.private_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PrivateFormat.Raw,
+ ... encryption_algorithm=serialization.NoEncryption()
+ ... )
+ >>> loaded_private_key = x448.X448PrivateKey.from_private_bytes(private_bytes)
+
+ .. method:: public_key()
+
+ :returns: :class:`X448PublicKey`
+
+ .. method:: exchange(peer_public_key)
+
+ :param X448PublicKey peer_public_key: The public key for the
+ peer.
+
+ :returns bytes: A shared key.
+
+ .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+ 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:: X448PublicKey
+
+ .. versionadded:: 2.5
+
+ .. classmethod:: from_public_bytes(data)
+
+ :param bytes data: 56 byte public key.
+
+ :returns: :class:`X448PublicKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import x448
+ >>> private_key = x448.X448PrivateKey.generate()
+ >>> public_key = private_key.public_key()
+ >>> public_bytes = public_key.public_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PublicFormat.Raw
+ ... )
+ >>> loaded_public_key = x448.X448PublicKey.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
+.. _`Curve448`: https://en.wikipedia.org/wiki/Curve448