Search code examples
pythonsslpython-3.6diffie-hellman

Server Side SSL using Diffie-Hellman in Python


I'm trying to set up a socket using Diffie-Hellman SSL, but can't seem find any documentation on how to do this. I notice that SSLContext in Python 3.3+ supports load_dh_params and set_ecdh_curve which suggests that using DH is possible.

I'm fairly new to using SSL so perhaps missing something obvious, but here's the code I'm using:

sock = socket.socket()
sock.bind((HOST, PORT))
sock.listen()
context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS)
context.set_ecdh_curve('prime256v1')
ssock, address = self._server.accept()
ssock= context.wrap_socket(ssock, server_side=True)

When using this code, I get the error:

ssl.SSLError: [SSL: NO_SHARED_CIPHER] no shared cipher

I've tried setting the ciphers like the following:

context.set_ciphers('ECDHE-RSA-AES256-GCM-SHA384')

but all the ciphers I've tried still throw up the same exception.

If anyone could point out where I'm going wrong or provide a working example of using DH SSL, it'd be much appreciated!


Solution

  • A TLS cipher defines the key exchange, the authentication method, the symmetric encryption algorithm and the HMAC. The authentication method in the cipher you explicitly try to use is RSA, i.e. using a certificate with an RSA public key. If you instead use the default cipher set the authentication methods are either RSA or ECDSA.

    Both of these authentication methods need an appropriate certificate on the server side, i.e. with RSA or ECC public key. Since you have not configured any certificates these ciphers can not be used. This means in essence that from the ciphers the client has offered (which commonly also require certificate based authentication) none can be used for the connection, ergo NO_SHARED_CIPHER.

    What you need to do:

    • The recommended way is to setup a certificate on the server which is trusted by the client. See SSLContext.load_cert_chain.
    • Or you could use ciphers which don't require authentication, for example ADH-AES256-GCM-SHA384. Note that you would need to explicitly configure the cipher in the client too since by default TLS stacks don't use ciphers without authentication for security reasons since man in the middle attacks will not be detected this way.