从PyCrypto迁移至pyasn1时DER序列解码报错求助
PyASN1解析含空序列的DER数据报错解决办法
问题描述
原有一段DER序列,此前可通过PyCrypto的ASN.1模块正常解析,迁移至pyasn1后解码报错。代码片段如下:
x = "308201cc04080c000000000000000408a80de7c97e000000161036633533346433323334333337653533308201a0301e040804000000000000000408240000000000000004089f86010000000000301e040804000000000000000408400d0300000000000408df93040000000000301e040805000000000000000408180000000000000004089f86010000000000301e040805000000000000000408e09304000000000004087f1a060000000000301e040806000000000000000408000000000000000004089f86010000000000301e040807000000000000000408240000000000000004089f86010000000000301e040808000000000000000408000000000000000004089f86010000000000301e040809000000000000000408000000000000000004089f86010000000000301e04080a000000000000000408000000000000000004089f86010000000000301e04080b000000000000000408000000000000000004089f86010000000000301e04080c000000000000000408000000000000000004089f86010000000000301e04080d000000000000000408000000000000000004089f86010000000000301e04080e000000000000000408000000000000000004089f860100000000003000" from pyasn1.codec.der import decoder decoder.decode(bytes.fromhex(x))
报错信息:
AttributeError("'NoneType' object has no attribute 'tagSet'")
经排查,错误由序列末尾的空SEQUENCE(3000,即长度为0的序列)导致。该序列可被OpenSSL正常解析:
echo "<hex string>" | xxd -p -r | openssl asn1parse -inform der
解决办法
1. 使用univ.Any()作为解析模板
pyasn1自动推断类型时无法识别空SEQUENCE,指定univ.Any()作为解析模板可兼容任意ASN.1结构,包括空序列:
from pyasn1.type import univ from pyasn1.codec.der import decoder x = "你的十六进制字符串" # 传入asn1Spec参数指定解析模板 result, rest = decoder.decode(bytes.fromhex(x), asn1Spec=univ.Any()) print(result)
2. 定义匹配结构的自定义SEQUENCE类型
如果知道DER数据的具体ASN.1结构,可以定义一个允许空元素的自定义SEQUENCE类型,示例如下:
from pyasn1.type import univ, namedtype from pyasn1.codec.der import decoder # 自定义SEQUENCE,根据实际结构调整组件定义 class CustomSequence(univ.Sequence): componentType = namedtype.NamedTypes( # 用univ.Any()兼容任意类型,optional=True允许元素缺失 namedtype.NamedType('item1', univ.Any(), optional=True), namedtype.NamedType('item2', univ.Any(), optional=True), # 按需添加更多组件 ) x = "你的十六进制字符串" result, rest = decoder.decode(bytes.fromhex(x), asn1Spec=CustomSequence())
3. 升级pyasn1到最新版本
部分旧版本的pyasn1对空序列的处理存在bug,升级到最新版本可能解决问题:
pip install --upgrade pyasn1
原因说明
pyasn1默认会自动尝试推断ASN.1类型,但遇到长度为0的SEQUENCE时,无法确定对应的合法类型,返回None,后续代码访问None的tagSet属性时触发报错。而PyCrypto和OpenSSL的解析器对这类非严格符合规范的结构兼容性更强。
内容的提问来源于stack exchange,提问作者theLearner
相关产品推荐
相关产品推荐

