From 881dcd1d58517a9beb131936898e81550148c167 Mon Sep 17 00:00:00 2001 From: Digital Studium Date: Wed, 14 May 2025 18:55:50 +0300 Subject: [PATCH] first commit --- .gitignore | 1 + cert_decoder/main.py | 81 +++++++++++++++++++++++++++++++++++ cert_decoder/requirements.txt | 10 +++++ 3 files changed, 92 insertions(+) create mode 100644 .gitignore create mode 100644 cert_decoder/main.py create mode 100644 cert_decoder/requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21d0b89 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.venv/ diff --git a/cert_decoder/main.py b/cert_decoder/main.py new file mode 100644 index 0000000..f047b90 --- /dev/null +++ b/cert_decoder/main.py @@ -0,0 +1,81 @@ +from flask import Flask, request, render_template_string, redirect, url_for +from cryptography import x509 +from cryptography.hazmat.backends import default_backend + +app = Flask(__name__) + +# Simple HTML Form +HTML_TEMPLATE = """ + + + + + + + + + + + SSL Certificate Decoder - View CN, SAN, Issuer & More + + +

Decode SSL Certificate

+
+

+ +
+ + {% if cert_info %} +

Certificate Information:

+
{{ cert_info }}
+ {% endif %} + + +""" + +def parse_certificate(pem_data): + try: + cert = x509.load_pem_x509_certificate(pem_data.encode(), default_backend()) + except Exception as e: + return f"Invalid certificate: {e}" + + issuer = cert.issuer.get_attributes_for_oid(x509.OID_COMMON_NAME) + subject = cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME) + not_before = cert.not_valid_before + not_after = cert.not_valid_after + serial_number = cert.serial_number + sig_algo = cert.signature_hash_algorithm.name + + # Get SANs + try: + ext = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName) + sans = ext.value.get_values_for_type(x509.DNSName) + except x509.ExtensionNotFound: + sans = [] + + output = f""" +Subject CN: {subject[0].value if subject else 'N/A'} +Issuer CN: {issuer[0].value if issuer else 'N/A'} +Valid From: {not_before} +Valid Until: {not_after} +Serial Number: {serial_number} +Signature Alg: {sig_algo} +SANs: {', '.join(sans) if sans else 'None'} +""" + return output.strip() + +@app.route("/", methods=["GET", "POST"]) +def index(): + if request.method == "POST": + pem_cert = request.form.get("certificate", "").strip() + cert_info = parse_certificate(pem_cert) + # Store result temporarily in session or pass via GET param + return redirect(url_for('index', cert_info=cert_info)) + + # GET Request — show result if available + cert_info = request.args.get('cert_info') + return render_template_string(HTML_TEMPLATE, cert_info=cert_info) + + +if __name__ == "__main__": + app.run(debug=True, port=5000) diff --git a/cert_decoder/requirements.txt b/cert_decoder/requirements.txt new file mode 100644 index 0000000..6ddc584 --- /dev/null +++ b/cert_decoder/requirements.txt @@ -0,0 +1,10 @@ +blinker==1.9.0 +cffi==1.17.1 +click==8.2.0 +cryptography==44.0.3 +Flask==3.1.1 +itsdangerous==2.2.0 +Jinja2==3.1.6 +MarkupSafe==3.0.2 +pycparser==2.22 +Werkzeug==3.1.3