Add CA chain and fingerprints

This commit is contained in:
Scott Wallace 2024-02-27 15:43:51 +00:00
parent e1f7fa0989
commit 575bceec25
Signed by: scott
GPG key ID: AA742FDC5AFE2A72
2 changed files with 49 additions and 3 deletions

View file

@ -6,9 +6,11 @@ import argparse
import socket
import ssl
import sys
import urllib.error
from typing import Any
from urllib.parse import urlparse
from cert_chain_resolver.api import CertificateChain, resolve
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
@ -17,6 +19,21 @@ from tabulate import tabulate
SAN_GROUPING = 4
def format_fingerprint(fingerprint: bytes | str) -> str:
"""
Print a fingerprint as a colon-separated hex string
Args:
fingerprint (bytes | str): fingerprint to format
Returns:
str: formatted fingerprint
"""
if isinstance(fingerprint, str):
fingerprint = bytearray.fromhex(fingerprint)
return ":".join([format(i, "02x") for i in fingerprint])
def display_error(
site: str,
error: Any = None,
@ -53,6 +70,10 @@ if __name__ == "__main__":
"""
args = parseargs()
url = args.site
if "://" not in url:
url = f"https://{url}"
parts = urlparse(args.site, scheme="https")
if not parts.netloc:
@ -70,7 +91,15 @@ if __name__ == "__main__":
try:
pem_data = ssl.get_server_certificate(
(parts.hostname, parts.port),
timeout=10,
).encode("utf-8")
cert_chain = CertificateChain()
try:
cert_chain = resolve(pem_data)
except urllib.error.URLError:
pass
except (
ConnectionRefusedError,
ssl.CertificateError,
@ -113,11 +142,28 @@ if __name__ == "__main__":
["Valid to", cert.not_valid_after_utc],
["Issuer", cert.issuer.rfc4514_string()],
[
"SHA1 fingerprint",
":".join([format(i, "02x") for i in cert.fingerprint(hashes.SHA1())]),
"Fingerprint",
f"{format_fingerprint(cert.fingerprint(hashes.SHA1()))} (SHA1)",
],
]
if cert_chain:
table.append(
[
"CA chain",
"\n".join(
[
f"{cert.common_name} "
f"(Issuer: {cert.issuer})\n"
"Fingerprint: "
f"{format_fingerprint(cert.get_fingerprint(hashes.SHA1))} (SHA1)"
for cert in list(cert_chain.intermediates)
+ [cert_chain.root]
]
),
]
)
print(tabulate(table, tablefmt="plain"))
return 0

View file

@ -10,7 +10,7 @@ description = "Show TLS certificate details for a given endpoint"
keywords = ["tls", "certificate", "python"]
classifiers = ["Programming Language :: Python :: 3"]
readme = "README.md"
dependencies = ["cryptography", "tabulate"]
dependencies = ["cert-chain-resolver", "cryptography", "tabulate"]
requires-python = ">=3.11"
[project.urls]