add generate_private_key to DSAParameters + add a new function to dsa

dsa.generate_private_key(key_size, backend) will allow you to generate a
new DSA key and implicitly generate new parameters. This streamlines the
common case and will be an avenue to support future backends that don't
allow independent generation of DSAParameters (e.g. CommonCrypto)
diff --git a/cryptography/hazmat/backends/interfaces.py b/cryptography/hazmat/backends/interfaces.py
index e4faf32..70168a0 100644
--- a/cryptography/hazmat/backends/interfaces.py
+++ b/cryptography/hazmat/backends/interfaces.py
@@ -171,6 +171,12 @@
         """
 
     @abc.abstractmethod
+    def generate_dsa_private_key_with_key_size(self, key_size):
+        """
+        Generate an DSAPrivateKey instance using key size only.
+        """
+
+    @abc.abstractmethod
     def create_dsa_signature_ctx(self, private_key, algorithm):
         """
         Returns an object conforming to the AsymmetricSignatureContext
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 6245e8e..82bdd7c 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -626,6 +626,10 @@
 
         return _DSAPrivateKey(self, ctx)
 
+    def generate_dsa_private_key_with_key_size(self, key_size):
+        parameters = self.generate_dsa_parameters(key_size)
+        return self.generate_dsa_private_key(parameters)
+
     def create_dsa_signature_ctx(self, private_key, algorithm):
         dsa_cdata = self._dsa_cdata_from_private_key(private_key)
         key = _DSAPrivateKey(self, dsa_cdata)
diff --git a/cryptography/hazmat/backends/openssl/dsa.py b/cryptography/hazmat/backends/openssl/dsa.py
index d492372..5e7a26f 100644
--- a/cryptography/hazmat/backends/openssl/dsa.py
+++ b/cryptography/hazmat/backends/openssl/dsa.py
@@ -97,6 +97,9 @@
             g=self._backend._bn_to_int(self._dsa_cdata.g)
         )
 
+    def generate_private_key(self):
+        return self._backend.generate_dsa_private_key(self)
+
 
 @utils.register_interface(DSAPrivateKeyWithNumbers)
 class _DSAPrivateKey(object):
diff --git a/cryptography/hazmat/primitives/asymmetric/dsa.py b/cryptography/hazmat/primitives/asymmetric/dsa.py
index 527b6bb..08bdad3 100644
--- a/cryptography/hazmat/primitives/asymmetric/dsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -25,8 +25,8 @@
     return backend.generate_dsa_parameters(key_size)
 
 
-def generate_private_key(parameters):
-    return parameters._backend.generate_dsa_private_key(parameters)
+def generate_private_key(key_size, backend):
+    return backend.generate_dsa_private_key_with_key_size(key_size)
 
 
 def _check_dsa_parameters(parameters):
diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py
index ef8640c..d60f9e0 100644
--- a/cryptography/hazmat/primitives/interfaces.py
+++ b/cryptography/hazmat/primitives/interfaces.py
@@ -251,7 +251,11 @@
 
 @six.add_metaclass(abc.ABCMeta)
 class DSAParameters(object):
-    pass
+    @abc.abstractmethod
+    def generate_private_key(self):
+        """
+        Generates and returns a DSAPrivateKey.
+        """
 
 
 @six.add_metaclass(abc.ABCMeta)
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index 42e3af2..095c49b 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -7,6 +7,27 @@
 
 `DSA`_ is a `public-key`_ algorithm for signing messages.
 
+.. function:: generate_private_key(key_size, backend)
+
+    .. versionadded:: 0.5
+
+    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 2014 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.
+
+    :return: A :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`
+        provider.
+
 .. function:: generate_parameters(key_size, backend)
 
     .. versionadded:: 0.5
@@ -31,19 +52,6 @@
         the provided ``backend`` does not implement
         :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
 
-.. function:: generate_private_key(parameters)
-
-    .. versionadded:: 0.5
-
-    Generate an DSA private key using the provided parameters.
-
-    :param parameters: A
-        :class:`~cryptography.hazmat.primitives.interfaces.DSAParameters`
-        provider.
-
-    :return: A :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`
-        provider.
-
 .. class:: DSAParameters(modulus, subgroup_order, generator)
 
     .. versionadded:: 0.4
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
index 755cef4..ac47c1e 100644
--- a/docs/hazmat/primitives/interfaces.rst
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -282,6 +282,17 @@
 
     `DSA`_ parameters.
 
+    .. method:: generate_private_key()
+
+        .. versionadded:: 0.5
+
+        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.interfaces.DSAPrivateKey`
+            provider.
+
 
 .. class:: DSAParametersWithNumbers
 
diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py
index 76436f7..531b448 100644
--- a/tests/hazmat/primitives/test_dsa.py
+++ b/tests/hazmat/primitives/test_dsa.py
@@ -77,7 +77,6 @@
     def test_generate_dsa_parameters(self, backend):
         parameters = dsa.generate_parameters(1024, backend)
         assert isinstance(parameters, interfaces.DSAParameters)
-        # TODO: withnumbers check like RSA
 
     def test_generate_invalid_dsa_parameters(self, backend):
         with pytest.raises(ValueError):
@@ -97,7 +96,7 @@
             q=vector['q'],
             g=vector['g']
         ).parameters(backend)
-        skey = dsa.generate_private_key(parameters)
+        skey = parameters.generate_private_key()
         if isinstance(skey, interfaces.DSAPrivateKeyWithNumbers):
             numbers = skey.private_numbers()
             skey_parameters = numbers.public_numbers.parameter_numbers
@@ -118,6 +117,16 @@
                 skey_parameters.g, numbers.x, skey_parameters.p
             )
 
+    def test_generate_dsa_private_key_and_parameters(self, backend):
+        skey = dsa.generate_private_key(1024, backend)
+        assert skey
+        if isinstance(skey, interfaces.DSAPrivateKeyWithNumbers):
+            numbers = skey.private_numbers()
+            skey_parameters = numbers.public_numbers.parameter_numbers
+            assert numbers.public_numbers.y == pow(
+                skey_parameters.g, numbers.x, skey_parameters.p
+            )
+
     def test_invalid_parameters_argument_types(self):
         with pytest.raises(TypeError):
             dsa.DSAParameters(None, None, None)