pyasn1
pyasn1 copied to clipboard
Can't decode native encoded AttributeTypeAndValue with univ.Choice inside
I was using pyasn1 0.4.5 and rfc5280 module to:
- decode the public key certificate,
- encode it to native Python objects,
- make some changes,
- and revert it all the way back to the der binary format.
But I've encountered an error "TypeError: 'str' object cannot be interpreted as an integer" when tried to decode native Python representation of AttributeTypeAndValue with X520StateOrProvinceName value lying inside.
Minimal working example without rfc5280 module:
from pyasn1.codec.native import decoder, encoder
from pyasn1.type import univ, char
from pyasn1.type.namedtype import NamedType, NamedTypes
from pyasn1.type.opentype import OpenType
import pyasn1.debug as debug
debug.setLogger(debug.Debug('all'))
class FooChoice(univ.Choice):
componentType = NamedTypes(NamedType('utf8String', char.UTF8String()))
fooTypeMap = { univ.ObjectIdentifier('1.2.3'): FooChoice() }
class FooType(univ.ObjectIdentifier): pass
class FooValue(univ.Any): pass
class FooTypeAndValue(univ.Sequence):
componentType = NamedTypes(
NamedType('type', FooType()),
NamedType('value', FooValue(), openType=OpenType('type', fooTypeMap))
)
fooTV = FooTypeAndValue()
fooTV['type'] = univ.ObjectIdentifier('1.2.3')
fooChoice = FooChoice()
fooChoice['utf8String'] = 'bar'
fooTV['value'] = fooChoice
natified = encoder.encode(fooTV)
print(f'Natified object: {natified}')
print(decoder.decode(natified, FooTypeAndValue()))
Standard output:
2019-06-08 19:03:57,175 pyasn1: running pyasn1 0.4.5, debug flags all2019-06-08 19:03:57,175 pyasn1: debug category 'all' enabled
2019-06-08 19:03:57,176 pyasn1: encoder called for type FooTypeAndValue <FooTypeAndValue:
type=1.2.3 value=FooChoice:
utf8String=bar
>
2019-06-08 19:03:57,176 pyasn1: using value codec SequenceEncoder chosen by <TagSet object at 0x3bd2dd0 tags 0:32:16>
2019-06-08 19:03:57,176 pyasn1: encoder called for type ObjectIdentifier <1.2.3>
2019-06-08 19:03:57,176 pyasn1: using value codec ObjectIdentifierEncoder chosen by <TagSet object at 0x3bd28b0 tags 0:0:6>
2019-06-08 19:03:57,177 pyasn1: encoder ObjectIdentifierEncoder produced: '1.2.3'
2019-06-08 19:03:57,177 pyasn1: encoder called for type FooChoice <FooChoice:
utf8String=bar
>
2019-06-08 19:03:57,177 pyasn1: using value codec ChoiceEncoder chosen by <TagSet object at 0x3be3090 untagged>
2019-06-08 19:03:57,178 pyasn1: encoder called for type UTF8String <bar>
2019-06-08 19:03:57,178 pyasn1: using value codec OctetStringEncoder chosen by <TagSet object at 0x3be3270 tags 0:0:12>
2019-06-08 19:03:57,179 pyasn1: encoder OctetStringEncoder produced: b'bar'
2019-06-08 19:03:57,179 pyasn1: encoder ChoiceEncoder produced: OrderedDict([('utf8String', b'bar')])
2019-06-08 19:03:57,179 pyasn1: encoder SequenceEncoder produced: OrderedDict([('type', '1.2.3'), ('value', OrderedDict([('utf8String', b'bar')]))])
Natified object: OrderedDict([('type', '1.2.3'), ('value', OrderedDict([('utf8String', b'bar')]))])
2019-06-08 19:03:57,179 pyasn1: decoder called at scope OrderedDict, working with type OrderedDict
2019-06-08 19:03:57,180 pyasn1: calling decoder SequenceOrSetDecoder on Python type OrderedDict <OrderedDict([('type', '1.2.3'), ('value', OrderedDict([('utf8String', b'bar')]))])>
2019-06-08 19:03:57,180 pyasn1: decoder called at scope OrderedDict.str, working with type str
2019-06-08 19:03:57,180 pyasn1: calling decoder AbstractScalarDecoder on Python type str <'1.2.3'>
2019-06-08 19:03:57,181 pyasn1: decoder AbstractScalarDecoder produced ASN.1 type FooType <<FooType value object at 0x3be3990 tagSet <TagSet object at 0x3bd28b0 tags 0:0:6> payload [1.2.3]>>
2019-06-08 19:03:57,181 pyasn1: decoder called at scope OrderedDict.OrderedDict, working with type OrderedDict
2019-06-08 19:03:57,181 pyasn1: calling decoder AbstractScalarDecoder on Python type OrderedDict <OrderedDict([('utf8String', b'bar')])>
Traceback (most recent call last):
File "mwe_basic.py", line 31, in <module>
print(decoder.decode(natified, FooTypeAndValue()))
File "...\lib\site-packages\pyasn1\codec\native\decoder.py", line 164, in __call__
value = valueDecoder(pyObject, asn1Spec, self, **options)
File "...\lib\site-packages\pyasn1\codec\native\decoder.py", line 38, in __call__
asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options)
File "...\lib\site-packages\pyasn1\codec\native\decoder.py", line 164, in __call__
value = valueDecoder(pyObject, asn1Spec, self, **options)
File "...\lib\site-packages\pyasn1\codec\native\decoder.py", line 22, in __call__
return asn1Spec.clone(pyObject)
File "...\lib\site-packages\pyasn1\type\base.py", line 349, in clone
return self.__class__(value, **initializers)
File "...\lib\site-packages\pyasn1\type\univ.py", line 819, in __init__
base.AbstractSimpleAsn1Item.__init__(self, value, **kwargs)
File "...\lib\site-packages\pyasn1\type\base.py", line 240, in __init__
value = self.prettyIn(value)
File "...\lib\site-packages\pyasn1\type\univ.py", line 878, in prettyIn
return bytes(value)
TypeError: 'str' object cannot be interpreted as an integer
Minimal working example based upon rfc5280 module:
from pyasn1_modules.rfc5280 import AttributeTypeAndValue, AttributeType, X520StateOrProvinceName
from pyasn1.codec.native import decoder, encoder
import pyasn1.debug as debug
debug.setLogger(debug.Debug('all'))
fooTV = AttributeTypeAndValue()
fooTV['type'] = AttributeType('2.5.4.8')
fooValue = X520StateOrProvinceName()
fooValue['utf8String'] = 'bar'
fooTV['value'] = fooValue
natified = encoder.encode(fooTV)
print(f'Natified object: {natified}')
print(decoder.decode(natified, AttributeTypeAndValue()))
Standard output:
2019-06-08 23:57:01,209 pyasn1: running pyasn1 0.4.5, debug flags all
2019-06-08 23:57:01,209 pyasn1: debug category 'all' enabled
2019-06-08 23:57:01,210 pyasn1: encoder called for type AttributeTypeAndValue <AttributeTypeAndValue:
type=2.5.4.8
value=X520StateOrProvinceName:
utf8String=bar
>
2019-06-08 23:57:01,210 pyasn1: using value codec SequenceEncoder chosen by <TagSet object at 0x3a11830 tags 0:32:16>
2019-06-08 23:57:01,211 pyasn1: encoder called for type AttributeType <2.5.4.8>
2019-06-08 23:57:01,211 pyasn1: using value codec ObjectIdentifierEncoder chosen by <TagSet object at 0x3a11310 tags 0:0:6>
2019-06-08 23:57:01,211 pyasn1: encoder ObjectIdentifierEncoder produced: '2.5.4.8'
2019-06-08 23:57:01,211 pyasn1: encoder called for type X520StateOrProvinceName <X520StateOrProvinceName:
utf8String=bar
>
2019-06-08 23:57:01,212 pyasn1: using value codec ChoiceEncoder chosen by <TagSet object at 0x3a11ad0 untagged>
2019-06-08 23:57:01,212 pyasn1: encoder called for type UTF8String <bar>
2019-06-08 23:57:01,212 pyasn1: using value codec OctetStringEncoder chosen by <TagSet object at 0x3a11cb0 tags 0:0:12>
2019-06-08 23:57:01,212 pyasn1: encoder OctetStringEncoder produced: b'bar'
2019-06-08 23:57:01,213 pyasn1: encoder ChoiceEncoder produced: OrderedDict([('utf8String', b'bar')])
2019-06-08 23:57:01,213 pyasn1: encoder SequenceEncoder produced: OrderedDict([('type', '2.5.4.8'), ('value', OrderedDict([('utf8String', b'bar')]))])
Natified object: OrderedDict([('type', '2.5.4.8'), ('value', OrderedDict([('utf8String', b'bar')]))])
2019-06-08 23:57:01,213 pyasn1: decoder called at scope OrderedDict, working with type OrderedDict
2019-06-08 23:57:01,214 pyasn1: calling decoder SequenceOrSetDecoder on Python type OrderedDict <OrderedDict([('type', '2.5.4.8'), ('value', OrderedDict([('utf8String', b'bar')]))])>
2019-06-08 23:57:01,214 pyasn1: decoder called at scope OrderedDict.str, working with type str
2019-06-08 23:57:01,214 pyasn1: calling decoder AbstractScalarDecoder on Python type str <'2.5.4.8'>
2019-06-08 23:57:01,214 pyasn1: decoder AbstractScalarDecoder produced ASN.1 type AttributeType <<AttributeType value object at 0x3b269f0 tagSet <TagSet object at 0x3a11310 tags 0:0:6> payload [2.5.4.8]>>
2019-06-08 23:57:01,215 pyasn1: decoder called at scope OrderedDict.OrderedDict, working with type OrderedDict
2019-06-08 23:57:01,215 pyasn1: calling decoder AbstractScalarDecoder on Python type OrderedDict <OrderedDict([('utf8String', b'bar')])>
Traceback (most recent call last):
File "mwe_rfc5280.py", line 15, in <module>
print(decoder.decode(natified, AttributeTypeAndValue()))
File "...\lib\site-packages\pyasn1\codec\native\decoder.py", line 164, in __call__
value = valueDecoder(pyObject, asn1Spec, self, **options)
File "...\lib\site-packages\pyasn1\codec\native\decoder.py", line 38, in __call__
asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options)
File "...\lib\site-packages\pyasn1\codec\native\decoder.py", line 164, in __call__
value = valueDecoder(pyObject, asn1Spec, self, **options)
File "...\lib\site-packages\pyasn1\codec\native\decoder.py", line 22, in __call__
return asn1Spec.clone(pyObject)
File "...\lib\site-packages\pyasn1\type\base.py", line 349, in clone
return self.__class__(value, **initializers)
File "...\lib\site-packages\pyasn1\type\univ.py", line 819, in __init__
base.AbstractSimpleAsn1Item.__init__(self, value, **kwargs)
File "...\lib\site-packages\pyasn1\type\base.py", line 240, in __init__
value = self.prettyIn(value)
File "...\lib\site-packages\pyasn1\type\univ.py", line 878, in prettyIn
return bytes(value)
TypeError: 'str' object cannot be interpreted as an integer
(parts_generator)
Thank you for reporting this issue!
It appears, that openType feature is not implemented for the native decoder. Let me see if we could add it there.