πŸ› οΈToolsShed

SSL Certificate Decoder

Parse and decode PEM-format SSL/TLS certificates.

Frequently Asked Questions

Code Implementation

from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from datetime import datetime, timezone
import base64, textwrap

def decode_pem_certificate(pem: str) -> dict:
    cert = x509.load_pem_x509_certificate(pem.encode(), default_backend())
    now  = datetime.now(timezone.utc)

    # Subject / Issuer fields
    def dn(name) -> dict:
        return {attr.oid._name: attr.value for attr in name}

    # Subject Alternative Names
    try:
        san_ext = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName)
        san = san_ext.value.get_values_for_type(x509.DNSName)
    except x509.ExtensionNotFound:
        san = []

    # Key usage
    try:
        ku = cert.extensions.get_extension_for_class(x509.KeyUsage).value
        key_usage = [
            name for name, ok in [
                ("digitalSignature", ku.digital_signature),
                ("keyEncipherment", ku.key_encipherment),
                ("keyCertSign", ku.key_cert_sign),
                ("cRLSign", ku.crl_sign),
            ] if ok
        ]
    except Exception:
        key_usage = []

    return {
        "subject":          dn(cert.subject),
        "issuer":           dn(cert.issuer),
        "serial":           hex(cert.serial_number),
        "not_before":       cert.not_valid_before_utc.isoformat(),
        "not_after":        cert.not_valid_after_utc.isoformat(),
        "is_expired":       cert.not_valid_after_utc < now,
        "days_remaining":   (cert.not_valid_after_utc - now).days,
        "signature_alg":    cert.signature_hash_algorithm.name,
        "public_key_type":  cert.public_key().__class__.__name__,
        "san":              san,
        "key_usage":        key_usage,
        "is_ca":            cert.extensions.get_extension_for_class(
                                x509.BasicConstraints
                            ).value.ca if True else False,
    }


if __name__ == "__main__":
    import sys, json
    pem = open(sys.argv[1]).read() if len(sys.argv) > 1 else ""
    if pem:
        info = decode_pem_certificate(pem)
        print(json.dumps(info, indent=2))

Comments & Feedback

Comments are powered by Giscus. Sign in with GitHub to leave a comment.