How to Check Negotiated Cipher Suite in Python
Connect to a TLS server with Python's ssl module and print the negotiated protocol version and cipher suite details.
Python code
19 linesimport ssl
import socket
def get_cipher_suites(hostname, port=443):
context = ssl.create_default_context()
context.set_ciphers("DEFAULT:@SECLEVEL=2")
with socket.create_connection((hostname, port), timeout=5) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
cipher = ssock.cipher()
version = ssock.version()
return version, cipher
if __name__ == "__main__":
version, cipher = get_cipher_suites("www.google.com")
print(f"TLS Version: {version}")
print(f"Negotiated Cipher: {cipher[0]}")
print(f"Protocol: {cipher[1]}")
print(f"Key Exchange Bits: {cipher[2]}")
Output
TLS Version: TLSv1.3
Negotiated Cipher: TLS_AES_256_GCM_SHA384
Protocol: TLSv1.3
Key Exchange Bits: 256
How it works
The ssl.create_default_context() builds a context with secure defaults, including system CA certificates. Calling set_ciphers with DEFAULT:@SECLEVEL=2 ensures only ciphers meeting OpenSSL's security level 2 (112-bit or stronger) are permitted. After wrapping the socket with the TLS context, ssock.cipher() returns a tuple with the cipher name, protocol version, and key exchange bits. ssock.version() gives the TLS protocol version that was actually negotiated. This approach works without extra dependencies, making it easy to audit remote endpoints for weak cipher support.
Common mistakes
- Forgetting the server_hostname argument, which disables SNI and may cause handshake failures.
- Using `ssl.wrap_socket` (deprecated) instead of `context.wrap_socket`.
- Not catching socket.timeout, which can crash the script on unresponsive hosts.
- Assuming the key exchange bits reflect symmetric key strength; they represent the ephemeral key size.
Variations
- Use `cryptography` library’s `ssl` integration to get more detailed cipher info.
- Connect to a local test server with a custom SSL context for controlled testing.
Real-world use cases
- Auditing a server’s TLS configuration during security compliance checks.
- Automatically verifying that endpoints use strong ciphers before enabling client connections.
- Debugging handshake failures caused by unsupported or weak cipher suites on legacy systems.
Sponsored
More from Auth & security at scale
- ACME LetsEncrypt Mock Challenge Server in Python medium
- AES GCM encryption and decryption in Python medium
- Build a Mock OIDC Userinfo Endpoint in Python with Flask easy
- ChaCha20-Poly1305 mock in Python medium
- ECDH key agreement in Python with cryptography medium
- Enforce TLS 1.2 Minimum in Python easy
Keep learning
Related tutorials and quizzes for this topic.