简体   繁体   中英

How to work around ASN.1 library not supporting RELATIVE-OID

I'm trying to use the asn1tools Python library to decode and encode BER messages conforming to the Ember+ standard.

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 ). Which is why I can't use that DTD in my Python program. But I really have to.

My options, as I see them, are to either create a patched version of pyasn1 with the RELATIVE-OID PR included and make asn1tools work with it, or to somehow build a workaround in the DTD.

I've already tried adding RELATIVE-OID ::= [UNIVERSAL 13] OCTET STRING to the DTD, but now asn1tools responds with Expected RELATIVE-OID with tag '2d' at offset 10, but got '0d'. Basically it seems to accept my definition, but makes it “universal constructed 13” while the message tags it as “universal primitive 13”.

Is there a way for me to work around this?

Here are my constraints:

  • I basically have to use asn1tools , my code is already heavily depending on it.
  • I have to be able to parse and create messages compatible to other third-party clients that tag these fields as 0d .
  • I can edit around in the DTD as I please, for example adding a type that defines RELATIVE-OID (but in what way?) or replacing every occurrence of RELATIVE-OID with something else, as long as it will still work with the messages that tag the fields as 0d .
  • I'm totally okay with getting the RELATIVE-OID value as an opaque blob of bytes or something, which is why I've tried the OCTET STRING workaround in the first place.

My ASN.1 knowledge is limited and I'm not proficient in writing DTDs. Maybe there's a way to force the type to being “primitive”? I'm happy for any suggestions. If you'd like to try it out for yourself, use the DTD linked above. Then, use the following Python code:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM