# HG changeset patch # User Paul Kehrer <paul.l.kehrer@gmail.com> # Date 1593998379 18000 # Sun Jul 05 20:19:39 2020 -0500 # Node ID 23d01ba79fc6415cc3deb10f496fff646c16486e # Parent 3a820004c384bd9b89cca4efb4d128e7b37368c9 support 4096 bit DSA parsing from numbers classes (#5301) * support 4096 bit DSA parsing from numbers classes * need to get local linting fixed. * reorder * add a link to more reasons why DSA sucks diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -78,6 +78,8 @@ * ``asymmetric/PEM_Serialization/rsa_public_key.pem`` and ``asymmetric/DER_Serialization/rsa_public_key.der``- Contains an RSA 2048 bit public generated using OpenSSL from ``rsa_private_key.pem``. +* ``asymmetric/PEM_Serialization/dsa_4096.pem`` - Contains a 4096-bit DSA + private key generated using OpenSSL. * ``asymmetric/PEM_Serialization/dsaparam.pem`` - Contains 2048-bit DSA parameters generated using OpenSSL; contains no keys. * ``asymmetric/PEM_Serialization/dsa_private_key.pem`` - Contains a DSA 2048 diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst --- a/docs/hazmat/primitives/asymmetric/dsa.rst +++ b/docs/hazmat/primitives/asymmetric/dsa.rst @@ -5,6 +5,13 @@ .. module:: cryptography.hazmat.primitives.asymmetric.dsa +.. note:: + + DSA is a **legacy algorithm** and should generally be avoided in favor of + choices like + :doc:`EdDSA using curve25519</hazmat/primitives/asymmetric/ed25519>` or + :doc:`ECDSA</hazmat/primitives/asymmetric/ec>`. + `DSA`_ is a `public-key`_ algorithm for signing messages. Generation @@ -14,15 +21,18 @@ .. versionadded:: 0.5 + .. versionchanged:: 3.0 + + Added support for 4096-bit keys for some legacy applications that + continue to use DSA despite the wider cryptographic community's + `ongoing protestations`_. + 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 :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. + be either 1024, 2048, 3072, or 4096. For keys generated in 2015 this + should be `at least 2048`_ (See page 41). :param backend: An instance of :class:`~cryptography.hazmat.backends.interfaces.DSABackend`. @@ -38,14 +48,17 @@ .. versionadded:: 0.5 + .. versionchanged:: 3.0 + + Added support for 4096-bit keys for some legacy applications that + continue to use DSA despite the wider cryptographic community's + `ongoing protestations`_. + Generate DSA parameters using the provided ``backend``. :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. + should be either 1024, 2048, 3072, or 4096. For keys generated in 2015 + this should be `at least 2048`_ (See page 41). :param backend: An instance of :class:`~cryptography.hazmat.backends.interfaces.DSABackend`. @@ -446,3 +459,4 @@ .. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography .. _`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 +.. _`ongoing protestations`: https://buttondown.email/cryptography-dispatches/archive/cryptography-dispatches-dsa-is-past-its-prime/ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -626,8 +626,10 @@ return False def generate_dsa_parameters(self, key_size): - if key_size not in (1024, 2048, 3072): - raise ValueError("Key size must be 1024 or 2048 or 3072 bits.") + if key_size not in (1024, 2048, 3072, 4096): + raise ValueError( + "Key size must be 1024, 2048, 3072, or 4096 bits." + ) ctx = self._lib.DSA_new() self.openssl_assert(ctx != self._ffi.NULL) diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py --- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -128,8 +128,10 @@ def _check_dsa_parameters(parameters): - if parameters.p.bit_length() not in [1024, 2048, 3072]: - raise ValueError("p must be exactly 1024, 2048, or 3072 bits long") + if parameters.p.bit_length() not in [1024, 2048, 3072, 4096]: + raise ValueError( + "p must be exactly 1024, 2048, 3072, or 4096 bits long" + ) if parameters.q.bit_length() not in [160, 224, 256]: raise ValueError("q must be exactly 160, 224, or 256 bits long") diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -349,6 +349,28 @@ y=y ).public_key(backend) + def test_large_p(self, backend): + key = load_vectors_from_file( + os.path.join("asymmetric", "PEM_Serialization", "dsa_4096.pem"), + lambda pemfile: serialization.load_pem_private_key( + pemfile.read(), None, backend + ), mode="rb" + ) + pn = key.private_numbers() + assert pn.public_numbers.parameter_numbers.p.bit_length() == 4096 + # Turn it back into a key to confirm that values this large pass + # verification + dsa.DSAPrivateNumbers( + public_numbers=dsa.DSAPublicNumbers( + parameter_numbers=dsa.DSAParameterNumbers( + p=pn.public_numbers.parameter_numbers.p, + q=pn.public_numbers.parameter_numbers.q, + g=pn.public_numbers.parameter_numbers.g, + ), + y=pn.public_numbers.y + ), x=pn.x + ).private_key(backend) + @pytest.mark.requires_backend_interface(interface=DSABackend) class TestDSAVerification(object): diff --git a/vectors/cryptography_vectors/asymmetric/PEM_Serialization/dsa_4096.pem b/vectors/cryptography_vectors/asymmetric/PEM_Serialization/dsa_4096.pem new file mode 100644 --- /dev/null +++ b/vectors/cryptography_vectors/asymmetric/PEM_Serialization/dsa_4096.pem @@ -0,0 +1,36 @@ +-----BEGIN DSA PRIVATE KEY----- +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 +-----END DSA PRIVATE KEY-----