diff options
author | Colleen Murphy <cmurphy@users.noreply.github.com> | 2016-06-04 09:09:08 -0700 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2016-06-04 09:09:08 -0700 |
commit | 34d5c39a9c1efa6c2f2c9f473890ebe44816e85a (patch) | |
tree | 8009a882571352fbd33ad05ff82c841eb4a0ff2e | |
parent | 4f125c122499e21050e46f20a18bbc4848b0f43b (diff) | |
download | cryptography-34d5c39a9c1efa6c2f2c9f473890ebe44816e85a.tar.gz cryptography-34d5c39a9c1efa6c2f2c9f473890ebe44816e85a.tar.bz2 cryptography-34d5c39a9c1efa6c2f2c9f473890ebe44816e85a.zip |
Add convenience methods to sign and verify w/ RSA (#2945)
This patch adds wrapper methods to allow the user to sign and verify a
single message block without having to go through the multi-step
process of creating a signer or verifier, updating it with the one
message, and finalizing the result. This will make signing and
verifying data more user-friendly when only using small messages.
Partial bug #1529
-rw-r--r-- | docs/hazmat/primitives/asymmetric/rsa.rst | 76 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/rsa.py | 11 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/rsa.py | 12 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_rsa.py | 22 |
4 files changed, 118 insertions, 3 deletions
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index c2a6d437..70e1678e 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -153,6 +153,20 @@ secure hash function and padding: >>> signer.update(message) >>> signature = signer.finalize() +There is a shortcut to sign sufficiently short messages directly: + +.. doctest:: + + >>> message = b"A message I want to sign" + >>> signature = private_key.sign( + ... message, + ... padding.PSS( + ... mgf=padding.MGF1(hashes.SHA256()), + ... salt_length=padding.PSS.MAX_LENGTH + ... ), + ... hashes.SHA256() + ... ) + Valid paddings for signatures are :class:`~cryptography.hazmat.primitives.asymmetric.padding.PSS` and :class:`~cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15`. ``PSS`` @@ -190,6 +204,20 @@ a public key to use in verification using If the signature does not match, ``verify()`` will raise an :class:`~cryptography.exceptions.InvalidSignature` exception. +There is a shortcut to verify sufficiently short messages directly: + +.. doctest:: + + >>> public_key.verify( + ... signature, + ... message, + ... padding.PSS( + ... mgf=padding.MGF1(hashes.SHA256()), + ... salt_length=padding.PSS.MAX_LENGTH + ... ), + ... hashes.SHA256() + ... ) + Encryption ~~~~~~~~~~ @@ -486,7 +514,8 @@ Key interfaces .. versionadded:: 0.3 - Sign data which can be verified later by others using the public key. + Get signer to sign data which can be verified later by others using + the public key. :param padding: An instance of a :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding` @@ -525,6 +554,25 @@ Key interfaces The bit length of the modulus. + .. method:: sign(data, padding, algorithm) + + .. versionadded:: 1.4 + + 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 padding: An instance of an + :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding` + provider. + + :param algorithm: An instance of a + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` + provider. + + :return: bytes: Signature. + .. class:: RSAPrivateKeyWithSerialization @@ -580,8 +628,8 @@ Key interfaces .. versionadded:: 0.3 - Verify data was signed by the private key associated with this public - key. + Get verifier to verify data was signed by the private key associated + with this public key. :param bytes signature: The signature to verify. @@ -645,6 +693,28 @@ Key interfaces :return bytes: Serialized key. + .. method:: verify(signature, data, padding, algorithm) + + .. versionadded:: 1.4 + + 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 padding: An instance of an + :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding` + provider. + + :param algorithm: An instance of a + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` + provider. + + :raises cryptography.exceptions.InvalidSignature: If the signature does + not validate. + .. class:: RSAPublicKeyWithSerialization diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index fa23bf89..10c51fee 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -611,6 +611,12 @@ class _RSAPrivateKey(object): self._rsa_cdata ) + def sign(self, data, padding, algorithm): + signer = self.signer(padding, algorithm) + signer.update(data) + signature = signer.finalize() + return signature + @utils.register_interface(RSAPublicKeyWithSerialization) class _RSAPublicKey(object): @@ -661,3 +667,8 @@ class _RSAPublicKey(object): self._evp_pkey, self._rsa_cdata ) + + def verify(self, signature, data, padding, algorithm): + verifier = self.verifier(signature, padding, algorithm) + verifier.update(data) + verifier.verify() diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index 41b0089e..2cb89515 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -40,6 +40,12 @@ class RSAPrivateKey(object): The RSAPublicKey associated with this private key. """ + @abc.abstractmethod + def sign(self, data, padding, algorithm): + """ + Signs the data. + """ + @six.add_metaclass(abc.ABCMeta) class RSAPrivateKeyWithSerialization(RSAPrivateKey): @@ -88,6 +94,12 @@ class RSAPublicKey(object): Returns the key serialized as bytes. """ + @abc.abstractmethod + def verify(self, signature, data, padding, algorithm): + """ + Verifies the signature of the data. + """ + RSAPublicKeyWithSerialization = RSAPublicKey diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index c94e0df9..9f3008e3 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -481,6 +481,17 @@ class TestRSASignature(object): signer.update(b"no failure") signer.finalize() + def test_sign(self, backend): + private_key = RSA_KEY_512.private_key(backend) + message = b"one little message" + pkcs = padding.PKCS1v15() + algorithm = hashes.SHA1() + signature = private_key.sign(message, pkcs, algorithm) + public_key = private_key.public_key() + verifier = public_key.verifier(signature, pkcs, algorithm) + verifier.update(message) + verifier.verify() + @pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSAVerification(object): @@ -836,6 +847,17 @@ class TestRSAVerification(object): with pytest.raises(InvalidSignature): verifier.verify() + def test_verify(self, backend): + private_key = RSA_KEY_512.private_key(backend) + message = b"one little message" + pkcs = padding.PKCS1v15() + algorithm = hashes.SHA1() + signer = private_key.signer(pkcs, algorithm) + signer.update(message) + signature = signer.finalize() + public_key = private_key.public_key() + public_key.verify(signature, message, pkcs, algorithm) + @pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSAPSSMGF1Verification(object): |