You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
2.9 KiB
Python
108 lines
2.9 KiB
Python
"""
|
|
Script to compare a set of X.509 certificate files
|
|
"""
|
|
import argparse
|
|
import typing
|
|
|
|
from cryptography import x509
|
|
|
|
import helpers
|
|
|
|
DEFAULT_OIDS = [
|
|
x509.OID_BASIC_CONSTRAINTS,
|
|
x509.OID_KEY_USAGE,
|
|
x509.OID_EXTENDED_KEY_USAGE,
|
|
x509.OID_AUTHORITY_KEY_IDENTIFIER,
|
|
x509.OID_SUBJECT_KEY_IDENTIFIER,
|
|
x509.OID_AUTHORITY_KEY_IDENTIFIER,
|
|
x509.OID_AUTHORITY_INFORMATION_ACCESS,
|
|
x509.OID_CRL_DISTRIBUTION_POINTS,
|
|
x509.OID_CERTIFICATE_POLICIES,
|
|
]
|
|
|
|
|
|
def table_line(key, values):
|
|
print(f"| {key} |", " | ".join(values), "|")
|
|
|
|
|
|
def format_duration(cert: x509.Certificate) -> str:
|
|
return f"{cert.not_valid_before} - {cert.not_valid_after} = {(cert.not_valid_after - cert.not_valid_before).days}d"
|
|
|
|
|
|
def compare_certificates(certificates: typing.List[str]):
|
|
parsed = {}
|
|
|
|
for cert_filename in certificates:
|
|
parsed[cert_filename] = helpers.parse_certificate(cert_filename)
|
|
|
|
print("| |", " | ".join([f"`{name}`" for name in certificates]), "|")
|
|
print("|---|" + "---|" * len(certificates))
|
|
table_line("Subject", [parsed[fn].subject.rfc4514_string() for fn in certificates])
|
|
table_line(
|
|
"Issuer",
|
|
[
|
|
parsed[fn].issuer.rfc4514_string(
|
|
attr_name_overrides={
|
|
x509.ObjectIdentifier("1.2.840.113549.1.9.1"): "emailAddress"
|
|
}
|
|
)
|
|
for fn in certificates
|
|
],
|
|
)
|
|
table_line(
|
|
"Public Key algorithm",
|
|
[helpers.format_key_type(parsed[fn]) for fn in certificates],
|
|
)
|
|
table_line(
|
|
"Hash algorithm",
|
|
[helpers.format_hash_algorithm(parsed[fn]) for fn in certificates],
|
|
)
|
|
table_line(
|
|
"Validity duration", [format_duration(parsed[fn]) for fn in certificates]
|
|
)
|
|
|
|
extra_oids = set()
|
|
for cert in certificates:
|
|
for oid in [
|
|
ext.oid for ext in parsed[cert].extensions if ext.oid not in DEFAULT_OIDS
|
|
]:
|
|
extra_oids.add(oid)
|
|
|
|
for oid in DEFAULT_OIDS:
|
|
table_line(
|
|
helpers.extension_label(oid),
|
|
[
|
|
helpers.format_extension(parsed[fn].extensions, oid)
|
|
for fn in certificates
|
|
],
|
|
)
|
|
|
|
for oid in extra_oids:
|
|
table_line(
|
|
helpers.extension_label(oid),
|
|
[
|
|
helpers.format_extension(parsed[fn].extensions, oid)
|
|
for fn in certificates
|
|
],
|
|
)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
prog="compare certs",
|
|
description="compare a certificate to a set of other certificates",
|
|
)
|
|
parser.add_argument("first", help="first certificates")
|
|
parser.add_argument("others", nargs="+", help="other certificates")
|
|
|
|
args = parser.parse_args()
|
|
|
|
cert_list = [args.first]
|
|
cert_list.extend(args.others)
|
|
|
|
compare_certificates(cert_list)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|