I have a python script that used to work for generating X509 certificates with certificate extensions using PyASN1 and pyasn1_modules
modules. But now that I've updated these modules to the latest versions from pypi (previously they were from Ubuntu 14.04 repos), generated certificates are no longer valid (according to openssl x509
command and also dumpasn1
command which shows changes from previously generated certificates, notably extension values are no longer wrapped in an OctetString
container).
This is the problematic code:
from pyasn1.type import univ
from pyasn1.codec.der import encoder as der_encoder
from pyasn1_modules import rfc2459
extn = rfc2459.BasicConstraints()
extn.setComponentByName('cA', True)
extn.setComponentByName('pathLenConstraint', 5)
extn_val = der_encoder.encode(extn)
extension = rfc2459.Extension()
extension.setComponentByName('extnID', '2.5.29.19')
extension.setComponentByName('critical', True)
extension.setComponentByName('extnValue', extn_val)
I've tried changing last line to this:
extension.setComponentByName('extnValue', univ.OctetString(extn_val))
Which raises this error from PyASN1:
Component value is tag-incompatible: OctetString(hexValue='30060101ff020105') vs Any()
What are the changes in recent versions that might have caused this and how can I correct my code to make it compatible with new version of these two modules (and preferably keep it compatible with previous versions).
New versions: pyasn1 0.1.9, and pyasn1_modules 0.0.8
Ubuntu repo versions: pyasn1 0.1.7, and pyasn1_modules 0.0.3
Python version 2.7
You should probably encode the OCTET STRING container as well.
The reason is that RFC specifies it as OCTET STRING, but pyasn1-modules use ANY type for it. Since ANY type is serialized transparently (e.g. no tag added), you need to pass OCTET STRING serialization.
extension.setComponentByName('extnValue', der_encoder.encode(univ.OctetString(extn_val)))