diff options
author | Aviv Palivoda <palaviv@gmail.com> | 2016-07-02 19:43:06 +0300 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2016-07-02 12:43:06 -0400 |
commit | 2120a8e090ff8974d727f76aae5f2f9eac56656c (patch) | |
tree | c79d3eaac5584d05bead50f516e5f5dac0cd4bea | |
parent | 14a9ad4c35a625088339e2e142907243adfffa99 (diff) | |
download | cryptography-2120a8e090ff8974d727f76aae5f2f9eac56656c.tar.gz cryptography-2120a8e090ff8974d727f76aae5f2f9eac56656c.tar.bz2 cryptography-2120a8e090ff8974d727f76aae5f2f9eac56656c.zip |
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
-rw-r--r-- | CHANGELOG.rst | 5 | ||||
-rw-r--r-- | docs/hazmat/primitives/asymmetric/dsa.rst | 2 | ||||
-rw-r--r-- | docs/hazmat/primitives/asymmetric/ec.rst | 49 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/ec.py | 10 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/ec.py | 12 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_ec.py | 22 |
6 files changed, 95 insertions, 5 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f044c7e7..518f57ec 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,11 @@ Changelog 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 7ab79f8c..f77af2a2 100644 --- a/docs/hazmat/primitives/asymmetric/dsa.rst +++ b/docs/hazmat/primitives/asymmetric/dsa.rst @@ -322,7 +322,7 @@ Key interfaces :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 2c59374a..979d3e4b 100644 --- a/docs/hazmat/primitives/asymmetric/ec.rst +++ b/docs/hazmat/primitives/asymmetric/ec.rst @@ -48,6 +48,16 @@ Elliptic Curve Signature Algorithms >>> 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 @@ Key Interfaces 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 @@ Key Interfaces 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 @@ Key Interfaces :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 @@ Key Interfaces :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 2f476031..1e45e402 100644 --- a/src/cryptography/hazmat/backends/openssl/ec.py +++ b/src/cryptography/hazmat/backends/openssl/ec.py @@ -240,6 +240,11 @@ class _EllipticCurvePrivateKey(object): 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 @@ class _EllipticCurvePublicKey(object): 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 907a6358..1c576c6d 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -62,6 +62,12 @@ class EllipticCurvePrivateKey(object): 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 @@ class EllipticCurvePublicKey(object): 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 8705f79c..dff2f3e1 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -503,6 +503,28 @@ class TestECDSAVectors(object): 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): |