<html><body>On 04:30 am, elicriffield@gmail.com wrote:<br /><br />&gt;I try to make the x590 object to feed to CertificateOptions from<br />&gt;t.i.s.Certifcate.loadPEM() but it doesn't like it. I see nowhere in<br />&gt;t.i.ssl to make a PKey object that t.i.s.CertificationOptions() wants.<br /><br />&gt;I've tried t.i.s.ContextFactory() but there is no options for<br />&gt;requiring a client side cert.<br />&gt;t.i.s.ClientContextFactory doesn't seem to have any options to tell it<br />&gt;what cert to use on the client side either, or how to verify the<br />&gt;server cert, I guess thats what t.i.s.CertificationOptions() is for<br />&gt;but it doesn't seem to work as documented.<br /><br />The "right" way to do this (and by "right" I mean the way I intended and used when I originally wrote this code, but never documented in any way) is by using the "PrivateCertificate" object, which represents a paired public/private key, and its (poorly named, and by the way did I mention it's undocumented) "options" method, which creates the CertificateOptions object for you.<br /><br />I can see from your example that you're already expecting the key and certificate to be in the same PEM file (like everyone does) so it could be as easy as this:<br /><br />&#160; &#160; from twisted.internet.ssl import PrivateCertificate<br />&#160; &#160; pc = PrivateCertificate.loadPEM(file('test.cert', r').read())<br />&#160; &#160; ctxFactory = pc.options()<br /><br />although if you want to verify client certificates, options() also takes, as varargs, a tuple of certificate authorities. &#160;However, a private certificate can also fill the role of a public certificate, so you can do:<br /><br />&#160; &#160; ctxFactory = pc.options(pc)<br /><br />to use a self-signed certificate as its own authority.<br /><br />This context factory can be used either for client or server connections, as shown below.<br /><br />If you are doing anything interesting with SSL, you might want to have a look at the source in the file twisted/internet/_sslverify.py, especially the other (undocumented) methods of PrivateCertificate, which implements a bit of CA functionality.<br /><br />&gt;Is there some great documentation out there about how to do this with<br />&gt;twisted.internet.ssl that I'm missing?<br /><br />Nope. &#160;The documentation here is particularly thin, and to make matters work, there are certain operations that are unsupported due to bugs or non-wrapped functions in pyopenssl.<br /><br />Please feel free to file a more specific documentation bug (and feel _double_ free to attach a patch) to add docstrings to _sslverify, and probably a separate bug to add an introductory document.<br /><br />I'm a big fan of complete runnable examples, so here's something to get you started. &#160;Hope that this helps:<br /><br />--- cut here ---<br /><br />from sys import stdout, argv<br /><br />from twisted.python.filepath import FilePath<br />from twisted.python.log import startLogging<br /><br />from twisted.internet.protocol import Protocol, Factory, ClientFactory<br /><br />from twisted.internet import reactor<br />from twisted.internet.ssl import PrivateCertificate<br /><br />class MyProto(Protocol):<br />&#160; &#160; def connectionMade(self):<br />&#160; &#160; &#160; &#160; self.transport.write(self.factory.stuff)<br />&#160; &#160; def dataReceived(self, data):<br />&#160; &#160; &#160; &#160; stdout.write('Received %r\n' % (data,))<br /><br />theCert = PrivateCertificate.loadPEM(file('server.pem','r').read())<br />theOptions = theCert.options(theCert)<br /><br />def server():<br />&#160; &#160; f = Factory()<br />&#160; &#160; f.stuff = 'hello, client'<br />&#160; &#160; f.protocol = MyProto<br />&#160; &#160; reactor.listenSSL(7080, f, theOptions)<br /><br />def client():<br />&#160; &#160; f = ClientFactory()<br />&#160; &#160; f.stuff = 'hello, server'<br />&#160; &#160; f.protocol = MyProto<br />&#160; &#160; reactor.connectSSL('localhost', 7080, f, theOptions)<br /><br />def main():<br />&#160; &#160; startLogging(stdout)<br />&#160; &#160; if argv[1] == 'server':<br />&#160; &#160; &#160; &#160; server()<br />&#160; &#160; else:<br />&#160; &#160; &#160; &#160; client()<br />&#160; &#160; reactor.run()<br /><br />if __name__ == '__main__':<br />&#160; &#160; main()<br /></body></html>