如何解决不支持 RELATIVE-OID 的 ASN.1 库
How to work around ASN.1 library not supporting RELATIVE-OID
我正在尝试使用 asn1tools
Python library to decode and encode BER messages conforming to the Ember+ 标准。
That standard’s DTD uses ASN.1’s RELATIVE-OID
type in some places. However, asn1tools
doesn’t know about this type, probably because the underlying pyasn1
library doesn’t implement it (not yet, there’s a pull request)。这就是为什么我不能在我的 Python 程序中使用那个 DTD。但我真的不得不。
在我看来,我的选择是创建包含 RELATIVE-OID
PR 的 pyasn1
的补丁版本并使 asn1tools
使用它,或者以某种方式构建DTD 中的解决方法。
我已经尝试将RELATIVE-OID ::= [UNIVERSAL 13] OCTET STRING
添加到DTD中,但现在asn1tools
响应Expected RELATIVE-OID with tag '2d' at offset 10, but got '0d'.
基本上它似乎接受我的定义,但使其成为“通用构造13”而消息将其标记为“通用 原始 13”。
我有办法解决这个问题吗?
这是我的限制条件:
- 我基本上有使用
asn1tools
,我的代码已经严重依赖它了。
- 我有能够解析和创建与将这些字段标记为
0d
. 的其他第三方客户端兼容的消息
- 我 可以 根据需要在 DTD 中进行编辑,例如添加定义
RELATIVE-OID
的类型(但以何种方式?)或替换每次出现的RELATIVE-OID
与其他东西一起使用,只要它仍然适用于将字段标记为 0d
. 的消息
- 我完全同意将
RELATIVE-OID
值作为 bytes
或其他东西的不透明 blob,这就是我首先尝试 OCTET STRING
解决方法的原因.
我的 ASN.1 知识有限,我不擅长编写 DTD。也许有一种方法可以强制该类型成为“原始”类型?我很高兴提出任何建议。如果您想亲自尝试一下,请使用上面链接的 DTD。然后,使用以下 Python 代码:
import asn1tools
spec = asn1tools.compile_files('GlowDtd.asn1')
print(spec.decode('Root', b'`\x80k\x80\xa0\x80b\x80\xa0\x03\x02\x01 \xa1\x03\x02\x01\xff\x00\x00\x00\x00\x00\x00\x00\x00'))
# should result in ('elements', [('element', ('command', {'number': 32, 'options': ('dirFieldMask', -1)}))])
print(spec.decode('Root', b'`\x80k\x80\xa0\x80j\x80\xa0\x03\r\x01\x01\xa2\x80d\x80\xa0\x80b\x80\xa0\x03\x02\x01 \xa1\x03\x02\x01\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
# doesn't work because it uses RELATIVE-OID
尝试
RELATIVE-OID ::= [UNIVERSAL 13] IMPLICIT OCTET STRING
我正在尝试使用 asn1tools
Python library to decode and encode BER messages conforming to the Ember+ 标准。
That standard’s DTD uses ASN.1’s RELATIVE-OID
type in some places. However, asn1tools
doesn’t know about this type, probably because the underlying pyasn1
library doesn’t implement it (not yet, there’s a pull request)。这就是为什么我不能在我的 Python 程序中使用那个 DTD。但我真的不得不。
在我看来,我的选择是创建包含 RELATIVE-OID
PR 的 pyasn1
的补丁版本并使 asn1tools
使用它,或者以某种方式构建DTD 中的解决方法。
我已经尝试将RELATIVE-OID ::= [UNIVERSAL 13] OCTET STRING
添加到DTD中,但现在asn1tools
响应Expected RELATIVE-OID with tag '2d' at offset 10, but got '0d'.
基本上它似乎接受我的定义,但使其成为“通用构造13”而消息将其标记为“通用 原始 13”。
我有办法解决这个问题吗?
这是我的限制条件:
- 我基本上有使用
asn1tools
,我的代码已经严重依赖它了。 - 我有能够解析和创建与将这些字段标记为
0d
. 的其他第三方客户端兼容的消息
- 我 可以 根据需要在 DTD 中进行编辑,例如添加定义
RELATIVE-OID
的类型(但以何种方式?)或替换每次出现的RELATIVE-OID
与其他东西一起使用,只要它仍然适用于将字段标记为0d
. 的消息
- 我完全同意将
RELATIVE-OID
值作为bytes
或其他东西的不透明 blob,这就是我首先尝试OCTET STRING
解决方法的原因.
我的 ASN.1 知识有限,我不擅长编写 DTD。也许有一种方法可以强制该类型成为“原始”类型?我很高兴提出任何建议。如果您想亲自尝试一下,请使用上面链接的 DTD。然后,使用以下 Python 代码:
import asn1tools
spec = asn1tools.compile_files('GlowDtd.asn1')
print(spec.decode('Root', b'`\x80k\x80\xa0\x80b\x80\xa0\x03\x02\x01 \xa1\x03\x02\x01\xff\x00\x00\x00\x00\x00\x00\x00\x00'))
# should result in ('elements', [('element', ('command', {'number': 32, 'options': ('dirFieldMask', -1)}))])
print(spec.decode('Root', b'`\x80k\x80\xa0\x80j\x80\xa0\x03\r\x01\x01\xa2\x80d\x80\xa0\x80b\x80\xa0\x03\x02\x01 \xa1\x03\x02\x01\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
# doesn't work because it uses RELATIVE-OID
尝试
RELATIVE-OID ::= [UNIVERSAL 13] IMPLICIT OCTET STRING