Added x509.Certificate.self_issued and x509.Certificate.self_signed
diff --git a/asn1crypto/x509.py b/asn1crypto/x509.py
index 1686057..738fce2 100644
--- a/asn1crypto/x509.py
+++ b/asn1crypto/x509.py
@@ -1317,6 +1317,8 @@
_delta_crl_distribution_points = None
_valid_domains = None
_valid_ips = None
+ _self_issued = None
+ _self_signed = None
def _set_extensions(self):
"""
@@ -1828,3 +1830,39 @@
self._valid_ips.append(general_name.native)
return self._valid_ips
+
+ @property
+ def self_issued(self):
+ """
+ :return:
+ A boolean - if the certificate is self-issued, as defined by RFC5280
+ """
+
+ if self._self_issued is None:
+ self._self_issued = False
+ if self.basic_constraints_value and self.basic_constraints_value['ca'].native:
+ self._self_issued = self.subject == self.issuer
+ return self._self_issued
+
+ @property
+ def self_signed(self):
+ """
+ :return:
+ A unicode string of "yes", "no" or "maybe". The "maybe" result will
+ be returned if the certificate does not contain a key identifier
+ extension, but is issued by the subject. In this case the
+ certificate signature will need to be verified using the subject
+ public key to determine a "yes" or "no" answer.
+ """
+
+ if self._self_signed is None:
+ self._self_signed = 'no'
+ if self.self_issued:
+ if self.key_identifier:
+ if not self.authority_key_identifier:
+ self._self_signed = 'yes'
+ elif self.authority_key_identifier == self.key_identifier:
+ self._self_signed = 'yes'
+ else:
+ self._self_signed = 'maybe'
+ return self._self_signed
diff --git a/tests/test_x509.py b/tests/test_x509.py
index 7a16d02..feefbac 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -1357,6 +1357,58 @@
cert = self._load_cert(relative_path)
self.assertEqual(crl_url, cert.valid_ips)
+ #pylint: disable=C0326
+ @staticmethod
+ def self_issued_info():
+ return (
+ ('keys/test-der.crt', True),
+ ('keys/test-inter-der.crt', False),
+ ('keys/test-third-der.crt', False),
+ ('geotrust_certs/GeoTrust_Universal_CA.crt', True),
+ ('geotrust_certs/GeoTrust_Primary_CA.crt', True),
+ ('geotrust_certs/GeoTrust_EV_SSL_CA_-_G4.crt', False),
+ ('geotrust_certs/codex.crt', False),
+ ('lets_encrypt/isrgrootx1.pem', True),
+ ('lets_encrypt/letsencryptauthorityx1.pem', False),
+ ('lets_encrypt/letsencryptauthorityx2.pem', False),
+ ('globalsign_example_keys/IssuingCA-der.cer', False),
+ ('globalsign_example_keys/rootCA.cer', True),
+ ('globalsign_example_keys/SSL1.cer', False),
+ ('globalsign_example_keys/SSL2.cer', False),
+ ('globalsign_example_keys/SSL3.cer', False),
+ )
+
+ @data('self_issued_info')
+ def self_issued(self, relative_path, self_issued):
+ cert = self._load_cert(relative_path)
+ self.assertEqual(self_issued, cert.self_issued)
+
+ #pylint: disable=C0326
+ @staticmethod
+ def self_signed_info():
+ return (
+ ('keys/test-der.crt', 'yes'),
+ ('keys/test-inter-der.crt', 'no'),
+ ('keys/test-third-der.crt', 'no'),
+ ('geotrust_certs/GeoTrust_Universal_CA.crt', 'yes'),
+ ('geotrust_certs/GeoTrust_Primary_CA.crt', 'yes'),
+ ('geotrust_certs/GeoTrust_EV_SSL_CA_-_G4.crt', 'no'),
+ ('geotrust_certs/codex.crt', 'no'),
+ ('lets_encrypt/isrgrootx1.pem', 'yes'),
+ ('lets_encrypt/letsencryptauthorityx1.pem', 'no'),
+ ('lets_encrypt/letsencryptauthorityx2.pem', 'no'),
+ ('globalsign_example_keys/IssuingCA-der.cer', 'no'),
+ ('globalsign_example_keys/rootCA.cer', 'yes'),
+ ('globalsign_example_keys/SSL1.cer', 'no'),
+ ('globalsign_example_keys/SSL2.cer', 'no'),
+ ('globalsign_example_keys/SSL3.cer', 'no'),
+ )
+
+ @data('self_signed_info')
+ def self_signed(self, relative_path, self_signed):
+ cert = self._load_cert(relative_path)
+ self.assertEqual(self_signed, cert.self_signed)
+
def test_parse_certificate(self):
cert = self._load_cert('keys/test-der.crt')