File size: 3,909 Bytes
26bf868
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0c34587
 
 
 
 
 
 
 
 
26bf868
0c34587
 
26bf868
 
 
 
 
 
 
 
 
 
 
 
 
 
0c34587
26bf868
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# 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()