We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
API: registering an app id and uploading an app release needs to check revoked certificates
In order to prevent old or lost certificates from being abused we need to check if the certificate has been revoked. This has to be done before validating the certificate on app release upload and before registering a new app id.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `nextcloudappstore/core/certificate/validator.py`
Content:
```
1 import logging
2 from base64 import b64decode
3 
4 import pem
5 from OpenSSL.crypto import FILETYPE_PEM, load_certificate, verify, X509, \
6     X509Store, X509StoreContext, load_crl
7 from django.conf import settings  # type: ignore
8 from rest_framework.exceptions import APIException
9 
10 logger = logging.getLogger(__name__)
11 
12 
13 class CertificateConfiguration:
14     def __init__(self) -> None:
15         self.digest = settings.CERTIFICATE_DIGEST
16 
17 
18 class InvalidSignatureException(APIException):
19     pass
20 
21 
22 class InvalidCertificateException(APIException):
23     pass
24 
25 
26 class CertificateAppIdMismatchException(APIException):
27     pass
28 
29 
30 class CertificateValidator:
31     """
32     See https://pyopenssl.readthedocs.io/en/stable/api/crypto.html#signing
33     -and-verifying-signatures
34     """
35 
36     def __init__(self, config: CertificateConfiguration) -> None:
37         self.config = config
38 
39     def validate_signature(self, certificate: str, signature: str,
40                            data: bytes) -> None:
41         """
42         Tests if a value is a valid certificate using SHA512
43         :param certificate: the certificate to use as string
44         :param signature: the signature base64 encoded string to test
45         :param data: the binary file content that was signed
46         :raises: InvalidSignatureException if the signature is invalid
47         :return: None
48         """
49         cert = self._to_cert(certificate)
50         err_msg = 'Signature is invalid'
51         try:
52             result = verify(cert, b64decode(signature.encode()), data,
53                             self.config.digest)
54             if result is not None:
55                 raise InvalidSignatureException(err_msg)
56         except Exception as e:
57             raise InvalidSignatureException('%s: %s' % (err_msg, str(e)))
58 
59     def validate_certificate(self, certificate: str, chain: str,
60                              crl: str = None) -> None:
61         """
62         Tests if a certificate has been signed by the chain, is not revoked
63         and has not yet been expired.
64         :param certificate: the certificate to test as string
65         :param chain: the certificate chain file content as string
66         :param crl: the certificate revocation list file content as string
67         :raises: InvalidCertificateException if the certificate is invalid
68         :return: None
69         """
70         # root and intermediary certificate need to be split
71         cas = pem.parse(chain.encode())
72         store = X509Store()
73         for ca in cas:
74             store.add_cert(self._to_cert(str(ca)))
75 
76         cert = self._to_cert(certificate)
77         ctx = X509StoreContext(store, cert)
78         err_msg = 'Certificate is invalid'
79 
80         if crl:
81             crl = load_crl(FILETYPE_PEM, crl)
82             store.add_crl(crl)
83 
84         try:
85             result = ctx.verify_certificate()
86             if result is not None:
87                 raise InvalidCertificateException(err_msg)
88         except Exception as e:
89             raise InvalidCertificateException('%s: %s' % (err_msg, str(e)))
90 
91     def get_cn(self, certificate: str) -> str:
92         """
93         Extracts the CN from a certificate and removes the leading
94         slash, e.g. /news should return news
95         :param certificate: certificate
96         :return: the certificate's subject without the leading slash
97         """
98         cert = self._to_cert(certificate)
99         return cert.get_subject().CN
100 
101     def validate_app_id(self, certificate: str, app_id: str) -> None:
102         """
103         Validates if the CN matches the app id
104         :param certificate: app certificate
105         :param app_id: the app id
106         :raises CertificateAppIdMismatchException: if the app id and cert CN do
107         not match
108         :return: None
109         """
110         cn = self.get_cn(certificate)
111         if cn != app_id:
112             msg = 'App id %s does not match cert CN %s' % (app_id, cn)
113             raise CertificateAppIdMismatchException(msg)
114 
115     def _to_cert(self, certificate: str) -> X509:
116         return load_certificate(FILETYPE_PEM, certificate.encode())
117
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/nextcloudappstore/core/certificate/validator.py b/nextcloudappstore/core/certificate/validator.py
--- a/nextcloudappstore/core/certificate/validator.py
+++ b/nextcloudappstore/core/certificate/validator.py
@@ -3,7 +3,7 @@
 
 import pem
 from OpenSSL.crypto import FILETYPE_PEM, load_certificate, verify, X509, \
-    X509Store, X509StoreContext, load_crl
+    X509Store, X509StoreContext, load_crl, X509StoreFlags
 from django.conf import settings  # type: ignore
 from rest_framework.exceptions import APIException
 
@@ -74,12 +74,14 @@
             store.add_cert(self._to_cert(str(ca)))
 
         cert = self._to_cert(certificate)
-        ctx = X509StoreContext(store, cert)
-        err_msg = 'Certificate is invalid'
 
         if crl:
-            crl = load_crl(FILETYPE_PEM, crl)
-            store.add_crl(crl)
+            parsed_crl = load_crl(FILETYPE_PEM, crl)
+            store.set_flags(X509StoreFlags.CRL_CHECK)
+            store.add_crl(parsed_crl)
+
+        ctx = X509StoreContext(store, cert)
+        err_msg = 'Certificate is invalid'
 
         try:
             result = ctx.verify_certificate()

{"golden_diff": "diff --git a/nextcloudappstore/core/certificate/validator.py b/nextcloudappstore/core/certificate/validator.py\n--- a/nextcloudappstore/core/certificate/validator.py\n+++ b/nextcloudappstore/core/certificate/validator.py\n@@ -3,7 +3,7 @@\n \n import pem\n from OpenSSL.crypto import FILETYPE_PEM, load_certificate, verify, X509, \\\n-    X509Store, X509StoreContext, load_crl\n+    X509Store, X509StoreContext, load_crl, X509StoreFlags\n from django.conf import settings  # type: ignore\n from rest_framework.exceptions import APIException\n \n@@ -74,12 +74,14 @@\n             store.add_cert(self._to_cert(str(ca)))\n \n         cert = self._to_cert(certificate)\n-        ctx = X509StoreContext(store, cert)\n-        err_msg = 'Certificate is invalid'\n \n         if crl:\n-            crl = load_crl(FILETYPE_PEM, crl)\n-            store.add_crl(crl)\n+            parsed_crl = load_crl(FILETYPE_PEM, crl)\n+            store.set_flags(X509StoreFlags.CRL_CHECK)\n+            store.add_crl(parsed_crl)\n+\n+        ctx = X509StoreContext(store, cert)\n+        err_msg = 'Certificate is invalid'\n \n         try:\n             result = ctx.verify_certificate()\n", "issue": "API: registering an app id and uploading an app release needs to check revoked certificates\nIn order to prevent old or lost certificates from being abused we need to check if the certificate has been revoked. This has to be done before validating the certificate on app release upload and before registering a new app id.\n\n", "before_files": [{"content": "import logging\nfrom base64 import b64decode\n\nimport pem\nfrom OpenSSL.crypto import FILETYPE_PEM, load_certificate, verify, X509, \\\n    X509Store, X509StoreContext, load_crl\nfrom django.conf import settings  # type: ignore\nfrom rest_framework.exceptions import APIException\n\nlogger = logging.getLogger(__name__)\n\n\nclass CertificateConfiguration:\n    def __init__(self) -> None:\n        self.digest = settings.CERTIFICATE_DIGEST\n\n\nclass InvalidSignatureException(APIException):\n    pass\n\n\nclass InvalidCertificateException(APIException):\n    pass\n\n\nclass CertificateAppIdMismatchException(APIException):\n    pass\n\n\nclass CertificateValidator:\n    \"\"\"\n    See https://pyopenssl.readthedocs.io/en/stable/api/crypto.html#signing\n    -and-verifying-signatures\n    \"\"\"\n\n    def __init__(self, config: CertificateConfiguration) -> None:\n        self.config = config\n\n    def validate_signature(self, certificate: str, signature: str,\n                           data: bytes) -> None:\n        \"\"\"\n        Tests if a value is a valid certificate using SHA512\n        :param certificate: the certificate to use as string\n        :param signature: the signature base64 encoded string to test\n        :param data: the binary file content that was signed\n        :raises: InvalidSignatureException if the signature is invalid\n        :return: None\n        \"\"\"\n        cert = self._to_cert(certificate)\n        err_msg = 'Signature is invalid'\n        try:\n            result = verify(cert, b64decode(signature.encode()), data,\n                            self.config.digest)\n            if result is not None:\n                raise InvalidSignatureException(err_msg)\n        except Exception as e:\n            raise InvalidSignatureException('%s: %s' % (err_msg, str(e)))\n\n    def validate_certificate(self, certificate: str, chain: str,\n                             crl: str = None) -> None:\n        \"\"\"\n        Tests if a certificate has been signed by the chain, is not revoked\n        and has not yet been expired.\n        :param certificate: the certificate to test as string\n        :param chain: the certificate chain file content as string\n        :param crl: the certificate revocation list file content as string\n        :raises: InvalidCertificateException if the certificate is invalid\n        :return: None\n        \"\"\"\n        # root and intermediary certificate need to be split\n        cas = pem.parse(chain.encode())\n        store = X509Store()\n        for ca in cas:\n            store.add_cert(self._to_cert(str(ca)))\n\n        cert = self._to_cert(certificate)\n        ctx = X509StoreContext(store, cert)\n        err_msg = 'Certificate is invalid'\n\n        if crl:\n            crl = load_crl(FILETYPE_PEM, crl)\n            store.add_crl(crl)\n\n        try:\n            result = ctx.verify_certificate()\n            if result is not None:\n                raise InvalidCertificateException(err_msg)\n        except Exception as e:\n            raise InvalidCertificateException('%s: %s' % (err_msg, str(e)))\n\n    def get_cn(self, certificate: str) -> str:\n        \"\"\"\n        Extracts the CN from a certificate and removes the leading\n        slash, e.g. /news should return news\n        :param certificate: certificate\n        :return: the certificate's subject without the leading slash\n        \"\"\"\n        cert = self._to_cert(certificate)\n        return cert.get_subject().CN\n\n    def validate_app_id(self, certificate: str, app_id: str) -> None:\n        \"\"\"\n        Validates if the CN matches the app id\n        :param certificate: app certificate\n        :param app_id: the app id\n        :raises CertificateAppIdMismatchException: if the app id and cert CN do\n        not match\n        :return: None\n        \"\"\"\n        cn = self.get_cn(certificate)\n        if cn != app_id:\n            msg = 'App id %s does not match cert CN %s' % (app_id, cn)\n            raise CertificateAppIdMismatchException(msg)\n\n    def _to_cert(self, certificate: str) -> X509:\n        return load_certificate(FILETYPE_PEM, certificate.encode())\n", "path": "nextcloudappstore/core/certificate/validator.py"}], "after_files": [{"content": "import logging\nfrom base64 import b64decode\n\nimport pem\nfrom OpenSSL.crypto import FILETYPE_PEM, load_certificate, verify, X509, \\\n    X509Store, X509StoreContext, load_crl, X509StoreFlags\nfrom django.conf import settings  # type: ignore\nfrom rest_framework.exceptions import APIException\n\nlogger = logging.getLogger(__name__)\n\n\nclass CertificateConfiguration:\n    def __init__(self) -> None:\n        self.digest = settings.CERTIFICATE_DIGEST\n\n\nclass InvalidSignatureException(APIException):\n    pass\n\n\nclass InvalidCertificateException(APIException):\n    pass\n\n\nclass CertificateAppIdMismatchException(APIException):\n    pass\n\n\nclass CertificateValidator:\n    \"\"\"\n    See https://pyopenssl.readthedocs.io/en/stable/api/crypto.html#signing\n    -and-verifying-signatures\n    \"\"\"\n\n    def __init__(self, config: CertificateConfiguration) -> None:\n        self.config = config\n\n    def validate_signature(self, certificate: str, signature: str,\n                           data: bytes) -> None:\n        \"\"\"\n        Tests if a value is a valid certificate using SHA512\n        :param certificate: the certificate to use as string\n        :param signature: the signature base64 encoded string to test\n        :param data: the binary file content that was signed\n        :raises: InvalidSignatureException if the signature is invalid\n        :return: None\n        \"\"\"\n        cert = self._to_cert(certificate)\n        err_msg = 'Signature is invalid'\n        try:\n            result = verify(cert, b64decode(signature.encode()), data,\n                            self.config.digest)\n            if result is not None:\n                raise InvalidSignatureException(err_msg)\n        except Exception as e:\n            raise InvalidSignatureException('%s: %s' % (err_msg, str(e)))\n\n    def validate_certificate(self, certificate: str, chain: str,\n                             crl: str = None) -> None:\n        \"\"\"\n        Tests if a certificate has been signed by the chain, is not revoked\n        and has not yet been expired.\n        :param certificate: the certificate to test as string\n        :param chain: the certificate chain file content as string\n        :param crl: the certificate revocation list file content as string\n        :raises: InvalidCertificateException if the certificate is invalid\n        :return: None\n        \"\"\"\n        # root and intermediary certificate need to be split\n        cas = pem.parse(chain.encode())\n        store = X509Store()\n        for ca in cas:\n            store.add_cert(self._to_cert(str(ca)))\n\n        cert = self._to_cert(certificate)\n\n        if crl:\n            parsed_crl = load_crl(FILETYPE_PEM, crl)\n            store.set_flags(X509StoreFlags.CRL_CHECK)\n            store.add_crl(parsed_crl)\n\n        ctx = X509StoreContext(store, cert)\n        err_msg = 'Certificate is invalid'\n\n        try:\n            result = ctx.verify_certificate()\n            if result is not None:\n                raise InvalidCertificateException(err_msg)\n        except Exception as e:\n            raise InvalidCertificateException('%s: %s' % (err_msg, str(e)))\n\n    def get_cn(self, certificate: str) -> str:\n        \"\"\"\n        Extracts the CN from a certificate and removes the leading\n        slash, e.g. /news should return news\n        :param certificate: certificate\n        :return: the certificate's subject without the leading slash\n        \"\"\"\n        cert = self._to_cert(certificate)\n        return cert.get_subject().CN\n\n    def validate_app_id(self, certificate: str, app_id: str) -> None:\n        \"\"\"\n        Validates if the CN matches the app id\n        :param certificate: app certificate\n        :param app_id: the app id\n        :raises CertificateAppIdMismatchException: if the app id and cert CN do\n        not match\n        :return: None\n        \"\"\"\n        cn = self.get_cn(certificate)\n        if cn != app_id:\n            msg = 'App id %s does not match cert CN %s' % (app_id, cn)\n            raise CertificateAppIdMismatchException(msg)\n\n    def _to_cert(self, certificate: str) -> X509:\n        return load_certificate(FILETYPE_PEM, certificate.encode())\n", "path": "nextcloudappstore/core/certificate/validator.py"}]}