Spaces:
Running
Running
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 | |