Friday, April 17, 2009

Client certificates with urllib2

First let's get pem formatted file with certificate and key from your *.pkcs12 or *.pfx file with openssl.
openssl pkcs12 -in file.p12 -out file.pem -nodes


Now we need to extend standart HTTPSHandler( I found it here. I added timeout to getConnection method. ) and sent instance of it to urllib2's build_opener.
import urllib2, httplib
class HTTPSClientAuthHandler(urllib2.HTTPSHandler):
def __init__(self, key, cert):
urllib2.HTTPSHandler.__init__(self)
self.key = key
self.cert = cert
def https_open(self, req):
#Rather than pass in a reference to a connection class, we pass in
# a reference to a function which, for all intents and purposes,
# will behave as a constructor
return self.do_open(self.getConnection, req)
def getConnection(self, host, timeout=300):
return httplib.HTTPSConnection(host, key_file=self.key, cert_file=self.cert)

opener = urllib2.build_opener(HTTPSClientAuthHandler('/path/to/file.pem', '/path/to/file.pem.') )
response = opener.open("https://example.org")

print response.read()

4 comments:

  1. Hi, Thats nice info.

    I followed this procedure, ....

    However I have a problem, I have the certificate file, but it is perhaps in some other format ....

    So I get this error "error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure"

    .. and I do not know how to determin using openssl, that in which 'format' this certificate is, my gut feeling is it is a RSA key, now how do i convert the RSA key in the 'pem' format ??
    ReplyDelete
  2. I have such format:

    Bag Attributes
    localKeyID: 01 00 00 00
    subject=/C=KG/L=bla-bla/O=bla-bla/OU=IT/CN=bla-bla
    issuer=/CN=bla-bla
    -----BEGIN CERTIFICATE-----
    long hex bla-bla
    -----END CERTIFICATE-----
    Bag Attributes
    localKeyID: 01 00 00 00
    Microsoft CSP Name: Microsoft Enhanced Cryptographic Provider v1.0
    friendlyName: ed8861c58dbe8ddd8e0389ec9479d205_4b0306d4-ef6e-4a26-977a-358ca718f4b5
    Key Attributes
    X509v3 Key Usage: 10
    -----BEGIN RSA PRIVATE KEY-----
    long hex bla-bla
    -----END RSA PRIVATE KEY-----
    ReplyDelete
  3. Are you sure this solution works? The modified version of httplib which ships with GAE raises an exception:

    File "/base/python_runtime/python_dist/lib/python2.5/httplib.py", line 221, in __init__
    "key_file and cert_file arguments are not implemented")
    NotImplementedError: key_file and cert_file arguments are not implemented
    ReplyDelete
  4. This solution works only on some version of python and I can't remember it. This issue is fixed in 2.6.
    ReplyDelete