# Author: Kerry Cordero
# Version: 1.0.0
# Description: This script prompts for domain and gets the TLS version for that domain along with Cipher Suites
import ssl
import socket
import warnings
from termcolor import colored
from prettytable import PrettyTable
# Suppress deprecation warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
# Define a list of OpenSSL-style cipher suites
CIPHER_SUITES = [
'DHE-RSA-AES128-GCM-SHA256',
'DHE-RSA-AES256-GCM-SHA384',
'ECDHE-RSA-AES128-GCM-SHA256',
'ECDHE-RSA-AES256-GCM-SHA384',
'ECDHE-RSA-CHACHA20-POLY1305',
'AES128-GCM-SHA256',
'AES256-GCM-SHA384',
'DHE-RSA-AES256-SHA256',
'ECDHE-RSA-AES128-SHA256',
'AES256-GCM-SHA384',
'AES128-GCM-SHA256',
'AES256-SHA256',
'AES128-SHA256'
# You can add more cipher suites here...
]
# Define TLS versions
TLS_VERSIONS = {
"TLSv1.0": ssl.PROTOCOL_TLSv1,
"TLSv1.1": ssl.PROTOCOL_TLSv1_1,
"TLSv1.2": ssl.PROTOCOL_TLSv1_2,
"TLSv1.3": ssl.PROTOCOL_TLS
}
def check_cipher_suite_support(fqdn, port, cipher_suite, tls_version):
context = ssl.SSLContext(tls_version)
context.verify_mode = ssl.CERT_NONE
try:
context.set_ciphers(cipher_suite)
except ssl.SSLError:
# This can occur if the cipher suite is not compatible with the chosen TLS version
return False
try:
with socket.create_connection((fqdn, port)) as sock:
with context.wrap_socket(sock, server_hostname=fqdn) as ssock:
return True
except Exception as e:
return False
def main():
fqdn = input("Enter the FQDN: ")
port = 443 # default port for HTTPS, change if necessary
print(f"\nScanning {fqdn} for supported cipher suites...\n")
# Create a table with TLS versions as columns
table = PrettyTable()
table.field_names = ["Cipher Suites"] + list(TLS_VERSIONS.keys())
# Fill the table with cipher suite support information
for cipher_suite in CIPHER_SUITES:
row = [cipher_suite]
for tls_version_name, tls_version_protocol in TLS_VERSIONS.items():
is_supported = check_cipher_suite_support(fqdn, port, cipher_suite, tls_version_protocol)
status = colored('✔️', 'green') if is_supported else colored('❌', 'red')
row.append(status)
table.add_row(row)
print(table)
if __name__ == "__main__":
main()
I received an email from a Vendor stating they will no longer support some older 1.2 Cipher Suites and listed the Cipher suites they support:
The following TLSv1.3 cipher suites will be supported (suites in server-preferred order).
TLS_AES_128_GCM_SHA256 (0x1301)
TLS_AES_256_GCM_SHA384 (0x1302)
The following TLSv1.2 cipher suites will be supported (suites in server-preferred order).
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
The following TLSv1.2 cipher suites will no longer be supported.
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
TLS_RSA_WITH_AES_128_GCM_SHA256 (0x9c)
TLS_RSA_WITH_AES_256_GCM_SHA384 (0x9d)
TLS_RSA_WITH_AES_128_CBC_SHA (0x2f)
TLS_RSA_WITH_AES_128_CBC_SHA256 (0x3c)
TLS_RSA_WITH_AES_256_CBC_SHA (0x35)
TLS_RSA_WITH_AES_256_CBC_SHA256 (0x3d)
In cases like this, you can just scan for those cipher suites:
CIPHER_SUITES = [
'AES_128_GCM_SHA256', # TLSv1.3
'AES_256_GCM_SHA384', # TLSv1.3
'ECDHE_RSA_WITH_AES_256_GCM_SHA384', # TLSv1.2
'ECDHE_RSA_WITH_AES_128_GCM_SHA256', # TLSv1.2
'ECDHE_RSA_WITH_AES_256_CBC_SHA384', # TLSv1.2 (less preferred due to CBC mode)
'ECDHE_RSA_WITH_AES_128_CBC_SHA256' # TLSv1.2 (less preferred due to CBC mode)
]