Skip to content

Instantly share code, notes, and snippets.

@recalde
Last active April 4, 2025 11:37
Show Gist options
  • Save recalde/6253986f2ae304dc3a8d19ad33a48139 to your computer and use it in GitHub Desktop.
Save recalde/6253986f2ae304dc3a8d19ad33a48139 to your computer and use it in GitHub Desktop.
Certificate Check
import ssl
import socket
import requests
from urllib.parse import urljoin
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from bs4 import BeautifulSoup
import hashlib
def fetch_ssl_chain(domain, port=443):
certs = []
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE # Accept self-signed certs
with socket.create_connection((domain, port)) as sock:
with context.wrap_socket(sock, server_hostname=domain) as ssock:
# Get the peer certificate in DER form
der_cert = ssock.getpeercert(binary_form=True)
pem_cert = ssl.DER_cert_to_PEM_cert(der_cert)
cert = x509.load_pem_x509_certificate(pem_cert.encode(), default_backend())
certs.append(cert)
# Python 3.11+ can access full chain with get_verified_chain()
if hasattr(ssock, "get_verified_chain"):
try:
chain = ssock.get_verified_chain()
for chain_cert in chain:
der = chain_cert.public_bytes(encoding=ssl.Encoding.DER)
pem = ssl.DER_cert_to_PEM_cert(der)
xcert = x509.load_pem_x509_certificate(pem.encode(), default_backend())
certs.append(xcert)
except Exception:
pass
return certs
def list_remote_cert_files(base_url):
response = requests.get(base_url)
soup = BeautifulSoup(response.text, "html.parser")
cert_files = []
for link in soup.find_all("a"):
href = link.get("href")
if href and (href.endswith(".crt") or href.endswith(".pem")):
cert_files.append(urljoin(base_url, href))
return cert_files
def load_remote_cert(cert_url):
response = requests.get(cert_url)
content = response.content
try:
return x509.load_pem_x509_certificate(content, default_backend())
except Exception:
try:
return x509.load_der_x509_certificate(content, default_backend())
except Exception as e:
print(f"Failed to parse cert from {cert_url}: {e}")
return None
def cert_fingerprint(cert):
return cert.fingerprint(hashlib.sha256())
def main():
domain = "example.com" # <-- your target domain
cert_dir_url = "http://example.com/certs/" # <-- your cert directory URL
print(f"Fetching SSL certificate chain for {domain}...")
domain_certs = fetch_ssl_chain(domain)
domain_fingerprints = {cert_fingerprint(c) for c in domain_certs}
print(f"\nChecking remote certs at {cert_dir_url}...\n")
cert_files = list_remote_cert_files(cert_dir_url)
for cert_url in cert_files:
cert = load_remote_cert(cert_url)
if cert is None:
continue
remote_fp = cert_fingerprint(cert)
match = remote_fp in domain_fingerprints
print(f"{cert_url} => Match: {match}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment