== First impressions of pyOpenSSL [[pyOpenSSL http://pyopenssl.sourceforge.net/]] is a high-level Python wrapper around a subset of the OpenSSL library (to quote it). It was pulled onto my machines recently as part of a Fedora update, and since I'm currently interested in OpenSSL-related things I decided to play around with it to try it out. After writing some basic stuff, I have to say that I like it. It's not entirely documented (and for some things you really want to read the OpenSSL manpages too), but it works fine. It's also nicely simple to use; my test program to connect to a server and extract its SSL certificate is only 40 lines. Here's the gotchas and stuff I know about so far: * despite what the _Connection_ object documentation says about the _.connect()_ method, it just connects the underlying socket. You must then call ((.do_handshake())) to start SSL on the new connection. * end-of-connection raises _ZeroReturnError_ instead of having the connection's _.recv()_ method return a zero-sized result. I imagine this makes sense if you understand the OpenSSL library. * I'm not entirely clear what exactly _.shutdown()_ does; it seems to only tell the other side that you're not going to send more stuff. (I probably need to write a server in [[pyOpenSSL]] to really understand it.) * there seems to be no way to find out the expiry date of an X509 certificate, although _X509_ objects have a function to tell you if they've expired. * The X509 _.digest()_ function's single argument is a string that is the name of the hash you want to use. The available hashes on my Fedora Core 6 machine seem to be be md2, md5, sha, sha1, dss1, and ripemd aka ripemd160. However, the exact list is in the depths of the OpenSSL library, so yours may differ; see the ((EVP_DigestInit)) manpage. * the string values of X509Name objects are almost but not quite the usual '/C=...' form; they have Python repr-style type bits glued on the ends. * some of the in-Python help text is misleading or wrong; trust the PostScript documentation instead, which is pretty good (if you like minimalism). These are pretty much minor concerns, though; the only one that required me to do some serious delving was the _.digest()_ issue. (And I'm coming into this completely ignorant of the underlying OpenSSL library routines, which doesn't help. Advanced usage of [[pyOpenSSL]], like callbacks, clearly requires familiarity with OpenSSL itself.) === Sidebar: a simple example client Here's an example of how you'd use the client side of [[pyOpenSSL]] (without error checking and the like): import socket from OpenSSL import SSL def ding(host, port, msg): s = socket.socket() # TLSv1 chosen more or less arbitrarily cx = SSL.Context(SSL.TLSv1_METHOD) cn = SSL.Connection(cx, s) cn.connect((host, port)) cn.do_handshake() cn.sendall(msg) tl = [] try: while 1: r = cn.recv(8192) tl.append(r) except SSL.ZeroReturnError: pass cn.shutdown() cn.close() return "".join(tl) As far as I can tell from _strace_, the _.recv()_ calls are blocking and this won't spin waiting for network IO.