decode_ssl / decode.py
raannakasturi's picture
Update decode.py
d549d68 verified
raw
history blame
6.82 kB
import os
import subprocess
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
from cryptography.hazmat.primitives.asymmetric import ec, rsa
from datetime import datetime
import pytz
def get_date(date):
date = datetime.fromisoformat(date)
timezone = pytz.timezone('Asia/Kolkata')
local_datetime = date.astimezone(timezone)
formatted_date = local_datetime.strftime('%d %B, %Y %H:%M:%S %z')
day = local_datetime.day
ordinal_suffix = 'th' if 4 <= day <= 20 else {1: 'st', 2: 'nd', 3: 'rd'}.get(day % 10, 'th')
formatted_date_with_suffix = formatted_date.replace(f"{day}", f"{day}{ordinal_suffix}")
return formatted_date_with_suffix
def check_expiry(date):
date = datetime.fromisoformat(date)
timezone = pytz.timezone('Asia/Kolkata')
current_date = datetime.now(timezone)
days_left = (date - current_date).days
if days_left > 0:
return f"No ({days_left} days till expiration)"
else:
return f"Yes ({abs(days_left)} days since expired)"
def get_key_data(public_key):
if isinstance(public_key, ec.EllipticCurvePublicKey):
public_key_curve = public_key.curve.name
public_key_size = public_key.curve.key_size
data = {
"type": f"ECDSA ({public_key_curve})",
"size": f"{public_key_size} bits"
}
elif isinstance(public_key, rsa.RSAPublicKey):
public_key_size = public_key.key_size
data = {
"type": "RSA",
"size": f"{public_key_size} bits"
}
else:
data = {
"type": "Unknown",
"size": "Unknown"
}
return data
def general_info(cert, public_key):
common_name = cert.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)[0].value
print(common_name)
sans = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName).value.get_values_for_type(x509.DNSName)
not_valid_after = get_date(str(cert.not_valid_after_utc))
not_valid_before = get_date(str(cert.not_valid_before_utc))
expiry = check_expiry(str(cert.not_valid_after_utc))
key_data = get_key_data(public_key)
signature_algorithm = cert.signature_algorithm_oid._name
serial_number = f"{cert.serial_number} ({hex(cert.serial_number)})"
gen_info = {
"common_name": common_name,
"sans": sans,
"not_valid_after": not_valid_after,
"not_valid_before": not_valid_before,
"expiry": expiry,
"key_data": key_data,
"signature_algorithm": signature_algorithm,
"serial_number": serial_number
}
return gen_info
def issuer_info(cert):
issuer = None; organization = None; country = None
issuer = cert.issuer.get_attributes_for_oid(x509.NameOID.COMMON_NAME)[0].value
organization = cert.issuer.get_attributes_for_oid(x509.NameOID.ORGANIZATION_NAME)[0].value
country = cert.issuer.get_attributes_for_oid(x509.NameOID.COUNTRY_NAME)[0].value
return {
"issuer": issuer,
"organization": organization,
"country": country
}
def extenstions_data(cert):
authorityinfo = None; ocsp_url = None; ca_issuer_url = None; subject_alt_name = None
if (tempdata1 := cert.extensions.get_extension_for_oid(x509.OID_AUTHORITY_KEY_IDENTIFIER).value.key_identifier):
authorityKeyIdentifier = ':'.join(f'{b:02X}' for b in tempdata1)
else:
authorityKeyIdentifier = None
if (subject := cert.extensions.get_extension_for_oid(x509.OID_SUBJECT_KEY_IDENTIFIER).value.digest):
subjectKeyIdentifier = ':'.join(f'{b:02X}' for b in subject)
else:
subjectKeyIdentifier = None
if (key_usage := cert.extensions.get_extension_for_oid(x509.OID_KEY_USAGE).value):
key_usage_info = list(vars(key_usage).items())
key_usage_data =[]
for item in key_usage_info:
key_usage_data.append(f"{item[0][1:]} : {item[1]}")
key_usage_data = key_usage_data
else:
key_usage_data = None
if (ext_key_usage := cert.extensions.get_extension_for_oid(x509.OID_EXTENDED_KEY_USAGE).value):
ext_key_usage_data = [oid._name for oid in ext_key_usage]
else:
ext_key_usage_data = None
crl_distribution_points = []
try:
crl_extension = cert.extensions.get_extension_for_oid(x509.OID_CRL_DISTRIBUTION_POINTS)
for distribution_point in crl_extension.value:
# Extracting the full names (URIs)
if distribution_point.full_name:
uris = [name.value for name in distribution_point.full_name]
crl_distribution_points.extend(uris)
except x509.ExtensionNotFound:
crl_distribution_points.append("No CRL Distribution Points extension")
authorityinfo = cert.extensions.get_extension_for_oid(x509.OID_AUTHORITY_INFORMATION_ACCESS).value
ocsp_url = authorityinfo[0].access_location.value
ca_issuer_url = authorityinfo[1].access_location.value
authority_info_data = {
"ocsp_url": ocsp_url,
"ca_issuer_url": ca_issuer_url
}
subject_alt_name = cert.extensions.get_extension_for_oid(x509.OID_SUBJECT_ALTERNATIVE_NAME).value.get_values_for_type(x509.DNSName)
return {
"authorityKeyIdentifier": authorityKeyIdentifier,
"subjectKeyIdentifier": subjectKeyIdentifier,
"key_usage": key_usage_data,
"extended_key_usage": ext_key_usage_data,
"crl_distribution_points": crl_distribution_points,
"authority_info": authority_info_data,
"subject_alt_name": subject_alt_name
}
def get_openssl_data(cert_file):
result1 = subprocess.run(["openssl", "x509", "-in", cert_file, "-text", "-noout"], capture_output=True, text=True)
result2 = subprocess.run(['openssl', 'asn1parse', '-in', cert_file], capture_output=True, text=True)
data = {
'raw_openssl_data': result1.stdout,
'openssl_asn1parse_data': result2.stdout
}
return data
def decode_ssl_certificate(cert):
subject = cert.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)[0].value
with open(f'{subject}.pem', 'wb') as cert_file:
cert_file.write(cert.public_bytes(Encoding.PEM))
public_key = cert.public_key()
general_info_data = general_info(cert, public_key)
issuer_info_data = issuer_info(cert)
extensions_data_data = extenstions_data(cert)
raw_openssl_data = get_openssl_data(f'{subject}.pem')
os.remove(f'{subject}.pem')
data = {
"general_info": general_info_data,
"issuer_info": issuer_info_data,
"extensions_data": extensions_data_data,
"raw_openssl_data": raw_openssl_data
}
return data