Repository: codemagic-ci-cd/cli-tools (language: python)

Issue:
Dependencies: Set upper bound to required cryptography version
[Cryptography version 37.0.0](https://cryptography.io/en/latest/changelog/#v37-0-0) released on 26.04.2022 introduced some breaking changes, which breaks CLI tools as `pyOpenSSL` uses attributes which were removed. 

Example traceback:

```python
Traceback (most recent call last):
  File "/home/builder/.local/bin/codemagic-cli-tools", line 5, in <module>
    from codemagic.tools import CodemagicCliTools
  File "/home/builder/.local/lib/python3.8/site-packages/codemagic/tools/__init__.py", line 1, in <module>
    from .android_app_bundle import AndroidAppBundle
  File "/home/builder/.local/lib/python3.8/site-packages/codemagic/tools/android_app_bundle.py", line 12, in <module>
    from codemagic.models import AndroidSigningInfo
  File "/home/builder/.local/lib/python3.8/site-packages/codemagic/models/__init__.py", line 1, in <module>
    from .altool import Altool
  File "/home/builder/.local/lib/python3.8/site-packages/codemagic/models/altool/__init__.py", line 1, in <module>
    from .altool import Altool
  File "/home/builder/.local/lib/python3.8/site-packages/codemagic/models/altool/altool.py", line 27, in <module>
    from .enums import AuthenticationMethod
  File "/home/builder/.local/lib/python3.8/site-packages/codemagic/models/altool/enums.py", line 9, in <module>
    from codemagic.models.application_package import Ipa
  File "/home/builder/.local/lib/python3.8/site-packages/codemagic/models/application_package/__init__.py", line 1, in <module>
    from .ipa import Ipa
  File "/home/builder/.local/lib/python3.8/site-packages/codemagic/models/application_package/ipa.py", line 13, in <module>
    from codemagic.models.certificate import Certificate
  File "/home/builder/.local/lib/python3.8/site-packages/codemagic/models/certificate.py", line 18, in <module>
    from OpenSSL import crypto
  File "/usr/lib/python3/dist-packages/OpenSSL/__init__.py", line 8, in <module>
    from OpenSSL import crypto, SSL
  File "/usr/lib/python3/dist-packages/OpenSSL/crypto.py", line 1553, in <module>
    class X509StoreFlags(object):
  File "/usr/lib/python3/dist-packages/OpenSSL/crypto.py", line 1573, in X509StoreFlags
    CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
AttributeError: module 'lib' has no attribute 'X509_V_FLAG_CB_ISSUER_CHECK'
```


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6f0ab51f..4ff6df74 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+Version 0.28.0
+-------------
+
+This release includes changes and fixes from [PR #243](https://github.com/codemagic-ci-cd/cli-tools/pull/243).
+
+**Bugfixes**
+- Fix properties `not_after` and `not_before` of `codemagic.models.Certificate` to work with `pyOpenSSL` versions `<=19.1.0`.
+
+**Development**
+- Remove type stubs for package `cryptography`.
+- Add tuple `SUPPORTED_PUBLIC_KEY_TYPES` to module `codemagic.models.private_key`.
+- Remove [`OpenSSL.crypto.X509`](https://www.pyopenssl.org/en/stable/api/crypto.html?highlight=X509#x509-objects) usages from `codemagic.models.Certificate` internals by replacing them with functionality from [`cryptography.x509.Certificate`](https://cryptography.io/en/latest/x509/reference/#x-509-certificate-object).
+
 Version 0.27.6
 -------------
 
diff --git a/src/codemagic/__version__.py b/src/codemagic/__version__.py
index 3fb9fd23..6ed90e94 100644
--- a/src/codemagic/__version__.py
+++ b/src/codemagic/__version__.py
@@ -1,5 +1,5 @@
 __title__ = 'codemagic-cli-tools'
 __description__ = 'CLI tools used in Codemagic builds'
-__version__ = '0.27.6'
+__version__ = '0.28.0'
 __url__ = 'https://github.com/codemagic-ci-cd/cli-tools'
 __licence__ = 'GNU General Public License v3.0'
diff --git a/src/codemagic/mixins/str_converter.py b/src/codemagic/mixins/str_converter.py
index af4e0e32..51495d69 100644
--- a/src/codemagic/mixins/str_converter.py
+++ b/src/codemagic/mixins/str_converter.py
@@ -1,17 +1,18 @@
 from typing import AnyStr
+from typing import Union
 
 
 class StringConverterMixin:
 
     @classmethod
-    def _bytes(cls, str_or_bytes: AnyStr) -> bytes:
+    def _bytes(cls, str_or_bytes: Union[str, bytes, AnyStr]) -> bytes:
         if isinstance(str_or_bytes, str):
             return str_or_bytes.encode(encoding='utf-8')
         else:
             return str_or_bytes
 
     @classmethod
-    def _str(cls, str_or_bytes: AnyStr) -> str:
+    def _str(cls, str_or_bytes: Union[str, bytes, AnyStr]) -> str:
         if isinstance(str_or_bytes, bytes):
             return str_or_bytes.decode(encoding='utf-8')
         else:
diff --git a/src/codemagic/models/certificate.py b/src/codemagic/models/certificate.py
index 0057ff7e..c78bde0f 100644
--- a/src/codemagic/models/certificate.py
+++ b/src/codemagic/models/certificate.py
@@ -24,6 +24,7 @@
 
 from .certificate_p12_exporter import P12Exporter
 from .json_serializable import JsonSerializable
+from .private_key import SUPPORTED_PUBLIC_KEY_TYPES
 from .private_key import PrivateKey
 
 
@@ -32,6 +33,7 @@ class Certificate(JsonSerializable, RunningCliAppMixin, StringConverterMixin):
 
     def __init__(self, x509_certificate: X509):
         self.x509 = x509_certificate
+        self.certificate: x509.Certificate = x509_certificate.to_cryptography()
 
     @classmethod
     def _get_x509_certificate(cls, buffer: AnyStr, buffer_type: int):
@@ -63,13 +65,17 @@ def from_p12(cls, p12: bytes, password: Optional[AnyStr] = None) -> Certificate:
 
     @property
     def subject(self) -> Dict[str, str]:
-        subject = self.x509.get_subject()
-        return {self._str(k): self._str(v) for k, v in subject.get_components()}
+        return {
+            self._get_rfc_4514_attribute_name(name_attribute): self._str(name_attribute.value)
+            for name_attribute in self.certificate.subject
+        }
 
     @property
     def issuer(self) -> Dict[str, str]:
-        issuer = self.x509.get_issuer()
-        return {self._str(k): self._str(v) for k, v in issuer.get_components()}
+        return {
+            self._get_rfc_4514_attribute_name(name_attribute): self._str(name_attribute.value)
+            for name_attribute in self.certificate.issuer
+        }
 
     @property
     def common_name(self) -> str:
@@ -77,29 +83,35 @@ def common_name(self) -> str:
 
     @property
     def not_after(self) -> str:
-        return self._str(self.x509.get_notAfter())
+        """
+        Get the timestamp at which the certificate stops being valid
+        as an ASN.1 TIME YYYYMMDDhhmmssZ
+        """
+        not_after = self.certificate.not_valid_after
+        return not_after.strftime('%Y%m%d%H%M%SZ')
 
     @property
     def not_before(self) -> str:
-        return self._str(self.x509.get_notBefore())
+        not_before = self.certificate.not_valid_before
+        return not_before.strftime('%Y%m%d%H%M%SZ')
 
     @property
     def has_expired(self) -> bool:
-        return self.x509.has_expired()
+        current_time = datetime.utcnow().replace(tzinfo=timezone.utc)
+        return self.expires_at < current_time
+        return self.expires_at < datetime.utcnow().replace(tzinfo=timezone.utc)
 
     @property
     def expires_at(self) -> datetime:
-        naive_dt = datetime.strptime(self.not_after, '%Y%m%d%H%M%SZ')
-        return naive_dt.astimezone(timezone.utc)
+        return self.certificate.not_valid_after.replace(tzinfo=timezone.utc)
 
     @property
     def serial(self) -> int:
-        return self.x509.get_serial_number()
+        return self.certificate.serial_number
 
     @property
     def extensions(self) -> List[str]:
-        extensions_count = self.x509.get_extension_count()
-        return [self._str(self.x509.get_extension(i).get_short_name()) for i in range(extensions_count)]
+        return [self._str(e.oid._name) for e in self.certificate.extensions]
 
     @property
     def is_development_certificate(self) -> bool:
@@ -132,7 +144,7 @@ def dict(self) -> Dict[str, Union[str, int, Dict[str, str], List[str]]]:
         }
 
     def as_pem(self) -> str:
-        pem = self.x509.to_cryptography().public_bytes(serialization.Encoding.PEM)
+        pem = self.certificate.public_bytes(serialization.Encoding.PEM)
         return self._str(pem)
 
     @classmethod
@@ -149,8 +161,7 @@ def get_certificate_signing_request_content(cls, csr: x509.CertificateSigningReq
         return cls._str(public_bytes)
 
     def get_fingerprint(self, algorithm: hashes.HashAlgorithm) -> str:
-        x509_certificate = self.x509.to_cryptography()
-        fingerprint = x509_certificate.fingerprint(algorithm)
+        fingerprint = self.certificate.fingerprint(algorithm)
         return fingerprint.hex().upper()
 
     def export_p12(self,
@@ -169,7 +180,9 @@ def export_p12(self,
         return exporter.export(_export_path)
 
     def is_signed_with(self, private_key: PrivateKey) -> bool:
-        certificate_public_key = self.x509.to_cryptography().public_key()
+        certificate_public_key = self.certificate.public_key()
+        if not isinstance(certificate_public_key, SUPPORTED_PUBLIC_KEY_TYPES):
+            raise TypeError('Public key type is not supported', type(certificate_public_key))
         certificate_public_numbers = certificate_public_key.public_numbers()
         private_key_public_numbers = private_key.public_key.public_numbers()
         return certificate_public_numbers == private_key_public_numbers
@@ -205,3 +218,15 @@ def get_text_summary(self) -> str:
             f'SHA1: {self.get_fingerprint(hashes.SHA1())}',
             f'SHA256: {self.get_fingerprint(hashes.SHA256())}',
         ])
+
+    @staticmethod
+    def _get_rfc_4514_attribute_name(name_attribute: x509.NameAttribute) -> str:
+        # Attribute rfc4514_attribute_name was introduced in cryptography version 35.0.0.
+        # Use this if possible, otherwise resolve it from full RFC 4514 string which
+        # also contains value.
+        # https://cryptography.io/en/latest/x509/reference/#cryptography.509.NameAttribute.rfc4514_attribute_name
+        if hasattr(name_attribute, 'rfc4514_attribute_name'):
+            return name_attribute.rfc4514_attribute_name
+        else:
+            rfc4514_string = name_attribute.rfc4514_string()
+            return rfc4514_string.split('=', maxsplit=1)[0]
diff --git a/src/codemagic/models/private_key.py b/src/codemagic/models/private_key.py
index 4711e5eb..15e383f2 100644
--- a/src/codemagic/models/private_key.py
+++ b/src/codemagic/models/private_key.py
@@ -20,7 +20,7 @@
 from codemagic.mixins import StringConverterMixin
 from codemagic.utilities import log
 
-_SUPPORTED_PRIVATE_KEY_TYPES = (
+SUPPORTED_PRIVATE_KEY_TYPES = (
     DSAPrivateKey,
     EllipticCurvePrivateKey,
     RSAPrivateKey,
@@ -32,6 +32,12 @@
     RSAPrivateKey,
 ]
 
+SUPPORTED_PUBLIC_KEY_TYPES = (
+    DSAPublicKey,
+    EllipticCurvePublicKey,
+    RSAPublicKey,
+)
+
 CryptographyPublicKey = Union[
     DSAPublicKey,
     EllipticCurvePublicKey,
@@ -87,7 +93,7 @@ def from_p12(cls, p12: bytes, password: Optional[AnyStr] = None) -> PrivateKey:
         cryptography_private_key, _, _ = pkcs12.load_key_and_certificates(p12, password_encoded)
         if cryptography_private_key is None:
             raise ValueError('Private key is missing from PKCS#12')
-        elif not isinstance(cryptography_private_key, _SUPPORTED_PRIVATE_KEY_TYPES):
+        elif not isinstance(cryptography_private_key, SUPPORTED_PRIVATE_KEY_TYPES):
             raise TypeError('Private key type is not supported', type(cryptography_private_key))
         return PrivateKey(cryptography_private_key)
 
diff --git a/stubs/cryptography/__about__.pyi b/stubs/cryptography/__about__.pyi
deleted file mode 100644
index 4e34cd9b..00000000
--- a/stubs/cryptography/__about__.pyi
+++ /dev/null
@@ -1,16 +0,0 @@
-# Stubs for cryptography.__about__ (Python 3)
-#
-# NOTE: This dynamically typed stub was automatically generated by stubgen.
-
-from typing import Any
-
-__title__: str
-__summary__: str
-__uri__: str
-__email__: str
-__license__: str
-__copyright__: Any
-
-# Names in __all__ with no definition:
-__author__: str
-__version__: str
diff --git a/stubs/cryptography/__init__.pyi b/stubs/cryptography/__init__.pyi
deleted file mode 100644
index f47a5484..00000000
--- a/stubs/cryptography/__init__.pyi
+++ /dev/null
@@ -1,5 +0,0 @@
-# Stubs for cryptography (Python 3)
-#
-# NOTE: This dynamically typed stub was automatically generated by stubgen.
-
-from cryptography.__about__ import __author__ as __author__, __copyright__ as __copyright__, __email__ as __email__, __license__ as __license__, __summary__ as __summary__, __title__ as __title__, __uri__ as __uri__, __version__ as __version__
diff --git a/stubs/cryptography/hazmat/primitives/asymmetric/rsa.pyi b/stubs/cryptography/hazmat/primitives/asymmetric/rsa.pyi
deleted file mode 100644
index 3c5c98cc..00000000
--- a/stubs/cryptography/hazmat/primitives/asymmetric/rsa.pyi
+++ /dev/null
@@ -1,66 +0,0 @@
-# Stubs for cryptography.hazmat.primitives.asymmetric.rsa (Python 3)
-#
-# NOTE: This dynamically typed stub was automatically generated by stubgen.
-
-import abc
-from typing import Any
-
-class RSAPrivateKey(metaclass=abc.ABCMeta):
-    @abc.abstractmethod
-    def signer(self, padding: Any, algorithm: Any) -> Any: ...
-    @abc.abstractmethod
-    def decrypt(self, ciphertext: Any, padding: Any) -> Any: ...
-    def key_size(self) -> Any: ...
-    @abc.abstractmethod
-    def public_key(self) -> Any: ...
-    @abc.abstractmethod
-    def sign(self, data: Any, padding: Any, algorithm: Any) -> Any: ...
-
-class RSAPrivateKeyWithSerialization(RSAPrivateKey, metaclass=abc.ABCMeta):
-    @abc.abstractmethod
-    def private_numbers(self) -> Any: ...
-    @abc.abstractmethod
-    def private_bytes(self, encoding: Any, format: Any, encryption_algorithm: Any) -> Any: ...
-
-class RSAPublicKey(metaclass=abc.ABCMeta):
-    @abc.abstractmethod
-    def verifier(self, signature: Any, padding: Any, algorithm: Any) -> Any: ...
-    @abc.abstractmethod
-    def encrypt(self, plaintext: Any, padding: Any) -> Any: ...
-    def key_size(self) -> Any: ...
-    @abc.abstractmethod
-    def public_numbers(self) -> Any: ...
-    @abc.abstractmethod
-    def public_bytes(self, encoding: Any, format: Any) -> Any: ...
-    @abc.abstractmethod
-    def verify(self, signature: Any, data: Any, padding: Any, algorithm: Any) -> Any: ...
-RSAPublicKeyWithSerialization = RSAPublicKey
-
-def generate_private_key(public_exponent: Any, key_size: Any, backend: Any): ...
-def rsa_crt_iqmp(p: Any, q: Any): ...
-def rsa_crt_dmp1(private_exponent: Any, p: Any): ...
-def rsa_crt_dmq1(private_exponent: Any, q: Any): ...
-def rsa_recover_prime_factors(n: Any, e: Any, d: Any): ...
-
-class RSAPrivateNumbers:
-    def __init__(self, p: Any, q: Any, d: Any, dmp1: Any, dmq1: Any, iqmp: Any, public_numbers: Any) -> None: ...
-    p: Any = ...
-    q: Any = ...
-    d: Any = ...
-    dmp1: Any = ...
-    dmq1: Any = ...
-    iqmp: Any = ...
-    public_numbers: Any = ...
-    def private_key(self, backend: Any): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class RSAPublicNumbers:
-    def __init__(self, e: Any, n: Any) -> None: ...
-    e: Any = ...
-    n: Any = ...
-    def public_key(self, backend: Any): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
diff --git a/stubs/cryptography/x509/__init__.pyi b/stubs/cryptography/x509/__init__.pyi
deleted file mode 100644
index f2022cdf..00000000
--- a/stubs/cryptography/x509/__init__.pyi
+++ /dev/null
@@ -1,16 +0,0 @@
-# Stubs for cryptography.x509 (Python 3)
-#
-# NOTE: This dynamically typed stub was automatically generated by stubgen.
-
-from cryptography.x509 import certificate_transparency as certificate_transparency
-from cryptography.x509.base import Certificate as Certificate, CertificateBuilder as CertificateBuilder, CertificateRevocationList as CertificateRevocationList, CertificateRevocationListBuilder as CertificateRevocationListBuilder, CertificateSigningRequest as CertificateSigningRequest, CertificateSigningRequestBuilder as CertificateSigningRequestBuilder, InvalidVersion as InvalidVersion, RevokedCertificate as RevokedCertificate, RevokedCertificateBuilder as RevokedCertificateBuilder, Version as Version, load_der_x509_certificate as load_der_x509_certificate, load_der_x509_crl as load_der_x509_crl, load_der_x509_csr as load_der_x509_csr, load_pem_x509_certificate as load_pem_x509_certificate, load_pem_x509_crl as load_pem_x509_crl, load_pem_x509_csr as load_pem_x509_csr, random_serial_number as random_serial_number
-from cryptography.x509.extensions import AccessDescription as AccessDescription, AuthorityInformationAccess as AuthorityInformationAccess, AuthorityKeyIdentifier as AuthorityKeyIdentifier, BasicConstraints as BasicConstraints, CRLDistributionPoints as CRLDistributionPoints, CRLNumber as CRLNumber, CRLReason as CRLReason, CertificateIssuer as CertificateIssuer, CertificatePolicies as CertificatePolicies, DeltaCRLIndicator as DeltaCRLIndicator, DistributionPoint as DistributionPoint, DuplicateExtension as DuplicateExtension, ExtendedKeyUsage as ExtendedKeyUsage, Extension as Extension, ExtensionNotFound as ExtensionNotFound, ExtensionType as ExtensionType, Extensions as Extensions, FreshestCRL as FreshestCRL, GeneralNames as GeneralNames, InhibitAnyPolicy as InhibitAnyPolicy, InvalidityDate as InvalidityDate, IssuerAlternativeName as IssuerAlternativeName, IssuingDistributionPoint as IssuingDistributionPoint, KeyUsage as KeyUsage, NameConstraints as NameConstraints, NoticeReference as NoticeReference, OCSPNoCheck as OCSPNoCheck, OCSPNonce as OCSPNonce, PolicyConstraints as PolicyConstraints, PolicyInformation as PolicyInformation, PrecertPoison as PrecertPoison, PrecertificateSignedCertificateTimestamps as PrecertificateSignedCertificateTimestamps, ReasonFlags as ReasonFlags, SubjectAlternativeName as SubjectAlternativeName, SubjectKeyIdentifier as SubjectKeyIdentifier, TLSFeature as TLSFeature, TLSFeatureType as TLSFeatureType, UnrecognizedExtension as UnrecognizedExtension, UserNotice as UserNotice
-from cryptography.x509.general_name import DNSName as DNSName, DirectoryName as DirectoryName, GeneralName as GeneralName, IPAddress as IPAddress, OtherName as OtherName, RFC822Name as RFC822Name, RegisteredID as RegisteredID, UniformResourceIdentifier as UniformResourceIdentifier, UnsupportedGeneralNameType as UnsupportedGeneralNameType, _GENERAL_NAMES as _GENERAL_NAMES
-from cryptography.x509.name import Name as Name, NameAttribute as NameAttribute, RelativeDistinguishedName as RelativeDistinguishedName
-from cryptography.x509.oid import ObjectIdentifier as ObjectIdentifier, _SIG_OIDS_TO_HASH as _SIG_OIDS_TO_HASH
-from typing import Any
-
-OID_CA_ISSUERS: Any
-OID_OCSP: Any
-
-NameOID: Any
diff --git a/stubs/cryptography/x509/base.pyi b/stubs/cryptography/x509/base.pyi
deleted file mode 100644
index 7656e5fc..00000000
--- a/stubs/cryptography/x509/base.pyi
+++ /dev/null
@@ -1,134 +0,0 @@
-# Stubs for cryptography.x509.base (Python 3)
-#
-# NOTE: This dynamically typed stub was automatically generated by stubgen.
-
-import abc
-from enum import Enum
-from typing import Any, Optional
-
-class Version(Enum):
-    v1: int = ...
-    v3: int = ...
-
-def load_pem_x509_certificate(data: Any, backend: Any): ...
-def load_der_x509_certificate(data: Any, backend: Any): ...
-def load_pem_x509_csr(data: Any, backend: Any): ...
-def load_der_x509_csr(data: Any, backend: Any): ...
-def load_pem_x509_crl(data: Any, backend: Any): ...
-def load_der_x509_crl(data: Any, backend: Any): ...
-
-class InvalidVersion(Exception):
-    parsed_version: Any = ...
-    def __init__(self, msg: Any, parsed_version: Any) -> None: ...
-
-class Certificate(metaclass=abc.ABCMeta):
-    @abc.abstractmethod
-    def fingerprint(self, algorithm: Any) -> Any: ...
-    def serial_number(self) -> Any: ...
-    def version(self) -> Any: ...
-    @abc.abstractmethod
-    def public_key(self) -> Any: ...
-    def not_valid_before(self) -> Any: ...
-    def not_valid_after(self) -> Any: ...
-    def issuer(self) -> Any: ...
-    def subject(self) -> Any: ...
-    def signature_hash_algorithm(self) -> Any: ...
-    def signature_algorithm_oid(self) -> Any: ...
-    def extensions(self) -> Any: ...
-    def signature(self) -> Any: ...
-    def tbs_certificate_bytes(self) -> Any: ...
-    @abc.abstractmethod
-    def __eq__(self, other: Any) -> Any: ...
-    @abc.abstractmethod
-    def __ne__(self, other: Any) -> Any: ...
-    @abc.abstractmethod
-    def __hash__(self) -> Any: ...
-    @abc.abstractmethod
-    def public_bytes(self, encoding: Any) -> Any: ...
-
-class CertificateRevocationList(metaclass=abc.ABCMeta):
-    @abc.abstractmethod
-    def public_bytes(self, encoding: Any) -> Any: ...
-    @abc.abstractmethod
-    def fingerprint(self, algorithm: Any) -> Any: ...
-    @abc.abstractmethod
-    def get_revoked_certificate_by_serial_number(self, serial_number: Any) -> Any: ...
-    def signature_hash_algorithm(self) -> Any: ...
-    def signature_algorithm_oid(self) -> Any: ...
-    def issuer(self) -> Any: ...
-    def next_update(self) -> Any: ...
-    def last_update(self) -> Any: ...
-    def extensions(self) -> Any: ...
-    def signature(self) -> Any: ...
-    def tbs_certlist_bytes(self) -> Any: ...
-    @abc.abstractmethod
-    def __eq__(self, other: Any) -> Any: ...
-    @abc.abstractmethod
-    def __ne__(self, other: Any) -> Any: ...
-    @abc.abstractmethod
-    def __len__(self) -> Any: ...
-    @abc.abstractmethod
-    def __getitem__(self, idx: Any) -> Any: ...
-    @abc.abstractmethod
-    def __iter__(self) -> Any: ...
-    @abc.abstractmethod
-    def is_signature_valid(self, public_key: Any) -> Any: ...
-
-class CertificateSigningRequest(metaclass=abc.ABCMeta):
-    @abc.abstractmethod
-    def __eq__(self, other: Any) -> Any: ...
-    @abc.abstractmethod
-    def __ne__(self, other: Any) -> Any: ...
-    @abc.abstractmethod
-    def __hash__(self) -> Any: ...
-    @abc.abstractmethod
-    def public_key(self) -> Any: ...
-    def subject(self) -> Any: ...
-    def signature_hash_algorithm(self) -> Any: ...
-    def signature_algorithm_oid(self) -> Any: ...
-    def extensions(self) -> Any: ...
-    @abc.abstractmethod
-    def public_bytes(self, encoding: Any) -> Any: ...
-    def signature(self) -> Any: ...
-    def tbs_certrequest_bytes(self) -> Any: ...
-    def is_signature_valid(self) -> Any: ...
-
-class RevokedCertificate(metaclass=abc.ABCMeta):
-    def serial_number(self) -> Any: ...
-    def revocation_date(self) -> Any: ...
-    def extensions(self) -> Any: ...
-
-class CertificateSigningRequestBuilder:
-    def __init__(self, subject_name: Optional[Any] = ..., extensions: Any = ...) -> None: ...
-    def subject_name(self, name: Any): ...
-    def add_extension(self, extension: Any, critical: Any): ...
-    def sign(self, private_key: Any, algorithm: Any, backend: Any): ...
-
-class CertificateBuilder:
-    def __init__(self, issuer_name: Optional[Any] = ..., subject_name: Optional[Any] = ..., public_key: Optional[Any] = ..., serial_number: Optional[Any] = ..., not_valid_before: Optional[Any] = ..., not_valid_after: Optional[Any] = ..., extensions: Any = ...) -> None: ...
-    def issuer_name(self, name: Any): ...
-    def subject_name(self, name: Any): ...
-    def public_key(self, key: Any): ...
-    def serial_number(self, number: Any): ...
-    def not_valid_before(self, time: Any): ...
-    def not_valid_after(self, time: Any): ...
-    def add_extension(self, extension: Any, critical: Any): ...
-    def sign(self, private_key: Any, algorithm: Any, backend: Any): ...
-
-class CertificateRevocationListBuilder:
-    def __init__(self, issuer_name: Optional[Any] = ..., last_update: Optional[Any] = ..., next_update: Optional[Any] = ..., extensions: Any = ..., revoked_certificates: Any = ...) -> None: ...
-    def issuer_name(self, issuer_name: Any): ...
-    def last_update(self, last_update: Any): ...
-    def next_update(self, next_update: Any): ...
-    def add_extension(self, extension: Any, critical: Any): ...
-    def add_revoked_certificate(self, revoked_certificate: Any): ...
-    def sign(self, private_key: Any, algorithm: Any, backend: Any): ...
-
-class RevokedCertificateBuilder:
-    def __init__(self, serial_number: Optional[Any] = ..., revocation_date: Optional[Any] = ..., extensions: Any = ...) -> None: ...
-    def serial_number(self, number: Any): ...
-    def revocation_date(self, time: Any): ...
-    def add_extension(self, extension: Any, critical: Any): ...
-    def build(self, backend: Any): ...
-
-def random_serial_number(): ...
diff --git a/stubs/cryptography/x509/certificate_transparency.pyi b/stubs/cryptography/x509/certificate_transparency.pyi
deleted file mode 100644
index c83cf9d6..00000000
--- a/stubs/cryptography/x509/certificate_transparency.pyi
+++ /dev/null
@@ -1,20 +0,0 @@
-# Stubs for cryptography.x509.certificate_transparency (Python 3)
-#
-# NOTE: This dynamically typed stub was automatically generated by stubgen.
-
-import abc
-from enum import Enum
-from typing import Any
-
-class LogEntryType(Enum):
-    X509_CERTIFICATE: int = ...
-    PRE_CERTIFICATE: int = ...
-
-class Version(Enum):
-    v1: int = ...
-
-class SignedCertificateTimestamp(metaclass=abc.ABCMeta):
-    def version(self) -> Any: ...
-    def log_id(self) -> Any: ...
-    def timestamp(self) -> Any: ...
-    def entry_type(self) -> Any: ...
diff --git a/stubs/cryptography/x509/extensions.pyi b/stubs/cryptography/x509/extensions.pyi
deleted file mode 100644
index 3accb7e9..00000000
--- a/stubs/cryptography/x509/extensions.pyi
+++ /dev/null
@@ -1,357 +0,0 @@
-# Stubs for cryptography.x509.extensions (Python 3)
-#
-# NOTE: This dynamically typed stub was automatically generated by stubgen.
-
-import abc
-from enum import Enum
-from typing import Any
-
-class DuplicateExtension(Exception):
-    oid: Any = ...
-    def __init__(self, msg: Any, oid: Any) -> None: ...
-
-class ExtensionNotFound(Exception):
-    oid: Any = ...
-    def __init__(self, msg: Any, oid: Any) -> None: ...
-
-class ExtensionType(metaclass=abc.ABCMeta):
-    def oid(self) -> Any: ...
-
-class Extensions:
-    def __init__(self, extensions: Any) -> None: ...
-    def get_extension_for_oid(self, oid: Any): ...
-    def get_extension_for_class(self, extclass: Any): ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-
-class CRLNumber:
-    oid: Any = ...
-    def __init__(self, crl_number: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    crl_number: Any = ...
-
-class AuthorityKeyIdentifier:
-    oid: Any = ...
-    def __init__(self, key_identifier: Any, authority_cert_issuer: Any, authority_cert_serial_number: Any) -> None: ...
-    @classmethod
-    def from_issuer_public_key(cls, public_key: Any): ...
-    @classmethod
-    def from_issuer_subject_key_identifier(cls, ski: Any): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    key_identifier: Any = ...
-    authority_cert_issuer: Any = ...
-    authority_cert_serial_number: Any = ...
-
-class SubjectKeyIdentifier:
-    oid: Any = ...
-    def __init__(self, digest: Any) -> None: ...
-    @classmethod
-    def from_public_key(cls, public_key: Any): ...
-    digest: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class AuthorityInformationAccess:
-    oid: Any = ...
-    def __init__(self, descriptions: Any) -> None: ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class AccessDescription:
-    def __init__(self, access_method: Any, access_location: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    access_method: Any = ...
-    access_location: Any = ...
-
-class BasicConstraints:
-    oid: Any = ...
-    def __init__(self, ca: Any, path_length: Any) -> None: ...
-    ca: Any = ...
-    path_length: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class DeltaCRLIndicator:
-    oid: Any = ...
-    def __init__(self, crl_number: Any) -> None: ...
-    crl_number: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class CRLDistributionPoints:
-    oid: Any = ...
-    def __init__(self, distribution_points: Any) -> None: ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class FreshestCRL:
-    oid: Any = ...
-    def __init__(self, distribution_points: Any) -> None: ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class DistributionPoint:
-    def __init__(self, full_name: Any, relative_name: Any, reasons: Any, crl_issuer: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    full_name: Any = ...
-    relative_name: Any = ...
-    reasons: Any = ...
-    crl_issuer: Any = ...
-
-class ReasonFlags(Enum):
-    unspecified: str = ...
-    key_compromise: str = ...
-    ca_compromise: str = ...
-    affiliation_changed: str = ...
-    superseded: str = ...
-    cessation_of_operation: str = ...
-    certificate_hold: str = ...
-    privilege_withdrawn: str = ...
-    aa_compromise: str = ...
-    remove_from_crl: str = ...
-
-class PolicyConstraints:
-    oid: Any = ...
-    def __init__(self, require_explicit_policy: Any, inhibit_policy_mapping: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    require_explicit_policy: Any = ...
-    inhibit_policy_mapping: Any = ...
-
-class CertificatePolicies:
-    oid: Any = ...
-    def __init__(self, policies: Any) -> None: ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class PolicyInformation:
-    def __init__(self, policy_identifier: Any, policy_qualifiers: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    policy_identifier: Any = ...
-    policy_qualifiers: Any = ...
-
-class UserNotice:
-    def __init__(self, notice_reference: Any, explicit_text: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    notice_reference: Any = ...
-    explicit_text: Any = ...
-
-class NoticeReference:
-    def __init__(self, organization: Any, notice_numbers: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    organization: Any = ...
-    notice_numbers: Any = ...
-
-class ExtendedKeyUsage:
-    oid: Any = ...
-    def __init__(self, usages: Any) -> None: ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class OCSPNoCheck:
-    oid: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class PrecertPoison:
-    oid: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class TLSFeature:
-    oid: Any = ...
-    def __init__(self, features: Any) -> None: ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class TLSFeatureType(Enum):
-    status_request: int = ...
-    status_request_v2: int = ...
-
-class InhibitAnyPolicy:
-    oid: Any = ...
-    def __init__(self, skip_certs: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    skip_certs: Any = ...
-
-class KeyUsage:
-    oid: Any = ...
-    def __init__(self, digital_signature: Any, content_commitment: Any, key_encipherment: Any, data_encipherment: Any, key_agreement: Any, key_cert_sign: Any, crl_sign: Any, encipher_only: Any, decipher_only: Any) -> None: ...
-    digital_signature: Any = ...
-    content_commitment: Any = ...
-    key_encipherment: Any = ...
-    data_encipherment: Any = ...
-    key_agreement: Any = ...
-    key_cert_sign: Any = ...
-    crl_sign: Any = ...
-    @property
-    def encipher_only(self): ...
-    @property
-    def decipher_only(self): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class NameConstraints:
-    oid: Any = ...
-    def __init__(self, permitted_subtrees: Any, excluded_subtrees: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    permitted_subtrees: Any = ...
-    excluded_subtrees: Any = ...
-
-class Extension:
-    def __init__(self, oid: Any, critical: Any, value: Any) -> None: ...
-    oid: Any = ...
-    critical: Any = ...
-    value: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class GeneralNames:
-    def __init__(self, general_names: Any) -> None: ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-    def get_values_for_type(self, type: Any): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class SubjectAlternativeName:
-    oid: Any = ...
-    def __init__(self, general_names: Any) -> None: ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-    def get_values_for_type(self, type: Any): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class IssuerAlternativeName:
-    oid: Any = ...
-    def __init__(self, general_names: Any) -> None: ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-    def get_values_for_type(self, type: Any): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class CertificateIssuer:
-    oid: Any = ...
-    def __init__(self, general_names: Any) -> None: ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-    def get_values_for_type(self, type: Any): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class CRLReason:
-    oid: Any = ...
-    def __init__(self, reason: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    reason: Any = ...
-
-class InvalidityDate:
-    oid: Any = ...
-    def __init__(self, invalidity_date: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    invalidity_date: Any = ...
-
-class PrecertificateSignedCertificateTimestamps:
-    oid: Any = ...
-    def __init__(self, signed_certificate_timestamps: Any) -> None: ...
-    __len__: Any = ...
-    __iter__: Any = ...
-    __getitem__: Any = ...
-    def __hash__(self): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-
-class OCSPNonce:
-    oid: Any = ...
-    def __init__(self, nonce: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    nonce: Any = ...
-
-class IssuingDistributionPoint:
-    oid: Any = ...
-    def __init__(self, full_name: Any, relative_name: Any, only_contains_user_certs: Any, only_contains_ca_certs: Any, only_some_reasons: Any, indirect_crl: Any, only_contains_attribute_certs: Any) -> None: ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    full_name: Any = ...
-    relative_name: Any = ...
-    only_contains_user_certs: Any = ...
-    only_contains_ca_certs: Any = ...
-    only_some_reasons: Any = ...
-    indirect_crl: Any = ...
-    only_contains_attribute_certs: Any = ...
-
-class UnrecognizedExtension:
-    def __init__(self, oid: Any, value: Any) -> None: ...
-    oid: Any = ...
-    value: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
diff --git a/stubs/cryptography/x509/general_name.pyi b/stubs/cryptography/x509/general_name.pyi
deleted file mode 100644
index 3d1f609f..00000000
--- a/stubs/cryptography/x509/general_name.pyi
+++ /dev/null
@@ -1,65 +0,0 @@
-# Stubs for cryptography.x509.general_name (Python 3)
-#
-# NOTE: This dynamically typed stub was automatically generated by stubgen.
-
-import abc
-from typing import Any
-
-class UnsupportedGeneralNameType(Exception):
-    type: Any = ...
-    def __init__(self, msg: Any, type: Any) -> None: ...
-
-class GeneralName(metaclass=abc.ABCMeta):
-    def value(self) -> Any: ...
-
-class RFC822Name:
-    def __init__(self, value: Any) -> None: ...
-    value: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class DNSName:
-    def __init__(self, value: Any) -> None: ...
-    value: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class UniformResourceIdentifier:
-    def __init__(self, value: Any) -> None: ...
-    value: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class DirectoryName:
-    def __init__(self, value: Any) -> None: ...
-    value: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class RegisteredID:
-    def __init__(self, value: Any) -> None: ...
-    value: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class IPAddress:
-    def __init__(self, value: Any) -> None: ...
-    value: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class OtherName:
-    def __init__(self, type_id: Any, value: Any) -> None: ...
-    type_id: Any = ...
-    value: Any = ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-_GENERAL_NAMES: Any
diff --git a/stubs/cryptography/x509/name.pyi b/stubs/cryptography/x509/name.pyi
deleted file mode 100644
index 336d0a86..00000000
--- a/stubs/cryptography/x509/name.pyi
+++ /dev/null
@@ -1,50 +0,0 @@
-# Stubs for cryptography.x509.name (Python 3)
-#
-# NOTE: This dynamically typed stub was automatically generated by stubgen.
-
-from enum import Enum
-from typing import Any
-
-class _ASN1Type(Enum):
-    UTF8String: int = ...
-    NumericString: int = ...
-    PrintableString: int = ...
-    T61String: int = ...
-    IA5String: int = ...
-    UTCTime: int = ...
-    GeneralizedTime: int = ...
-    VisibleString: int = ...
-    UniversalString: int = ...
-    BMPString: int = ...
-
-class NameAttribute:
-    def __init__(self, oid: Any, value: Any, _type: Any = ...) -> None: ...
-    oid: Any = ...
-    value: Any = ...
-    def rfc4514_string(self): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-
-class RelativeDistinguishedName:
-    def __init__(self, attributes: Any) -> None: ...
-    def get_attributes_for_oid(self, oid: Any): ...
-    def rfc4514_string(self): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    def __iter__(self): ...
-    def __len__(self): ...
-
-class Name:
-    def __init__(self, attributes: Any) -> None: ...
-    def rfc4514_string(self): ...
-    def get_attributes_for_oid(self, oid: Any): ...
-    @property
-    def rdns(self): ...
-    def public_bytes(self, backend: Any): ...
-    def __eq__(self, other: Any): ...
-    def __ne__(self, other: Any): ...
-    def __hash__(self): ...
-    def __iter__(self) -> None: ...
-    def __len__(self): ...
diff --git a/stubs/cryptography/x509/oid.pyi b/stubs/cryptography/x509/oid.pyi
deleted file mode 100644
index 48826932..00000000
--- a/stubs/cryptography/x509/oid.pyi
+++ /dev/null
@@ -1,105 +0,0 @@
-# Stubs for cryptography.x509.oid (Python 3)
-#
-# NOTE: This dynamically typed stub was automatically generated by stubgen.
-
-from typing import Any
-
-class ExtensionOID:
-    SUBJECT_DIRECTORY_ATTRIBUTES: Any = ...
-    SUBJECT_KEY_IDENTIFIER: Any = ...
-    KEY_USAGE: Any = ...
-    SUBJECT_ALTERNATIVE_NAME: Any = ...
-    ISSUER_ALTERNATIVE_NAME: Any = ...
-    BASIC_CONSTRAINTS: Any = ...
-    NAME_CONSTRAINTS: Any = ...
-    CRL_DISTRIBUTION_POINTS: Any = ...
-    CERTIFICATE_POLICIES: Any = ...
-    POLICY_MAPPINGS: Any = ...
-    AUTHORITY_KEY_IDENTIFIER: Any = ...
-    POLICY_CONSTRAINTS: Any = ...
-    EXTENDED_KEY_USAGE: Any = ...
-    FRESHEST_CRL: Any = ...
-    INHIBIT_ANY_POLICY: Any = ...
-    ISSUING_DISTRIBUTION_POINT: Any = ...
-    AUTHORITY_INFORMATION_ACCESS: Any = ...
-    SUBJECT_INFORMATION_ACCESS: Any = ...
-    OCSP_NO_CHECK: Any = ...
-    TLS_FEATURE: Any = ...
-    CRL_NUMBER: Any = ...
-    DELTA_CRL_INDICATOR: Any = ...
-    PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: Any = ...
-    PRECERT_POISON: Any = ...
-
-class OCSPExtensionOID:
-    NONCE: Any = ...
-
-class CRLEntryExtensionOID:
-    CERTIFICATE_ISSUER: Any = ...
-    CRL_REASON: Any = ...
-    INVALIDITY_DATE: Any = ...
-
-class NameOID:
-    COMMON_NAME: Any = ...
-    COUNTRY_NAME: Any = ...
-    LOCALITY_NAME: Any = ...
-    STATE_OR_PROVINCE_NAME: Any = ...
-    STREET_ADDRESS: Any = ...
-    ORGANIZATION_NAME: Any = ...
-    ORGANIZATIONAL_UNIT_NAME: Any = ...
-    SERIAL_NUMBER: Any = ...
-    SURNAME: Any = ...
-    GIVEN_NAME: Any = ...
-    TITLE: Any = ...
-    GENERATION_QUALIFIER: Any = ...
-    X500_UNIQUE_IDENTIFIER: Any = ...
-    DN_QUALIFIER: Any = ...
-    PSEUDONYM: Any = ...
-    USER_ID: Any = ...
-    DOMAIN_COMPONENT: Any = ...
-    EMAIL_ADDRESS: Any = ...
-    JURISDICTION_COUNTRY_NAME: Any = ...
-    JURISDICTION_LOCALITY_NAME: Any = ...
-    JURISDICTION_STATE_OR_PROVINCE_NAME: Any = ...
-    BUSINESS_CATEGORY: Any = ...
-    POSTAL_ADDRESS: Any = ...
-    POSTAL_CODE: Any = ...
-
-class SignatureAlgorithmOID:
-    RSA_WITH_MD5: Any = ...
-    RSA_WITH_SHA1: Any = ...
-    RSA_WITH_SHA224: Any = ...
-    RSA_WITH_SHA256: Any = ...
-    RSA_WITH_SHA384: Any = ...
-    RSA_WITH_SHA512: Any = ...
-    RSASSA_PSS: Any = ...
-    ECDSA_WITH_SHA1: Any = ...
-    ECDSA_WITH_SHA224: Any = ...
-    ECDSA_WITH_SHA256: Any = ...
-    ECDSA_WITH_SHA384: Any = ...
-    ECDSA_WITH_SHA512: Any = ...
-    DSA_WITH_SHA1: Any = ...
-    DSA_WITH_SHA224: Any = ...
-    DSA_WITH_SHA256: Any = ...
-    ED25519: Any = ...
-    ED448: Any = ...
-
-class ExtendedKeyUsageOID:
-    SERVER_AUTH: Any = ...
-    CLIENT_AUTH: Any = ...
-    CODE_SIGNING: Any = ...
-    EMAIL_PROTECTION: Any = ...
-    TIME_STAMPING: Any = ...
-    OCSP_SIGNING: Any = ...
-    ANY_EXTENDED_KEY_USAGE: Any = ...
-
-class AuthorityInformationAccessOID:
-    CA_ISSUERS: Any = ...
-    OCSP: Any = ...
-
-class CertificatePoliciesOID:
-    CPS_QUALIFIER: Any = ...
-    CPS_USER_NOTICE: Any = ...
-    ANY_POLICY: Any = ...
-
-ObjectIdentifier: Any
-_SIG_OIDS_TO_HASH: Any


Test patch:
diff --git a/tests/models/test_certificate.py b/tests/models/test_certificate.py
index 983cebdb..134b8a8c 100644
--- a/tests/models/test_certificate.py
+++ b/tests/models/test_certificate.py
@@ -1,8 +1,12 @@
 from __future__ import annotations
 
+from datetime import datetime
+from datetime import timezone
+from distutils.version import LooseVersion
 from unittest import mock
 from unittest.mock import PropertyMock
 
+import cryptography
 import pytest
 from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives import serialization
@@ -94,6 +98,14 @@ def certificate(certificate_asn1) -> Certificate:
     return Certificate.from_ans1(certificate_asn1)
 
 
+@pytest.mark.skipif(
+    LooseVersion(cryptography.__version__) < LooseVersion('36.0.0'),
+    reason=(
+        f'Cryptography {cryptography.__version__} < 36.0.0 generates '
+        f'slightly different CSR public bytes for certificate request '
+        f'than is expected here.'
+    ),
+)
 def test_create_certificate_signing_request(unencrypted_pem, certificate_signing_request_pem):
     pk = PrivateKey.from_pem(unencrypted_pem.content)
     csr = Certificate.create_certificate_signing_request(pk)
@@ -173,3 +185,59 @@ def test_is_development_certificate(is_development_cert, cert_common_name, certi
     patched_common_name = PropertyMock(return_value=cert_common_name)
     with mock.patch.object(Certificate, 'common_name', new_callable=patched_common_name):
         assert certificate.is_development_certificate is is_development_cert
+
+
+def test_subject(certificate):
+    expected_subject = {
+        'C': 'US',
+        'CN': 'iPhone Developer: Created via API (6HQ443353U)',
+        'O': 'NEVERCODE LTD',
+        'OU': 'X8NNQ9CYL2',
+        'UID': '6HQ443353U',
+    }
+    assert certificate.subject == expected_subject
+
+
+def test_issuer(certificate):
+    expected_issuer = {
+        'C': 'US',
+        'CN': 'Apple Worldwide Developer Relations Certification Authority',
+        'O': 'Apple Inc.',
+        'OU': 'Apple Worldwide Developer Relations',
+    }
+    assert certificate.issuer == expected_issuer
+
+
+def test_not_before(certificate):
+    assert certificate.not_before == '20191129113745Z'
+
+
+def test_not_after(certificate):
+    assert certificate.not_after == '20201128113745Z'
+
+
+def test_expires_at(certificate):
+    expected_expires_at = datetime(2020, 11, 28, 11, 37, 45, tzinfo=timezone.utc)
+    assert certificate.expires_at == expected_expires_at
+
+
+def test_has_expired(certificate):
+    assert certificate.has_expired is True
+
+
+def test_serial(certificate):
+    assert certificate.serial == 5308349992945343936
+
+
+def test_extensions(certificate):
+    expected_extensions = [
+        'Unknown OID',
+        'authorityInfoAccess',
+        'authorityKeyIdentifier',
+        'basicConstraints',
+        'certificatePolicies',
+        'extendedKeyUsage',
+        'keyUsage',
+        'subjectKeyIdentifier',
+    ]
+    assert sorted(certificate.extensions) == expected_extensions