# Import necessary libraries import gradio as gr import ssl import socket import logging import json from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from datetime import datetime, timezone def setup_logging(): logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") file_handler = logging.FileHandler("ssl_check.log") file_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")) logging.getLogger().addHandler(file_handler) setup_logging() def get_fingerprints(cert): return { "SHA-256": cert.fingerprint(hashes.SHA256()).hex(), "SHA-1": cert.fingerprint(hashes.SHA1()).hex(), "MD5": cert.fingerprint(hashes.MD5()).hex(), } def get_san_list(cert): try: san_extension = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName) return san_extension.value.get_values_for_type(x509.DNSName) except x509.ExtensionNotFound: return [] def extract_certificate_details(cert): """ Extract key details from the certificate, including issuer, subject, fingerprints, and validity. Args: cert (x509.Certificate): The certificate object. Returns: dict: Dictionary containing certificate details. """ now = datetime.now(timezone.utc) expiry_date = cert.not_valid_after.replace(tzinfo=timezone.utc) not_before = cert.not_valid_before.replace(tzinfo=timezone.utc) days_remaining = (expiry_date - now).days fingerprints = get_fingerprints(cert) san_list = get_san_list(cert) return { "expiry_date": expiry_date.isoformat(), "not_before": not_before.isoformat(), "days_remaining": days_remaining, "fingerprints": fingerprints, "issuer": {attr.oid._name: attr.value for attr in cert.issuer}, "subject": {attr.oid._name: attr.value for attr in cert.subject}, "san_list": san_list, } def establish_tls_connection(hostname, port, timeout): context = ssl.create_default_context() context.check_hostname = False context.verify_mode = ssl.CERT_REQUIRED with socket.create_connection((hostname, port), timeout=timeout) as sock: with context.wrap_socket(sock, server_hostname=hostname) as tls_conn: peer_cert_bin = tls_conn.getpeercert(binary_form=True) if not peer_cert_bin: raise ValueError("Peer certificate is missing.") return peer_cert_bin, tls_conn.version() def check_certificate(hostname, port, timeout): try: peer_cert_bin, tls_version = establish_tls_connection(hostname, port, timeout) cert = x509.load_der_x509_certificate(peer_cert_bin, default_backend()) cert_details = extract_certificate_details(cert) cert_details["tls_version"] = tls_version return json.dumps(cert_details, indent=2) except Exception as e: logging.error(f"Error checking certificate: {e}") return f"Error: {e}" def gradio_interface(hostname, port, timeout): try: port = int(port) timeout = int(timeout) return check_certificate(hostname, port, timeout) except ValueError: return "Port and timeout must be integers." def create_interface(): iface = gr.Interface( fn=gradio_interface, inputs=[ gr.Textbox(label="Hostname", placeholder="Enter server hostname", lines=1), gr.Number(label="Port", value=443), gr.Number(label="Timeout (seconds)", value=10), ], outputs=gr.Textbox(label="Certificate Details"), title="SSL Certificate Checker", description="Check the SSL certificate details of a server.", ) return iface if __name__ == "__main__": iface = create_interface() iface.launch()