Merge pull request #2670 from joernheissler/x509_req_verify
Add verify method on CertificateSigningRequest
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst
index 4d28419..5bb4eef 100644
--- a/docs/development/test-vectors.rst
+++ b/docs/development/test-vectors.rst
@@ -283,7 +283,7 @@
request using RSA and SHA1 with a subject alternative name extension
generated using OpenSSL.
* ``two_basic_constraints.pem`` - A certificate signing request
- for a RSA 2048 bit key containing two basic constraints extensions.
+ for an RSA 2048 bit key containing two basic constraints extensions.
* ``unsupported_extension.pem`` - A certificate signing request
for an RSA 2048 bit key containing containing an unsupported
extension type. The OID was encoded as "1.2.3.4" with an
@@ -292,9 +292,11 @@
request for an RSA 2048 bit key containing containing an unsupported
extension type marked critical. The OID was encoded as "1.2.3.4"
with an ``extnValue`` of "value".
-* ``basic_constraints.pem`` - A certificate signing request for a RSA
+* ``basic_constraints.pem`` - A certificate signing request for an RSA
2048 bit key containing a basic constraints extension marked as
critical.
+* ``invalid_signature.pem`` - A certificate signing request for an RSA
+ 1024 bit key containing an invalid signature with correct padding.
Custom X.509 Certificate Revocation List Vectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index 529578b..67427dd 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -761,6 +761,12 @@
key embedded in the CSR). This data may be used to validate the CSR
signature.
+ .. attribute:: is_signature_valid
+
+ .. versionadded:: 1.3
+
+ Returns True if the CSR signature is correct, False otherwise.
+
X.509 Certificate Revocation List Builder
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index a6f7d69..c71f8d9 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -362,3 +362,16 @@
@property
def signature(self):
return _asn1_string_to_bytes(self._backend, self._x509_req.signature)
+
+ @property
+ def is_signature_valid(self):
+ pkey = self._backend._lib.X509_REQ_get_pubkey(self._x509_req)
+ self._backend.openssl_assert(pkey != self._backend._ffi.NULL)
+ pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free)
+ res = self._backend._lib.X509_REQ_verify(self._x509_req, pkey)
+
+ if res != 1:
+ self._backend._consume_errors()
+ return False
+
+ return True
diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py
index 55e965f..4a22ed0 100644
--- a/src/cryptography/x509/base.py
+++ b/src/cryptography/x509/base.py
@@ -288,6 +288,12 @@
2986.
"""
+ @abc.abstractproperty
+ def is_signature_valid(self):
+ """
+ Verifies signature of signing request.
+ """
+
@six.add_metaclass(abc.ABCMeta)
class RevokedCertificate(object):
diff --git a/tests/test_x509.py b/tests/test_x509.py
index 9054c4e..c042169 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -1241,6 +1241,22 @@
with pytest.raises(TypeError):
request.public_bytes('NotAnEncoding')
+ def test_signature_invalid(self, backend):
+ request = _load_cert(
+ os.path.join("x509", "requests", "invalid_signature.pem"),
+ x509.load_pem_x509_csr,
+ backend
+ )
+ assert not request.is_signature_valid
+
+ def test_signature_valid(self, backend):
+ request = _load_cert(
+ os.path.join("x509", "requests", "rsa_sha256.pem"),
+ x509.load_pem_x509_csr,
+ backend
+ )
+ assert request.is_signature_valid
+
@pytest.mark.parametrize(
("request_path", "loader_func", "encoding"),
[
diff --git a/vectors/cryptography_vectors/x509/requests/invalid_signature.pem b/vectors/cryptography_vectors/x509/requests/invalid_signature.pem
new file mode 100644
index 0000000..f95bd17
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/requests/invalid_signature.pem
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBTjCBuAIBADAPMQ0wCwYDVQQDDAR0ZXN0MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDOdf0xwr1fUP0+wtYfwi1sqAe78WNSONLjtGYSpEFBNS9T6dW+m3vj
+EaEZ0dI7B+Y5jC53JG8vSoBN/xLzw/CCDgLq8OvftOeS4+FZqznRDucgzbqctVzs
+PshGcfZ3n8DIiEBbSqeMvs02spKXvYxi3M2S5aJ2GVl2wNlzRLcTuwIDAQABoAAw
+DQYJKoZIhvcNAQELBQADgYEAZ7Jbqn9hhMYJ+y4ikTNG6GNu48GINyzXXX3bzv3O
++xGnKbjp99FbJKDOalnG492kZKyg2cCC5UQW8SNZOQpfnjsguB3HZoOrRlExkavY
+IapdMZiK5g6ocViceV4gRybkW/Yh3p7cFzOmaABAWzeyJm3/TcTWBLvx/M7Mj1pE
+8f8=
+-----END CERTIFICATE REQUEST-----