One shot sign/verification ECDSA (#3029)

* Add sign and verify methods to ECDSA

* Documented ECDSA sign/verify methods

* Added CHANGELOG entry

* Skipping test verify and sign if curve is not supported

* Fixed typo in documentation return type

* Removed provider language from EllipticCurvePrivateKey and EllipticCurvePublicKey
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index f044c7e..518f57e 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -13,6 +13,11 @@
   and
   :meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey.verify`
   methods to DSA keys.
+* Added "one shot"
+  :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey.sign`
+  and
+  :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.verify`
+  methods to ECDSA keys.
 
 
 1.4 - 2016-06-04
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index 7ab79f8..f77af2a 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -322,7 +322,7 @@
             :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
             provider.
 
-        :return: bytes: Signature.
+        :return bytes: Signature.
 
 
 .. class:: DSAPrivateKeyWithSerialization
diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst
index 2c59374..979d3e4 100644
--- a/docs/hazmat/primitives/asymmetric/ec.rst
+++ b/docs/hazmat/primitives/asymmetric/ec.rst
@@ -48,6 +48,16 @@
         >>> signer.update(b" to sign")
         >>> signature = signer.finalize()
 
+    There is a shortcut to sign sufficiently short messages directly:
+
+    .. doctest::
+
+        >>> 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 is DER encoded as
     described in :rfc:`3279`. This can be decoded using
     :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`.
@@ -371,8 +381,8 @@
         The signature is formatted as DER-encoded bytes, as specified in
         :rfc:`3279`.
 
-        :param signature_algorithm: An instance of a
-            :class:`EllipticCurveSignatureAlgorithm` provider.
+        :param signature_algorithm: An instance of
+            :class:`EllipticCurveSignatureAlgorithm`.
 
         :returns:
             :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricSignatureContext`
@@ -401,6 +411,20 @@
 
         The EllipticCurvePublicKey object for this private key.
 
+    .. method:: sign(data, signature_algorithm)
+
+        .. versionadded:: 1.5
+
+        Sign one block of data which can be verified later by others using the
+        public key.
+
+        :param bytes data: The message string to sign.
+
+        :param signature_algorithm: An instance of
+            :class:`EllipticCurveSignatureAlgorithm`.
+
+        :return bytes: Signature.
+
 
 .. class:: EllipticCurvePrivateKeyWithSerialization
 
@@ -455,8 +479,8 @@
         :param bytes signature: The signature to verify. DER encoded as
             specified in :rfc:`3279`.
 
-        :param signature_algorithm: An instance of a
-            :class:`EllipticCurveSignatureAlgorithm` provider.
+        :param signature_algorithm: An instance of
+            :class:`EllipticCurveSignatureAlgorithm`.
 
         :returns:
             :class:`~cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext`
@@ -490,6 +514,23 @@
 
         :return bytes: Serialized key.
 
+    .. method:: verify(signature, data, signature_algorithm)
+
+        .. versionadded:: 1.5
+
+        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 signature_algorithm: An instance of
+            :class:`EllipticCurveSignatureAlgorithm`.
+
+        :raises cryptography.exceptions.InvalidSignature: If the signature does
+            not validate.
+
 
 .. class:: EllipticCurvePublicKeyWithSerialization
 
diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py
index 2f47603..1e45e40 100644
--- a/src/cryptography/hazmat/backends/openssl/ec.py
+++ b/src/cryptography/hazmat/backends/openssl/ec.py
@@ -240,6 +240,11 @@
             self._ec_key
         )
 
+    def sign(self, data, signature_algorithm):
+        signer = self.signer(signature_algorithm)
+        signer.update(data)
+        return signer.finalize()
+
 
 @utils.register_interface(ec.EllipticCurvePublicKeyWithSerialization)
 class _EllipticCurvePublicKey(object):
@@ -303,3 +308,8 @@
             self._evp_pkey,
             None
         )
+
+    def verify(self, signature, data, signature_algorithm):
+        verifier = self.verifier(signature, signature_algorithm)
+        verifier.update(data)
+        verifier.verify()
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py
index 907a635..1c576c6 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/ec.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py
@@ -62,6 +62,12 @@
         The EllipticCurve that this key is on.
         """
 
+    @abc.abstractproperty
+    def sign(self, data, signature_algorithm):
+        """
+        Signs the data
+        """
+
 
 @six.add_metaclass(abc.ABCMeta)
 class EllipticCurvePrivateKeyWithSerialization(EllipticCurvePrivateKey):
@@ -104,6 +110,12 @@
         Returns the key serialized as bytes.
         """
 
+    @abc.abstractmethod
+    def verify(self, signature, data, signature_algorithm):
+        """
+        Verifies the signature of the data.
+        """
+
 
 EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey
 
diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py
index 8705f79..dff2f3e 100644
--- a/tests/hazmat/primitives/test_ec.py
+++ b/tests/hazmat/primitives/test_ec.py
@@ -503,6 +503,28 @@
         else:
             verifier.verify()
 
+    def test_sign(self, backend):
+        _skip_curve_unsupported(backend, ec.SECP256R1())
+        message = b"one little message"
+        algorithm = ec.ECDSA(hashes.SHA1())
+        private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+        signature = private_key.sign(message, algorithm)
+        public_key = private_key.public_key()
+        verifier = public_key.verifier(signature, algorithm)
+        verifier.update(message)
+        verifier.verify()
+
+    def test_verify(self, backend):
+        _skip_curve_unsupported(backend, ec.SECP256R1())
+        message = b"one little message"
+        algorithm = ec.ECDSA(hashes.SHA1())
+        private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+        signer = private_key.signer(algorithm)
+        signer.update(message)
+        signature = signer.finalize()
+        public_key = private_key.public_key()
+        public_key.verify(signature, message, algorithm)
+
 
 class TestECNumbersEquality(object):
     def test_public_numbers_eq(self):