There doesn't appear to be an easy way to fix this on python 2.7. Internally, gevent.server
uses the python ssl
module which calls the OpenSSL library from C. The _ssl.sslwrap()
function creates a new SSLContext for each call and this is why you are prompted for the key passphrase each time a connection is made.
Twisted uses pyOpenSSL instead of the ssl
module. In pyOpenSSL you create your SSLContext first and that single context is used each time a connection is made. Thus you are only prompted for the passphrase once when using Twisted.
Python 3.2 adds an ssl.SSLContext
class with a wrap_socket()
method. If you were on this version or later then you could patch the gevent code to work more like Twisted, i.e. use a single SSLContext and replace the call to _ssl.sslwrap()
with a call to the wrap_socket()
method. It doesn't appear that gevent is ported to python3, though.
You could offload SSL handling by gevent by placing an SSL proxy in front so incoming SSL connections to a public port are proxied to your gevent server on an unencrypted internal port. You could write your own proxy with Twisted or use a dedicated proxy like stunnel. However, this might negate some or all of the reasons you wanted to use gevent in the first place.
You could patch your _ssl
module either to cache SSLContexts or to use another way of accepting the passphrase. _ssl
in python 2.7 uses the default passphrase callback, which interactively prompts to enter the passphrase. This wouldn't be that difficult, but it requires that you know at least a bit of C, the python C API, and the OpenSSL API, plus you would have to build and override the module everywhere you deploy.
You could patch gevent with your own code to wrap a socket with SSL. This can be done entirely in python with a library like pyOpenSSL, but getting it right is probably a fair amount of work.
Finally, you could just use an unencrypted key. Perhaps putting the key on a RAM disk or on an encrypted file system (or both) would address whatever security requirements you have.