From 42b3713eede3f5b417b0ce123fdcc9c4c24009d3 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 23 Feb 2014 19:13:19 -0600 Subject: add RSA verification support --- cryptography/hazmat/backends/multibackend.py | 7 ++ cryptography/hazmat/backends/openssl/backend.py | 100 ++++++++++++++++++++++- cryptography/hazmat/primitives/asymmetric/rsa.py | 4 + docs/exceptions.rst | 4 +- docs/hazmat/primitives/asymmetric/rsa.rst | 36 ++++++++ docs/hazmat/primitives/interfaces.rst | 4 +- tests/hazmat/backends/test_multibackend.py | 11 +++ tests/hazmat/primitives/test_rsa.py | 88 ++++++++++++++++++++ 8 files changed, 249 insertions(+), 5 deletions(-) diff --git a/cryptography/hazmat/backends/multibackend.py b/cryptography/hazmat/backends/multibackend.py index f0017191..de1fff7c 100644 --- a/cryptography/hazmat/backends/multibackend.py +++ b/cryptography/hazmat/backends/multibackend.py @@ -112,3 +112,10 @@ class MultiBackend(object): for b in self._filtered_backends(RSABackend): return b.create_rsa_signature_ctx(private_key, padding, algorithm) raise UnsupportedAlgorithm + + def create_rsa_verification_ctx(self, public_key, signature, padding, + algorithm): + for b in self._filtered_backends(RSABackend): + return b.create_rsa_verification_ctx(public_key, signature, + padding, algorithm) + raise UnsupportedAlgorithm diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 00fdc266..d080cc8a 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -18,7 +18,7 @@ import itertools from cryptography import utils from cryptography.exceptions import ( UnsupportedAlgorithm, InvalidTag, InternalError, AlreadyFinalized, - UnsupportedPadding + UnsupportedPadding, InvalidSignature ) from cryptography.hazmat.backends.interfaces import ( CipherBackend, HashBackend, HMACBackend, PBKDF2HMACBackend, RSABackend @@ -336,9 +336,21 @@ class Backend(object): ctx.iqmp = self._int_to_bn(private_key.iqmp) return ctx + def _rsa_cdata_from_public_key(self, public_key): + ctx = self._lib.RSA_new() + ctx = self._ffi.gc(ctx, self._lib.RSA_free) + ctx.e = self._int_to_bn(public_key.e) + ctx.n = self._int_to_bn(public_key.n) + return ctx + def create_rsa_signature_ctx(self, private_key, padding, algorithm): return _RSASignatureContext(self, private_key, padding, algorithm) + def create_rsa_verification_ctx(self, public_key, signature, padding, + algorithm): + return _RSAVerificationContext(self, public_key, signature, padding, + algorithm) + class GetCipherByName(object): def __init__(self, fmt): @@ -686,4 +698,90 @@ class _RSASignatureContext(object): return self._backend._ffi.buffer(sig_buf)[:sig_len[0]] +@utils.register_interface(interfaces.AsymmetricVerificationContext) +class _RSAVerificationContext(object): + def __init__(self, backend, public_key, signature, padding, algorithm): + self._backend = backend + self._public_key = public_key + self._signature = signature + if not isinstance(padding, interfaces.AsymmetricPadding): + raise TypeError( + "Expected interface of interfaces.AsymmetricPadding") + + if padding.name == "EMSA-PKCS1-v1_5": + if self._backend._lib.Cryptography_HAS_PKEY_CTX: + self._verify_method = self._verify_pkey_ctx + self._padding_enum = self._backend._lib.RSA_PKCS1_PADDING + else: + self._verify_method = self._verify_pkcs1 + else: + raise UnsupportedPadding + + self._padding = padding + self._algorithm = algorithm + self._hash_ctx = _HashContext(backend, self._algorithm) + + def update(self, data): + if self._hash_ctx is None: + raise AlreadyFinalized("Context was already finalized") + + self._hash_ctx.update(data) + + def verify(self): + if self._hash_ctx is None: + raise AlreadyFinalized("Context was already finalized") + + evp_pkey = self._backend._lib.EVP_PKEY_new() + assert evp_pkey != self._backend._ffi.NULL + evp_pkey = backend._ffi.gc(evp_pkey, backend._lib.EVP_PKEY_free) + rsa_cdata = backend._rsa_cdata_from_public_key(self._public_key) + res = self._backend._lib.RSA_blinding_on( + rsa_cdata, self._backend._ffi.NULL) + assert res == 1 + res = self._backend._lib.EVP_PKEY_set1_RSA(evp_pkey, rsa_cdata) + assert res == 1 + evp_md = self._backend._lib.EVP_get_digestbyname( + self._algorithm.name.encode("ascii")) + assert evp_md != self._backend._ffi.NULL + + self._verify_method(rsa_cdata, evp_pkey, evp_md) + + def _verify_pkey_ctx(self, rsa_cdata, evp_pkey, evp_md): + pkey_ctx = self._backend._lib.EVP_PKEY_CTX_new( + evp_pkey, self._backend._ffi.NULL + ) + assert pkey_ctx != self._backend._ffi.NULL + res = self._backend._lib.EVP_PKEY_verify_init(pkey_ctx) + assert res == 1 + res = self._backend._lib.EVP_PKEY_CTX_set_signature_md( + pkey_ctx, evp_md) + assert res > 0 + + res = self._backend._lib.EVP_PKEY_CTX_set_rsa_padding( + pkey_ctx, self._padding_enum) + assert res > 0 + data_to_verify = self._hash_ctx.finalize() + self._hash_ctx = None + res = self._backend._lib.EVP_PKEY_verify( + pkey_ctx, + self._signature, + len(self._signature), + data_to_verify, + len(data_to_verify) + ) + if res != 1: + raise InvalidSignature + + def _verify_pkcs1(self, rsa_cdata, evp_pkey, evp_md): + res = self._backend._lib.EVP_VerifyFinal( + self._hash_ctx._ctx, + self._signature, + len(self._signature), + evp_pkey + ) + self._hash_ctx = None + if res != 1: + raise InvalidSignature + + backend = Backend() diff --git a/cryptography/hazmat/primitives/asymmetric/rsa.py b/cryptography/hazmat/primitives/asymmetric/rsa.py index 2f9e4247..d8254046 100644 --- a/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -49,6 +49,10 @@ class RSAPublicKey(object): self._public_exponent = public_exponent self._modulus = modulus + def verifier(self, signature, padding, algorithm, backend): + return backend.create_rsa_verification_ctx(self, signature, padding, + algorithm) + @property def key_size(self): return _bit_length(self.modulus) diff --git a/docs/exceptions.rst b/docs/exceptions.rst index 0982426f..7f9ae347 100644 --- a/docs/exceptions.rst +++ b/docs/exceptions.rst @@ -10,8 +10,8 @@ Exceptions .. class:: InvalidSignature - This is raised when the verify method of a hash context's computed digest - does not match the expected digest. + This is raised when signature verification fails. This can occur with + HMAC or asymmetric key signature validation. .. class:: NotYetFinalized diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index 682820b3..528b5324 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -111,6 +111,42 @@ RSA or ``modulus`` do not match the bounds specified in :rfc:`3447`. + .. method:: verifier(signature, padding, algorithm, backend) + + .. versionadded:: 0.3 + + :param bytes signature: The signature to verify. + + :param padding: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding` + provider. + + :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.AsymmetricVerificationContext` + + .. doctest:: + + >>> from cryptography.hazmat.backends import default_backend + >>> from cryptography.hazmat.primitives import hashes + >>> from cryptography.hazmat.primitives.asymmetric import rsa, padding + >>> private_key = rsa.RSAPrivateKey.generate(65537, 2048, default_backend()) + >>> signer = private_key.signer(padding.PKCS1(), 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() + >>> verifier = public_key.verifier(signature, padding.PKCS1(), hashes.SHA256(), default_backend()) + >>> verifier.update(data) + >>> verifier.verify() + .. _`RSA`: https://en.wikipedia.org/wiki/RSA_(cryptosystem) .. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography .. _`use 65537`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst index 5be3dd95..53113223 100644 --- a/docs/hazmat/primitives/interfaces.rst +++ b/docs/hazmat/primitives/interfaces.rst @@ -254,8 +254,8 @@ Asymmetric Interfaces .. method:: verify() - :raises cryptography.exceptions.InvalidSignature: If signature does not - validate. + :raises :class:`~cryptography.exceptions.InvalidAsymmetricSignature`: If + the signature does not validate. .. class:: AsymmetricPadding diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py index be1e76e2..5a8f9934 100644 --- a/tests/hazmat/backends/test_multibackend.py +++ b/tests/hazmat/backends/test_multibackend.py @@ -89,6 +89,10 @@ class DummyRSABackend(object): def create_rsa_signature_ctx(self, private_key, padding, algorithm): pass + def create_rsa_verification_ctx(self, public_key, signature, padding, + algorithm): + pass + class TestMultiBackend(object): def test_ciphers(self): @@ -165,6 +169,9 @@ class TestMultiBackend(object): backend.create_rsa_signature_ctx("private_key", padding.PKCS1v15(), hashes.MD5()) + backend.create_rsa_verification_ctx("public_key", "sig", + padding.PKCS1(), hashes.MD5()) + backend = MultiBackend([]) with pytest.raises(UnsupportedAlgorithm): backend.generate_rsa_private_key(key_size=1024, public_exponent=3) @@ -172,3 +179,7 @@ class TestMultiBackend(object): with pytest.raises(UnsupportedAlgorithm): backend.create_rsa_signature_ctx("private_key", padding.PKCS1v15(), hashes.MD5()) + + with pytest.raises(UnsupportedAlgorithm): + backend.create_rsa_verification_ctx("public_key", "sig", + padding.PKCS1(), hashes.MD5()) diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 647c51b4..552bfc5f 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -443,3 +443,91 @@ class TestRSASignature(object): ) with pytest.raises(TypeError): private_key.signer("notpadding", hashes.SHA1(), backend) + + +@pytest.mark.rsa +class TestRSAVerification(object): + @pytest.mark.parametrize( + "pkcs1_example", + _flatten_pkcs1_examples(load_vectors_from_file( + os.path.join( + "asymmetric", "RSA", "pkcs1v15sign-vectors.txt"), + load_pkcs1_vectors + )) + ) + def test_pkcs1v15_verification(self, pkcs1_example, backend): + private, public, example = pkcs1_example + public_key = rsa.RSAPublicKey(**public) + verifier = public_key.verifier( + binascii.unhexlify(example["signature"]), + padding.PKCS1(), + hashes.SHA1(), + backend + ) + verifier.update(binascii.unhexlify(example["message"])) + verifier.verify() + + def test_invalid_pkcs1v15_signature_wrong_data(self, backend): + private_key = rsa.RSAPrivateKey.generate(65537, 512, backend) + public_key = private_key.public_key() + signer = private_key.signer(padding.PKCS1(), hashes.SHA1(), backend) + signer.update(b"sign me") + signature = signer.finalize() + verifier = public_key.verifier( + signature, + padding.PKCS1(), + hashes.SHA1(), + backend + ) + verifier.update(b"incorrect data") + with pytest.raises(exceptions.InvalidAsymmetricSignature): + verifier.verify() + + def test_invalid_pkcs1v15_signature_wrong_key(self, backend): + private_key = rsa.RSAPrivateKey.generate(65537, 512, backend) + public_key = private_key.public_key() + public_key._modulus += 2 + signer = private_key.signer(padding.PKCS1(), hashes.SHA1(), backend) + signer.update(b"sign me") + signature = signer.finalize() + verifier = public_key.verifier( + signature, + padding.PKCS1(), + hashes.SHA1(), + backend + ) + verifier.update(b"sign me") + with pytest.raises(exceptions.InvalidAsymmetricSignature): + verifier.verify() + + def test_use_after_finalize(self, backend): + private_key = rsa.RSAPrivateKey.generate(65537, 512, backend) + public_key = private_key.public_key() + signer = private_key.signer(padding.PKCS1(), hashes.SHA1(), backend) + signer.update(b"sign me") + signature = signer.finalize() + + verifier = public_key.verifier( + signature, + padding.PKCS1(), + hashes.SHA1(), + backend + ) + verifier.update(b"sign me") + verifier.verify() + with pytest.raises(exceptions.AlreadyFinalized): + verifier.verify() + with pytest.raises(exceptions.AlreadyFinalized): + verifier.update(b"more data") + + def test_unsupported_padding(self, backend): + private_key = rsa.RSAPrivateKey.generate(65537, 512, backend) + public_key = private_key.public_key() + with pytest.raises(exceptions.UnsupportedAsymmetricPadding): + public_key.verifier(b"sig", DummyPadding(), hashes.SHA1(), backend) + + def test_padding_incorrect_type(self, backend): + private_key = rsa.RSAPrivateKey.generate(65537, 512, backend) + public_key = private_key.public_key() + with pytest.raises(TypeError): + public_key.verifier(b"sig", "notpadding", hashes.SHA1(), backend) -- cgit v1.2.3 From 4c0b4a99982138c4ab83dfffb19975a91c57d1ab Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 23 Feb 2014 19:28:44 -0600 Subject: more kwargs --- docs/hazmat/primitives/asymmetric/rsa.rst | 6 +++++- tests/hazmat/primitives/test_rsa.py | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index 528b5324..198ed7a3 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -137,7 +137,11 @@ RSA >>> from cryptography.hazmat.backends import default_backend >>> from cryptography.hazmat.primitives import hashes >>> from cryptography.hazmat.primitives.asymmetric import rsa, padding - >>> private_key = rsa.RSAPrivateKey.generate(65537, 2048, default_backend()) + >>> private_key = rsa.RSAPrivateKey.generate( + ... public_exponent=65537, + ... key_size=2048, + ... backend=default_backend() + ... ) >>> signer = private_key.signer(padding.PKCS1(), hashes.SHA256(), default_backend()) >>> data= b"this is some data I'd like to sign" >>> signer.update(data) diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 552bfc5f..fb4d1d77 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -457,7 +457,10 @@ class TestRSAVerification(object): ) def test_pkcs1v15_verification(self, pkcs1_example, backend): private, public, example = pkcs1_example - public_key = rsa.RSAPublicKey(**public) + public_key = rsa.RSAPublicKey( + public_exponent=public["public_exponent"], + modulus=public["modulus"] + ) verifier = public_key.verifier( binascii.unhexlify(example["signature"]), padding.PKCS1(), -- cgit v1.2.3 From 8186251635237187012df878645a4e4af3822e4e Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 25 Feb 2014 13:29:21 -0600 Subject: kwargs and class renames to bring verification up to date --- tests/hazmat/primitives/test_rsa.py | 50 ++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index fb4d1d77..649165b8 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -463,7 +463,7 @@ class TestRSAVerification(object): ) verifier = public_key.verifier( binascii.unhexlify(example["signature"]), - padding.PKCS1(), + padding.PKCS1v15(), hashes.SHA1(), backend ) @@ -471,48 +471,60 @@ class TestRSAVerification(object): verifier.verify() def test_invalid_pkcs1v15_signature_wrong_data(self, backend): - private_key = rsa.RSAPrivateKey.generate(65537, 512, backend) + private_key = rsa.RSAPrivateKey.generate( + public_exponent=65537, + key_size=512, + backend=backend + ) public_key = private_key.public_key() - signer = private_key.signer(padding.PKCS1(), hashes.SHA1(), backend) + signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1(), backend) signer.update(b"sign me") signature = signer.finalize() verifier = public_key.verifier( signature, - padding.PKCS1(), + padding.PKCS1v15(), hashes.SHA1(), backend ) verifier.update(b"incorrect data") - with pytest.raises(exceptions.InvalidAsymmetricSignature): + with pytest.raises(exceptions.InvalidSignature): verifier.verify() def test_invalid_pkcs1v15_signature_wrong_key(self, backend): - private_key = rsa.RSAPrivateKey.generate(65537, 512, backend) + private_key = rsa.RSAPrivateKey.generate( + public_exponent=65537, + key_size=512, + backend=backend + ) public_key = private_key.public_key() public_key._modulus += 2 - signer = private_key.signer(padding.PKCS1(), hashes.SHA1(), backend) + signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1(), backend) signer.update(b"sign me") signature = signer.finalize() verifier = public_key.verifier( signature, - padding.PKCS1(), + padding.PKCS1v15(), hashes.SHA1(), backend ) verifier.update(b"sign me") - with pytest.raises(exceptions.InvalidAsymmetricSignature): + with pytest.raises(exceptions.InvalidSignature): verifier.verify() def test_use_after_finalize(self, backend): - private_key = rsa.RSAPrivateKey.generate(65537, 512, backend) + private_key = rsa.RSAPrivateKey.generate( + public_exponent=65537, + key_size=512, + backend=backend + ) public_key = private_key.public_key() - signer = private_key.signer(padding.PKCS1(), hashes.SHA1(), backend) + signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1(), backend) signer.update(b"sign me") signature = signer.finalize() verifier = public_key.verifier( signature, - padding.PKCS1(), + padding.PKCS1v15(), hashes.SHA1(), backend ) @@ -524,13 +536,21 @@ class TestRSAVerification(object): verifier.update(b"more data") def test_unsupported_padding(self, backend): - private_key = rsa.RSAPrivateKey.generate(65537, 512, backend) + private_key = rsa.RSAPrivateKey.generate( + public_exponent=65537, + key_size=512, + backend=backend + ) public_key = private_key.public_key() - with pytest.raises(exceptions.UnsupportedAsymmetricPadding): + with pytest.raises(exceptions.UnsupportedPadding): public_key.verifier(b"sig", DummyPadding(), hashes.SHA1(), backend) def test_padding_incorrect_type(self, backend): - private_key = rsa.RSAPrivateKey.generate(65537, 512, backend) + private_key = rsa.RSAPrivateKey.generate( + public_exponent=65537, + key_size=512, + backend=backend + ) public_key = private_key.public_key() with pytest.raises(TypeError): public_key.verifier(b"sig", "notpadding", hashes.SHA1(), backend) -- cgit v1.2.3 From dc720296556645f0641907e3618f6a1613c39fe7 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 25 Feb 2014 22:59:58 -0600 Subject: more PKCS1->PKCS1v15 --- tests/hazmat/backends/test_multibackend.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py index 5a8f9934..63168180 100644 --- a/tests/hazmat/backends/test_multibackend.py +++ b/tests/hazmat/backends/test_multibackend.py @@ -170,7 +170,7 @@ class TestMultiBackend(object): hashes.MD5()) backend.create_rsa_verification_ctx("public_key", "sig", - padding.PKCS1(), hashes.MD5()) + padding.PKCS1v15(), hashes.MD5()) backend = MultiBackend([]) with pytest.raises(UnsupportedAlgorithm): @@ -181,5 +181,5 @@ class TestMultiBackend(object): hashes.MD5()) with pytest.raises(UnsupportedAlgorithm): - backend.create_rsa_verification_ctx("public_key", "sig", - padding.PKCS1(), hashes.MD5()) + backend.create_rsa_verification_ctx( + "public_key", "sig", padding.PKCS1v15(), hashes.MD5()) -- cgit v1.2.3 From a0c157f467536b556481f7c2ee950612f4f8f7e7 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 25 Feb 2014 23:05:54 -0600 Subject: fix docs, port some review comments forward to the new PR --- cryptography/hazmat/backends/openssl/backend.py | 6 ++-- docs/hazmat/primitives/asymmetric/rsa.rst | 39 +++++++++++++------------ 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index d080cc8a..0c4fbc3e 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -706,7 +706,7 @@ class _RSAVerificationContext(object): self._signature = signature if not isinstance(padding, interfaces.AsymmetricPadding): raise TypeError( - "Expected interface of interfaces.AsymmetricPadding") + "Expected provider of interfaces.AsymmetricPadding") if padding.name == "EMSA-PKCS1-v1_5": if self._backend._lib.Cryptography_HAS_PKEY_CTX: @@ -723,13 +723,13 @@ class _RSAVerificationContext(object): def update(self, data): if self._hash_ctx is None: - raise AlreadyFinalized("Context was already finalized") + raise AlreadyFinalized("Context has already been finalized") self._hash_ctx.update(data) def verify(self): if self._hash_ctx is None: - raise AlreadyFinalized("Context was already finalized") + raise AlreadyFinalized("Context has already been finalized") evp_pkey = self._backend._lib.EVP_PKEY_new() assert evp_pkey != self._backend._ffi.NULL diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index 198ed7a3..b3119440 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -115,22 +115,8 @@ RSA .. versionadded:: 0.3 - :param bytes signature: The signature to verify. - - :param padding: An instance of a - :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding` - provider. - - :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.AsymmetricVerificationContext` + Verify data was signed by the private key associated with the public + key. .. doctest:: @@ -142,15 +128,32 @@ RSA ... key_size=2048, ... backend=default_backend() ... ) - >>> signer = private_key.signer(padding.PKCS1(), hashes.SHA256(), default_backend()) + >>> signer = private_key.signer(padding.PKCS1v15(), 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() - >>> verifier = public_key.verifier(signature, padding.PKCS1(), hashes.SHA256(), default_backend()) + >>> verifier = public_key.verifier(signature, padding.PKCS1v15(), hashes.SHA256(), default_backend()) >>> verifier.update(data) >>> verifier.verify() + :param bytes signature: The signature to verify. + + :param padding: An instance of a + :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding` + provider. + + :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.AsymmetricVerificationContext` + .. _`RSA`: https://en.wikipedia.org/wiki/RSA_(cryptosystem) .. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography .. _`use 65537`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html -- cgit v1.2.3 From fef1fbd1187b7fc80589553fb192210dd15a3a1c Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 26 Feb 2014 23:39:37 -0400 Subject: address some review comments --- cryptography/hazmat/backends/openssl/backend.py | 1 + docs/hazmat/primitives/interfaces.rst | 4 ++-- tests/hazmat/primitives/test_rsa.py | 8 ++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 0c4fbc3e..3eec244e 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -779,6 +779,7 @@ class _RSAVerificationContext(object): len(self._signature), evp_pkey ) + self._hash_ctx.finalize() self._hash_ctx = None if res != 1: raise InvalidSignature diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst index 53113223..15ad1d1b 100644 --- a/docs/hazmat/primitives/interfaces.rst +++ b/docs/hazmat/primitives/interfaces.rst @@ -254,8 +254,8 @@ Asymmetric Interfaces .. method:: verify() - :raises :class:`~cryptography.exceptions.InvalidAsymmetricSignature`: If - the signature does not validate. + :raises cryptography.exceptions.InvalidSignature: If the signature does + not validate. .. class:: AsymmetricPadding diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 649165b8..79323265 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -496,8 +496,12 @@ class TestRSAVerification(object): key_size=512, backend=backend ) - public_key = private_key.public_key() - public_key._modulus += 2 + private_key2 = rsa.RSAPrivateKey.generate( + public_exponent=65537, + key_size=512, + backend=backend + ) + public_key = private_key2.public_key() signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1(), backend) signer.update(b"sign me") signature = signer.finalize() -- cgit v1.2.3 From adba07a814626d1e409cd06d6a0774dae69a2c33 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 26 Feb 2014 23:55:51 -0400 Subject: docs language improvement --- docs/hazmat/primitives/asymmetric/rsa.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index b3119440..7943981e 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -115,7 +115,7 @@ RSA .. versionadded:: 0.3 - Verify data was signed by the private key associated with the public + Verify data was signed by the private key associated with this public key. .. doctest:: -- cgit v1.2.3 From 4f852a4d679e6fdf281d5fb58e7a9d3deab935b8 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 27 Feb 2014 00:00:21 -0400 Subject: assert some things --- cryptography/hazmat/backends/openssl/backend.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 3eec244e..6bb76c47 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -769,7 +769,11 @@ class _RSAVerificationContext(object): data_to_verify, len(data_to_verify) ) - if res != 1: + # The previous call can return negative numbers in the event of an + # error. This is not a signature failure but we need to fail if it + # occurs. + assert res >= 0 + if res == 0: raise InvalidSignature def _verify_pkcs1(self, rsa_cdata, evp_pkey, evp_md): @@ -781,7 +785,11 @@ class _RSAVerificationContext(object): ) self._hash_ctx.finalize() self._hash_ctx = None - if res != 1: + # The previous call can return negative numbers in the event of an + # error. This is not a signature failure but we need to fail if it + # occurs. + assert res >= 0 + if res == 0: raise InvalidSignature -- cgit v1.2.3 From bb97691d33c3ebb0764f1d97bbbda387c9eaa665 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 27 Feb 2014 09:16:13 -0400 Subject: assert another thing --- cryptography/hazmat/backends/openssl/backend.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 6bb76c47..c7ae9141 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -338,6 +338,7 @@ class Backend(object): def _rsa_cdata_from_public_key(self, public_key): ctx = self._lib.RSA_new() + assert ctx != self._ffi.NULL ctx = self._ffi.gc(ctx, self._lib.RSA_free) ctx.e = self._int_to_bn(public_key.e) ctx.n = self._int_to_bn(public_key.n) -- cgit v1.2.3