Skip to content

Instantly share code, notes, and snippets.

@apettinen
Last active October 6, 2016 11:39
Show Gist options
  • Save apettinen/def48e39ff6e01f622be3ffe3db53cb6 to your computer and use it in GitHub Desktop.
Save apettinen/def48e39ff6e01f622be3ffe3db53cb6 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
# -*- coding: utf-8 -*-
# pylint: disable=C0301, C0103, W0702, W1201
# Antti Pettinen (Tampere University of Technology)
# Ilkka Vanhatalo (Helsinki University)
# Copyright: Tampere University of Technology and University of Helsinki
# License: Apache 2.0
'''
Parse CSRs for Custom Attributes and Requested Extensions with pyASN1
'''
import sys
try:
from pyasn1.codec.der import decoder as der_decoder
from pyasn1_modules import rfc2314, rfc2459, pem
from pyasn1.type import univ, namedtype, tag
except ImportError:
sys.exit(1)
def _parseAndMapToOIDs(csr, OIDs):
'''
Map ASN.1 type CSR attributes and extensions to provided OID values. In ASN.1 CSR structure the requested extensions are mapped under attributes with predifined and fixed OID of 1.2.840.113549.1.9.14. Thus they can be reached with similar methods than custom attributes in CSR.
'''
# This is the OID for Extension Requests in CSRs:
extReqOID = '1.2.840.113549.1.9.14'
extReqOIDObj = univ.ObjectIdentifier(extReqOID)
# make sure that OID for requested extensions is in the list of OIDs
if extReqOID not in OIDs:
OIDs.append(extReqOID)
OIDToValue = dict()
try:
for attribute in csr['certificationRequestInfo']['attributes']:
# change the attribute to octet representation:
attributeOctet = attribute['vals'].getComponentByPosition(0).asOctets()
attributeOIDObj = attribute['type']
attributeOID = attributeOIDObj.prettyPrint()
# if a custom attribute is found amongst the provided OIDs, map
# the custom attribute to the corresponding OID...
if attributeOID in OIDs and attributeOIDObj != extReqOIDObj:
attributeValue, _attrRest= der_decoder.decode(attributeOctet)
OIDToValue[attributeOID] = attributeValue.prettyPrint()
print('Mapped custom attribute {AO} to value {AV}...').format(AO=attributeOID, AV=attributeValue.prettyPrint())
# unless attribute is extension request... Then we need to
# transform the rfc2314 type CSR attribute information to rfc2459
# type requested extension information
elif attributeOIDObj == extReqOIDObj:
extReqs, _extRest = der_decoder.decode(attributeOctet, asn1Spec=rfc2459.Extensions())
# Dict in dict for requested extensions:
OIDToValue[attributeOID] = {}
for extReq in extReqs:
# get OID and value for the requested extension
extOID = extReq['extnID'].prettyPrint()
extValue = der_decoder.decode(der_decoder.decode(univ.OctetString(extReq['extnValue'].asOctets()))[0])[0].prettyPrint()
# map the value
OIDToValue[attributeOID][extOID] = extValue
print('Mapped requested extension {EO} to value {EV}...').format(EO=extOID, EV=extValue)
print('CSR parsing succesfull!')
except:
print('Error parsing attributes and extensions from CSR.')
sys.exit(1)
return OIDToValue
def main():
'''It's me, main.'''
#Example: myOIDs = ['1.3.6.1.4.1.34380.1.2.2.2', '1.3.6.1.4.1.34380.1.2.2.3']
# myCSR= what ever way you get your CSR substrate (e.g pem.readPemBlocksFromFile(sys.stdin, ('-----BEGIN CERTIFICATE REQUEST-----', '-----END CERTIFICATE REQUEST-----'))
OIDsToValues=_parseAndMapToOIDs(myCSR, myOIDs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment