DSA signing support (this is mostly skeuomorf's work, credit to him)
diff --git a/cryptography/hazmat/backends/interfaces.py b/cryptography/hazmat/backends/interfaces.py
index e63b079..264c5af 100644
--- a/cryptography/hazmat/backends/interfaces.py
+++ b/cryptography/hazmat/backends/interfaces.py
@@ -146,6 +146,13 @@
         """
 
     @abc.abstractmethod
+    def create_dsa_signature_ctx(self, private_key, algorithm):
+        """
+        Returns an object conforming to the AsymmetricSignatureContext
+        interface.
+        """
+
+    @abc.abstractmethod
     def create_dsa_verification_ctx(self, public_key, signature, algorithm):
         """
         Returns an object conforming to the AsymmetricVerificationContext
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 37deb2a..348e415 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -474,6 +474,9 @@
             y=self._bn_to_int(ctx.pub_key)
         )
 
+    def create_dsa_signature_ctx(self, private_key, algorithm):
+        return _DSASignatureContext(self, private_key, algorithm)
+
     def create_dsa_verification_ctx(self, public_key, signature,
                                     algorithm):
         return _DSAVerificationContext(self, public_key, signature,
@@ -491,6 +494,19 @@
         ctx.pub_key = self._int_to_bn(public_key.y)
         return ctx
 
+    def _dsa_cdata_from_private_key(self, private_key):
+        # Does not GC the DSA cdata. You *must* make sure it's freed
+        # correctly yourself!
+        ctx = self._lib.DSA_new()
+        assert ctx != self._ffi.NULL
+        parameters = private_key.parameters()
+        ctx.p = self._int_to_bn(parameters.p)
+        ctx.q = self._int_to_bn(parameters.q)
+        ctx.g = self._int_to_bn(parameters.g)
+        ctx.priv_key = self._int_to_bn(private_key.x)
+        ctx.pub_key = self._int_to_bn(private_key.y)
+        return ctx
+
     def dsa_hash_supported(self, algorithm):
         if self._lib.OPENSSL_VERSION_NUMBER < 0x1000000f:
             return isinstance(algorithm, hashes.SHA1)
@@ -1369,6 +1385,48 @@
             raise InvalidSignature
 
 
+@utils.register_interface(interfaces.AsymmetricSignatureContext)
+class _DSASignatureContext(object):
+    def __init__(self, backend, private_key, algorithm):
+        self._backend = backend
+        self._private_key = private_key
+        self._algorithm = algorithm
+        self._hash_ctx = _HashContext(backend, self._algorithm)
+        self._dsa_cdata = self._backend._dsa_cdata_from_private_key(
+            self._private_key)
+        self._dsa_cdata = self._backend._ffi.gc(self._dsa_cdata,
+                                                self._backend._lib.DSA_free)
+
+    def update(self, data):
+        if self._hash_ctx is None:
+            raise AlreadyFinalized("Context has already been finalized")
+
+        self._hash_ctx.update(data)
+
+    def finalize(self):
+        if self._hash_ctx is None:
+            raise AlreadyFinalized("Context has already been finalized")
+
+        data_to_sign = self._hash_ctx.finalize()
+        self._hash_ctx = None
+        sig_buf_len = self._backend._lib.DSA_size(self._dsa_cdata)
+        sig_buf = self._backend._ffi.new("unsigned char[]", sig_buf_len)
+        buflen = self._backend._ffi.new("unsigned int *")
+
+        # The first parameter passed to DSA_sign is unused by OpenSSL but
+        # must be an integer.
+        res = self._backend._lib.DSA_sign(
+            0, data_to_sign, len(data_to_sign), sig_buf,
+            buflen, self._dsa_cdata)
+
+        if res != 1:
+            errors = self._backend._consume_errors()
+            assert errors
+            raise InvalidSignature
+
+        return self._backend._ffi.buffer(sig_buf)[:]
+
+
 @utils.register_interface(interfaces.CMACContext)
 class _CMACContext(object):
     def __init__(self, backend, algorithm, ctx=None):
diff --git a/cryptography/hazmat/primitives/asymmetric/dsa.py b/cryptography/hazmat/primitives/asymmetric/dsa.py
index 57a7ef3..aa3cdc9 100644
--- a/cryptography/hazmat/primitives/asymmetric/dsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -118,6 +118,15 @@
 
         return backend.generate_dsa_private_key(parameters)
 
+    def signer(self, algorithm, backend):
+        if not isinstance(backend, DSABackend):
+            raise UnsupportedAlgorithm(
+                "Backend object does not implement DSABackend",
+                _Reasons.BACKEND_MISSING_INTERFACE
+            )
+
+        return backend.create_dsa_signature_ctx(self, algorithm)
+
     @property
     def key_size(self):
         return utils.bit_length(self._modulus)
diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index 6833f22..f363b54 100644
--- a/docs/hazmat/backends/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -345,6 +345,19 @@
             1.0.0 and the key size is larger than 1024; older OpenSSL versions
             do not support keys larger than 1024 bits.
 
+    .. method:: create_dsa_signature_ctx(private_key, algorithm)
+
+        :param private_key: An instance of a
+            :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`
+            provider.
+
+        :param algorithm: An instance of a
+            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            provider
+
+        :returns:
+            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`
+
     .. method:: create_dsa_verification_ctx(public_key, signature, algorithm)
 
         :param public_key: An instance of a
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index 03e476b..98aebb6 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -97,6 +97,49 @@
             or if the OpenSSL version is older than 1.0.0 and the key size is larger than 1024
             because older OpenSSL versions don't support a key size larger than 1024.
 
+    .. method:: signer(algorithm, backend)
+
+        .. versionadded:: 0.4
+
+        Sign data which can be verified later by others using the public key.
+
+        .. code-block:: pycon
+
+            >>> from cryptography.hazmat.backends import default_backend
+            >>> from cryptography.hazmat.primitives import hashes
+            >>> from cryptography.hazmat.primitives.asymmetric import dsa
+            >>> parameters = dsa.DSAParameters.generate(
+            ...     key_size=1024,
+            ...     backend=default_backend()
+            ... )
+            >>> private_key = dsa.DSAPrivateKey.generate(
+            ...     parameters=parameters,
+            ...     backend=default_backend()
+            ... )
+            >>> signer = private_key.signer(
+            ...     hashes.SHA256(),
+            ...     default_backend()
+            ... )
+            >>> data= b"this is some data I'd like to sign"
+            >>> signer.update(data)
+            >>> signature = signer.finalize()
+            >>> public_key = private_key.public_key()
+
+        :param algorithm: An instance of a
+            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            provider.
+
+        :param backend: A
+            :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
+            provider.
+
+        :returns:
+            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`
+
+        :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+            the provided ``backend`` does not implement
+            :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
+
 
 .. class:: DSAPublicKey(modulus, subgroup_order, generator, y)
 
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
index feafe94..dc09a26 100644
--- a/docs/hazmat/primitives/interfaces.rst
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -381,6 +381,23 @@
 
         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.
+
+        :param algorithm: An instance of a
+            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+            provider.
+
+        :param backend: A
+            :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
+            provider.
+
+        :returns:
+            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`
+
     .. attribute:: key_size
 
         :type: int
diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py
index 4c3cd58..1bfea2e 100644
--- a/tests/hazmat/primitives/test_dsa.py
+++ b/tests/hazmat/primitives/test_dsa.py
@@ -798,6 +798,60 @@
             public_key.verifier(b"sig", hashes.SHA1(), pretend_backend)
 
 
+@pytest.mark.dsa
+class TestDSASignature(object):
+    _algorithms_dict = {
+        'SHA1': hashes.SHA1,
+        'SHA224': hashes.SHA224,
+        'SHA256': hashes.SHA256,
+        'SHA384': hashes.SHA384,
+        'SHA512': hashes.SHA512}
+
+    @pytest.mark.parametrize(
+        "vector",
+        load_vectors_from_file(
+            os.path.join(
+                "asymmetric", "DSA", "FIPS_186-3", "SigGen.txt"),
+            load_fips_dsa_sig_vectors
+        )
+    )
+    def test_dsa_signing(self, vector, backend):
+        digest_algorithm = vector['digest_algorithm'].replace("-", "")
+        algorithm = self._algorithms_dict[digest_algorithm]
+        if (
+            not backend.dsa_parameters_supported(
+                vector['p'], vector['q'], vector['g']
+            ) or not backend.dsa_hash_supported(algorithm)
+        ):
+            pytest.skip(
+                "{0} does not support the provided parameters".format(backend)
+            )
+
+        private_key = dsa.DSAPrivateKey(
+            vector['p'], vector['q'], vector['g'], vector['x'], vector['y']
+        )
+        signer = private_key.signer(algorithm(), backend)
+        signer.update(vector['msg'])
+        signature = signer.finalize()
+        assert signature
+
+        public_key = private_key.public_key()
+        verifier = public_key.verifier(signature, algorithm(), backend)
+        verifier.update(vector['msg'])
+        verifier.verify()
+
+    def test_use_after_finalize(self, backend):
+        parameters = dsa.DSAParameters.generate(1024, backend)
+        private_key = dsa.DSAPrivateKey.generate(parameters, backend)
+        signer = private_key.signer(hashes.SHA1(), backend)
+        signer.update(b"data")
+        signer.finalize()
+        with pytest.raises(AlreadyFinalized):
+            signer.finalize()
+        with pytest.raises(AlreadyFinalized):
+            signer.update(b"more data")
+
+
 def test_dsa_generate_invalid_backend():
     pretend_backend = object()