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.