# -*- encoding: utf-8 -*- # requires a recent enough python with idna support in socket # pyopenssl, cryptography and idna from OpenSSL import SSL from cryptography import x509 from cryptography.x509.oid import NameOID import idna from socket import socket from collections import namedtuple HostInfo = namedtuple(field_names='cert hostname peername address', typename='HostInfo') def verify_cert(cert, hostname): # verify notAfter/notBefore, CA trusted, servername/sni/hostname cert.has_expired() # service_identity.pyopenssl.verify_hostname(client_ssl, hostname) # issuer def get_certificate(hostname, port, address): hostname_idna = idna.encode(hostname) sock = socket() try: sock.settimeout(3) sock.connect((hostname, port)) sock.settimeout(None) peername = sock.getpeername() ctx = SSL.Context(SSL.SSLv23_METHOD) # most compatible ctx.check_hostname = False ctx.verify_mode = SSL.VERIFY_NONE sock_ssl = SSL.Connection(ctx, sock) sock_ssl.set_connect_state() sock_ssl.set_tlsext_host_name(hostname_idna) sock_ssl.do_handshake() cert = sock_ssl.get_peer_certificate() crypto_cert = cert.to_cryptography() sock_ssl.close() sock.close() return HostInfo(cert=crypto_cert, peername=peername, hostname=hostname address=address) except: pass def get_alt_names(cert): try: ext = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName) return ext.value.get_values_for_type(x509.DNSName) except x509.ExtensionNotFound: return None def get_common_name(cert): try: names = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME) return names[0].value except x509.ExtensionNotFound: return None def get_issuer(cert): try: names = cert.issuer.get_attributes_for_oid(NameOID.COMMON_NAME) return names[0].value except x509.ExtensionNotFound: return None def print_basic_info(hostinfo): try: s = '''» {peername} « \tcommonName: {commonname} \tSAN: {SAN} \tissuer: {issuer} '''.format( peername=hostinfo.address, commonname=get_common_name(hostinfo.cert), SAN=get_alt_names(hostinfo.cert), issuer=get_issuer(hostinfo.cert) ) print(s) except: print("GG") def check_it_out(hostname, port): hostinfo = get_certificate(hostname, port) print_basic_info(hostinfo) import concurrent.futures if __name__ == '__main__': HOSTS = [] file = open("file.txt", "r").readlines() for i in file: x = str(i).strip().rstrip('/').lstrip('http://').lstrip('https://').split(':') if len(x) == 2: HOSTS.append((x[0], int(x[1]), i)) else: HOSTS.append((x[0], 443, i)) #exit(0) with concurrent.futures.ThreadPoolExecutor(max_workers=4) as e: for hostinfo in e.map(lambda x: get_certificate(x[0], x[1], x[2].strip()), HOSTS): print_basic_info(hostinfo)