SSL-Checker / app.py
CultriX's picture
Update app.py
0c34587 verified
# 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()