aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAviv Palivoda <palaviv@gmail.com>2016-06-30 21:42:46 +0300
committerPaul Kehrer <paul.l.kehrer@gmail.com>2016-06-30 13:42:46 -0500
commitf67429b9d199931eb695524724a947847ed1f808 (patch)
tree6cf38e2a2fdf93074964264963ba575722cb9ea2
parent602f88f35dfda15c031de0dce5305e4850df7e07 (diff)
downloadcryptography-f67429b9d199931eb695524724a947847ed1f808.tar.gz
cryptography-f67429b9d199931eb695524724a947847ed1f808.tar.bz2
cryptography-f67429b9d199931eb695524724a947847ed1f808.zip
One shot sign/verify DSA (#3003)
* Add sign and verify methods to DSA * Documented DSA sign/verify methods * Added CHANGELOG entry
-rw-r--r--CHANGELOG.rst5
-rw-r--r--docs/hazmat/primitives/asymmetric/dsa.rst53
-rw-r--r--src/cryptography/hazmat/backends/openssl/dsa.py10
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/dsa.py12
-rw-r--r--tests/hazmat/primitives/test_dsa.py20
5 files changed, 100 insertions, 0 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 28530853..f044c7e7 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -8,6 +8,11 @@ Changelog
* Added
:func:`~cryptography.hazmat.primitives.asymmetric.padding.calculate_max_pss_salt_length`.
+* Added "one shot"
+ :meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey.sign`
+ and
+ :meth:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey.verify`
+ methods to DSA keys.
1.4 - 2016-06-04
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index 93d0db6f..0eb68ce6 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -79,6 +79,16 @@ provider.
>>> signer.update(data)
>>> 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,
+ ... 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`.
@@ -102,6 +112,16 @@ You can get a public key object with
>>> verifier.update(data)
>>> verifier.verify()
+There is a shortcut to verify sufficiently short messages directly:
+
+.. doctest::
+
+ >>> public_key.verify(
+ ... signature,
+ ... data,
+ ... hashes.SHA256()
+ ... )
+
``verifier()`` takes the signature in the same format as is returned by
``signer.finalize()``.
@@ -289,6 +309,21 @@ Key interfaces
The bit length of :attr:`~DSAParameterNumbers.q`.
+ .. method:: sign(data, 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 algorithm: An instance of a
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ provider.
+
+ :return: bytes: Signature.
+
.. class:: DSAPrivateKeyWithSerialization
@@ -400,6 +435,24 @@ Key interfaces
:return bytes: Serialized key.
+ .. method:: verify(signature, data, algorithm)
+
+ .. versionadded:: 1.5
+
+ Verify one block of data which can be verified later by others using the
+ public key.
+
+ :param bytes signature: The signature to verify.
+
+ :param bytes data: The message string that was signed.
+
+ :param algorithm: An instance of a
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ provider.
+
+ :raises cryptography.exceptions.InvalidSignature: If the signature does
+ not validate.
+
.. class:: DSAPublicKeyWithSerialization
diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py
index 1012d044..43702861 100644
--- a/src/cryptography/hazmat/backends/openssl/dsa.py
+++ b/src/cryptography/hazmat/backends/openssl/dsa.py
@@ -197,6 +197,11 @@ class _DSAPrivateKey(object):
self._dsa_cdata
)
+ def sign(self, data, algorithm):
+ signer = self.signer(algorithm)
+ signer.update(data)
+ return signer.finalize()
+
@utils.register_interface(dsa.DSAPublicKeyWithSerialization)
class _DSAPublicKey(object):
@@ -263,3 +268,8 @@ class _DSAPublicKey(object):
self._evp_pkey,
None
)
+
+ def verify(self, signature, data, algorithm):
+ verifier = self.verifier(signature, algorithm)
+ verifier.update(data)
+ verifier.verify()
diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py
index 511d3464..03e6a53e 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -55,6 +55,12 @@ class DSAPrivateKey(object):
Returns an AsymmetricSignatureContext used for signing data.
"""
+ @abc.abstractmethod
+ def sign(self, data, algorithm):
+ """
+ Signs the data
+ """
+
@six.add_metaclass(abc.ABCMeta)
class DSAPrivateKeyWithSerialization(DSAPrivateKey):
@@ -103,6 +109,12 @@ class DSAPublicKey(object):
Returns the key serialized as bytes.
"""
+ @abc.abstractmethod
+ def verify(self, signature, data, algorithm):
+ """
+ Verifies the signature of the data.
+ """
+
DSAPublicKeyWithSerialization = DSAPublicKey
diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py
index 46c86d54..dde60607 100644
--- a/tests/hazmat/primitives/test_dsa.py
+++ b/tests/hazmat/primitives/test_dsa.py
@@ -606,6 +606,16 @@ class TestDSAVerification(object):
with pytest.raises(AlreadyFinalized):
verifier.update(b"more data")
+ def test_verify(self, backend):
+ message = b"one little message"
+ algorithm = hashes.SHA1()
+ private_key = DSA_KEY_1024.private_key(backend)
+ signer = private_key.signer(algorithm)
+ signer.update(message)
+ signature = signer.finalize()
+ public_key = private_key.public_key()
+ public_key.verify(signature, message, algorithm)
+
@pytest.mark.requires_backend_interface(interface=DSABackend)
class TestDSASignature(object):
@@ -661,6 +671,16 @@ class TestDSASignature(object):
with pytest.raises(AlreadyFinalized):
signer.update(b"more data")
+ def test_sign(self, backend):
+ private_key = DSA_KEY_1024.private_key(backend)
+ message = b"one little message"
+ algorithm = hashes.SHA1()
+ signature = private_key.sign(message, algorithm)
+ public_key = private_key.public_key()
+ verifier = public_key.verifier(signature, algorithm)
+ verifier.update(message)
+ verifier.verify()
+
class TestDSANumbers(object):
def test_dsa_parameter_numbers(self):