[Twisted-Python] twisted echo ssl client with .p12

Glyph glyph at twistedmatrix.com
Thu Mar 19 23:25:10 MDT 2015


> On Mar 19, 2015, at 8:36 AM, Louis D. Burr <ldanielburr at me.com> wrote:
> 
> Hi Timothy,
> 
>> On Mar 19, 2015, at 9:56 AM, Timothy Gallagher <timothy.gallagher at nuspire.com <mailto:timothy.gallagher at nuspire.com>> wrote:
>> 
>> Hello all,
>> I have a project that requires client server with ssl/tls including client certificate authentication.  Also the a requirement is that the client needs to use a .p12 file to house its keys.  I have the server part and client part down except I cannot find any code examples using a .p12 file to get the certificates.  Can this be done without having to hack into the ssl.ClientConextFactory?
> 
> Maybe http://stackoverflow.com/questions/6345786/python-reading-a-pkcs12-certificate-with-pyopenssl-crypto <http://stackoverflow.com/questions/6345786/python-reading-a-pkcs12-certificate-with-pyopenssl-crypto> will be useful to you.  Twisted uses pyopenssl under the covers, so the solution exarkun posted to StackOverflow should be applicable.
> 
> Hope this helps,
> 
> - L. Daniel Burr

You definitely shouldn't use ssl.ClientContextFactory.  It doesn't verify certificates, or provide any authentication of the server.  We should really remove and deprecate it :-\.

You should use ssl.optionsForClientTLS, and you should build it like this:

import getpass

from OpenSSL.crypto import load_pkcs12
from twisted.internet.ssl import (
    PrivateCertificate, KeyPair, Certificate, optionsForClientTLS
)

from twisted.internet.protocol import Factory, Protocol
from twisted.internet.endpoints import SSL4ClientEndpoint
from twisted.internet.defer import inlineCallbacks, Deferred
from twisted.internet.task import react

@inlineCallbacks
def main(reactor, p12file, host, port=443):
    host = host.decode("utf-8")
    port = int(port)
    with open(p12file) as f:
        pkcs12 = load_pkcs12(f.read(), getpass.getpass())
        publicCertificate = Certificate(pkcs12.get_certificate())
        privateKey = KeyPair(pkcs12.get_privatekey())
        privateCertificate = PrivateCertificate.fromCertificateAndKeyPair(
            publicCertificate, privateKey
        )
    contextFactory = optionsForClientTLS(host,
                                         clientCertificate=privateCertificate)
    endpoint = SSL4ClientEndpoint(reactor, host, port, contextFactory)
    x = Deferred()
    class it(Protocol, object):
        def connectionMade(self):
            self.transport.write(b"GET / HTTP/1.1\r\n\r\n")
        def dataReceived(self, data):
            x.callback(Certificate.peerFromTransport(self.transport))
            self.transport.abortConnection()
    yield endpoint.connect(Factory.forProtocol(it))
    cert = yield x
    print(cert)

from sys import argv
react(main, argv[1:])

Hopefully that's a pretty complete answer :-).

-glyph
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20150319/5d5edec5/attachment-0002.html>


More information about the Twisted-Python mailing list