Search code examples
pythonapacheopensslpyopenssl

pyOpenSSL Cipher List failure


In Apache, I'm successfully using the following OpenSSL cipher settings:

SSLHonorCipherOrder on
SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM \
                EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 \
                EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 \
                EECDH EDH+aRSA \
                !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"

I'm trying to emulate that in a python (Twisted) server, but the server won't serve any pages with a comparable cipher list specified. What am I doing wrong? Here's the python (well in essence...)

     from OpenSSL import SSL
....
     httpSslContext = ssl.DefaultOpenSSLContextFactory(...)
     ctx = httpSslContext.getContext()                
     ctx.set_options( SSL.OP_CIPHER_SERVER_PREFERENCE )                 
     ctx.set_cipher_list( "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:EDH+aRSA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4" )   
...

It works if I change the cipher list to something simple like "RC4-SHA", or even something a bit more complicated like "DEFAULT:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4". I set some other options, e.g. the excepted protocols, but I don't know if that relevant...

Note that this same cipher list is used here: Python Paste SSL server with TLSv1.2 and Forward Secrecy

I'm trying to achieve the same results, for the same reason, but running into some issues. I'm wondering now if there is pyOpenssl version discrepancy? Are EECDH ciphers not allowed perhaps? I can't use ctx.set_tmp_ecdh() either...


Solution

  • The problem was indeed the inability to use context.set_tmp_ecdh(), which was due to not having a new version of pyOpenSSL installed. See: Why is context.set_tmp_ecdh() not defined in pyOpenSSL?. Resolving that fixed the problem.

    When you specify a cypher list, that is not literally the ciphers which end up being implemented. connection.get_cipher_list() (which I called in a context.set_info_callback() function) will reveal the actual results when everything else is taken into account.

    Older versions of pyOpenSSL couldn't use EECDH (elliptical curve) ciphers. As such, they were not available and my preferred cipher list didn't work on some browsers.

    Apache, on the other hand didn't have this problem and allowed the use of those ciphers out of the box.