4

I'm trying to get the dates for a CRL using PyOpenSSL. The CRL class doesn't contain them as accessible members. I'm going through all of the underscore members, but I'd rather not use one of those, as they're not supposed to be 'public'.

Any suggestions on getting the dates out?

user1667153
  • 125
  • 1
  • 3
  • 10

3 Answers3

5

You can't do that with pyOpenSSL, but this information from CRLs can actually be extracted using PyCrypto's asn1 parser without much problems. See example below:

import types
from Crypto.Util import asn1
import datetime as dt
from pytz import UTC

def decode_time(obj, format):
    return dt.datetime.strptime(obj.payload, format).replace(tzinfo=UTC)

time_formats = {
    23: lambda(obj): decode_time(obj, "%y%m%d%H%M%SZ"),
    24: lambda(obj): decode_time(obj, "%Y%m%d%H%M%SZ"),
    }

def crl_dates(crl_der):
    crl_seq = asn1.DerSequence()
    crl_seq.decode(crl_der)
    if len(crl_seq) != 3: raise ValueError("unknown crl format")
    tbsCertList = asn1.DerSequence()
    tbsCertList.decode(crl_seq[0])
    thisUpdate = asn1.DerObject()
    nextUpdate = asn1.DerObject()
    if isinstance(tbsCertList[0], types.StringTypes): # CRL v1
        thisUpdate.decode(tbsCertList[2])
        nextUpdate.decode(tbsCertList[3])
    else:
        if tbsCertList[0] > 1: raise ValueError("unsupported CRL profile version: %d" % tbsCertList[0])
        thisUpdate.decode(tbsCertList[3])
        nextUpdate.decode(tbsCertList[4])
    if thisUpdate.typeTag not in time_formats or \
       nextUpdate.typeTag not in time_formats:
        raise ValueError("invalid CRL date/time fields")
    return time_formats[thisUpdate.typeTag](thisUpdate), \
           time_formats[nextUpdate.typeTag](nextUpdate)

if __name__ == '__main__':
    from urllib2 import urlopen
    print "CRL v1", crl_dates(urlopen("http://crl.verisign.com/pca1.1.1.crl").read())
    print "CRL v2", crl_dates(urlopen("http://www.gstatic.com/GoogleInternetAuthority/GoogleInternetAuthority.crl").read())

Note: this code does not check any signatures or anything like that, just extracts the CRL dates.

abbot
  • 27,408
  • 6
  • 54
  • 57
  • Apparently installing PyCrypto on OS X takes too much fiddling, so I can't test the code, but I assume it works. But sadly it seems it's currently still easiest sticking to calling the "openssl crl …" command on the server and using the output of that. OpenSSL will always be present in our environment, so not worth replacing it for a non-standard library (in our case). – Joel L Dec 14 '12 at 17:29
  • Or: is PyCrypto included when I do a standard install of Ubuntu 12.04 server? – Joel L Dec 14 '12 at 17:29
  • @JoelL, PyCrypto can be trivially installed on OS X from MacPorts (e.g. just run `sudo port install py27-crypto` if you are using MacPorts with python27), and is also available on Ubuntu (`apt-get install python-crypto`) – abbot Dec 14 '12 at 21:09
0

It seems that get_rev_date() will return that date as ASN1 GENERALIZEDTIME.

I found this on pyOpenSSL's documentation.

ryucl0ud
  • 622
  • 4
  • 7
  • This returns the revocation date for a single certificate in the list, not the CRL nextUpdate/lastUpdate fields. – Joel L Dec 07 '12 at 21:29
0

The functionality doesn't exist currently. We ended up having to extend pyOpenSSL to handle this.

user1667153
  • 125
  • 1
  • 3
  • 10
  • Do you plan to contribute your implementation of this capability to the pyOpenSSL project? If so, perhaps the OP would like to review/test your code.For reference, here is the implementation of [get_rev_date](https://bazaar.launchpad.net/~exarkun/pyopenssl/trunk/view/head:/OpenSSL/crypto/revoked.c#L215) – neirbowj Dec 10 '12 at 21:21
  • (I ended up using the openssl command via python ("openssl crl -in FILENAME.crl -noout -nextupdate"), and parsing the output to get the nextUpdate datetime value. Not the most elegant solution…) – Joel L Dec 12 '12 at 15:11