== Using Python to find out what cipher a SSL server is using I have a [[new-found interest ../tech/SSLForwardSecrecy]] in finding out what ciphers various SSL servers around here are using in some easy and convenient way. Doing this in Perl is easy (there's an example [[here http://seclists.org/basics/2003/Jun/0702.html]]), but I prefer Python. I'd normally use [[pyOpenSSL http://pyopenssl.sourceforge.net/]], [[my favorite Python OpenSSL module PyOpenSSLComments]], but unfortunately it doesn't (currently) have an interface to the necessary 'get the connection's cipher' OpenSSL routine, and there's no visible substitute for it. (While the _[[.get_cipher_list()|]]_ method of _Connection_ objects looks tempting, I discovered through some experimentation that it doesn't return anything like the list of ciphers that are common between the server and the client.) However, all is not lost; it turns out that the commonly available [[M2Crypto module http://chandlerproject.org/bin/view/Projects/MeTooCrypto]] does have enough functionality to do this. In fact, it's pretty easy, and so here is sample code to do it (omitting error checking, as usual): from M2Crypto import SSL def printcipher(host, port): ctx = SSL.Context('tlsv1') s = SSL.Connection(ctx) # No, really, all I care is that you successfully # negotiated SSL, especially as some of your checks # are broken. s.postConnectionCheck = None s.connect((host, port)) # The space at the end is [sic] if s.get_state() == "SSLOK ": c = s.get_cipher() cp = c.name() print "Cipher %s, %d bits" % (cp, len(c)) if cp.startswith("DHE-") or cp.startswith("EDH-"): print "forward secrecy: yes" else: print "forward secrecy: probably not" s.close() This code works for protocols that start SSL/TLS immediately on connection, such as https or imaps. Extension to protocols that have a plaintext conversation and then start TLS (such as ESTMP with STARTTLS) is left as an exercise for the sufficiently interested. I believe but am not sure that there is no point in asking for anything except TLS v1; the OpenSSL _ciphers(1)_ manpage suggests that SSLv3 and TLSv1 have the same set of ciphers. (Presumably this is TLS v1.0.) (Note that M2Crypto is pretty under-documented; reading the source is not so much recommended as required. Fortunately it comes with a large set of examples.)