Created
May 15, 2024 01:40
-
-
Save zerolagtime/164c8899e04cdfee592a370ad446c15d to your computer and use it in GitHub Desktop.
Python to analyze a servers X.509 certificate chain - requires packages and libopenssl.do
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Fetching certificate chain for: untrusted-root.badssl.com | |
0: Subject: <Name(C=US,ST=California,L=San Francisco,O=BadSSL,CN=*.badssl.com)> | |
0: Issuer: <Name(C=US,ST=California,L=San Francisco,O=BadSSL,CN=BadSSL Untrusted Root Certificate Authority)> | |
0: Serial Number: 16983658469221716870 | |
0: Validity: From 2024-02-21 21:28:32+00:00 to 2026-02-20 21:28:32+00:00 | |
{idx}: Extensions: | |
0.0: basicConstraints: <BasicConstraints(ca=False, path_length=None)> | |
0.1: subjectAltName: <SubjectAlternativeName(<GeneralNames([<DNSName(value='*.badssl.com')>, <DNSName(value='badssl.com')>])>)> | |
1: Subject: <Name(C=US,ST=California,L=San Francisco,O=BadSSL,CN=BadSSL Untrusted Root Certificate Authority)> | |
1: Issuer: <Name(C=US,ST=California,L=San Francisco,O=BadSSL,CN=BadSSL Untrusted Root Certificate Authority)> | |
1: Serial Number: 10926010850294966525 | |
1: Validity: From 2016-07-07 06:31:35+00:00 to 2036-07-02 06:31:35+00:00 | |
{idx}: Extensions: | |
1.0: subjectKeyIdentifier: <SubjectKeyIdentifier(digest=b'o\xc7\x83sI\xb5\xa7c\xffu\xdemn\xfe\xed\xfb\x97\xa3,\x00')> | |
1.1: authorityKeyIdentifier: <AuthorityKeyIdentifier(key_identifier=b'o\xc7\x83sI\xb5\xa7c\xffu\xdemn\xfe\xed\xfb\x97\xa3,\x00', authority_cert_issuer=[<DirectoryName(value=<Name(C=US,ST=California,L=San Francisco,O=BadSSL,CN=BadSSL Untrusted Root Certificate Authority)>)>], authority_cert_serial_number=10926010850294966525)> | |
1.2: basicConstraints: <BasicConstraints(ca=True, path_length=None)> | |
1.3: keyUsage: <KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=False, decipher_only=False)> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import socket | |
import sys | |
import OpenSSL | |
from OpenSSL import SSL | |
from cryptography import x509 | |
from cryptography.hazmat.backends import default_backend | |
def get_certificate_chain(hostname, port=443): | |
# Create a context with SSL method | |
context = SSL.Context(SSL.SSLv23_METHOD) | |
# Create a socket and wrap it in an SSL connection | |
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
connection = SSL.Connection(context, sock) | |
connection.set_tlsext_host_name(hostname.encode()) | |
connection.connect((hostname, port)) | |
connection.do_handshake() | |
# Get the certificate chain | |
chain = connection.get_peer_cert_chain() | |
connection.close() | |
return chain | |
def parse_certificates(chain): | |
for idx,openssl_cert in enumerate(chain): | |
# Convert OpenSSL certificate to DER format | |
der_cert = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_ASN1, openssl_cert) | |
# Load DER formatted certificate using cryptography | |
cert = x509.load_der_x509_certificate(der_cert, default_backend()) | |
# Extract various details from the certificate | |
print(f"{idx}: Subject: {cert.subject}") | |
print(f"{idx}: Issuer: {cert.issuer}") | |
print(f"{idx}: Serial Number: {cert.serial_number}") | |
print(f"{idx}: Validity: From {cert.not_valid_before_utc} to {cert.not_valid_after_utc}") | |
print("{idx}: Extensions:") | |
for subidx, ext in enumerate(cert.extensions): | |
print(f"{idx}.{subidx}: {ext.oid._name if ext.oid._name else ext.oid.dotted_string}: {ext.value}") | |
print() | |
def main(): | |
hostname = sys.argv[1] if len(sys.argv)>1 and sys.argv[1] \ | |
else "example.com" | |
print(f"Fetching certificate chain for: {hostname}") | |
chain = get_certificate_chain(hostname) | |
parse_certificates(chain) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cffi==1.16.0 | |
cryptography==42.0.7 | |
pycparser==2.22 | |
pyOpenSSL==24.1.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment