First impressions of pyOpenSSL
pyOpenSSL 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 theEVP_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.
Comments on this page:
|
|