Parsing DER with ASN1 modules provided runtime

Attestations need to work with the following systems:

  • SmartContract (read-only)
  • Web Sites (mostly read-only)
  • TokenScript engine (like ╬▒Wallet, read and write)
  • Supernode (or any server that openly deals with attestations defined by TS)

The first two can probably use compile-time ASN.1 modules. As they probably already know what kind of tokens they are dealing with, they can compile the parsing code from the TokkenScrip they already have.

The latter two has to deal with TokenScripts not known at the time of deployment and has to parse DER-encoded attestations using modules supplied by TokenScript at runtime.

I experimented with supplying module at runtime. The following experiment is done with Python. Not very portable to iOS/Android but it gives an idea of what could be done with an interpreted language.

First, translate a module in ASN.X to code (with XSLT). This one has a Record type which has an id, a room number and a house number.

<?xml version="1.0"?>
<asnx:module xmlns:asnx="urn:ietf:params:xml:ns:asnx"
             tagDefault="explicit">

 <namedType name="Record">
  <type>
    <sequence>
      <element name="id" type="Integer"/>
      <optional>
        <element name="room">
          <type>
            <tagged number="0" tagging="explicit" type="Integer"/>
          </type>
      </optional>
      <element name="house">
        <type>
          <tagged number="1" tagging="explicit" type="Integer"/>
          <default literalValue="0"/>
        </type>
      </element>
   </sequence>
  </type>
 </namedType>

The translated Python code is

Record.componentType = NamedTypes(
    NamedType('id', Integer()),
    OptionalNamedType(
        'room', Integer().subtype(
            implicitTag=Tag(tagClassContext, tagFormatSimple, 0)
        )
    ),
    DefaultedNamedType(
        'house', Integer(0).subtype(
            implicitTag=Tag(tagClassContext, tagFormatSimple, 1)
        )
    )
)

Then, enclose this translated Python code-segment into a string, to demonstrate that they can be used at runtime:

from pyasn1.type.univ import Sequence, Integer
from pyasn1.type.namedtype import NamedType, NamedTypes, OptionalNamedType, DefaultedNamedType
from pyasn1.type.tag import Tag, tagFormatSimple, tagClassContext

class Record(Sequence):
    pass

asn1sequence = """
Record.componentType = NamedTypes(
    NamedType('id', Integer()),
    OptionalNamedType(
        'room', Integer().subtype(
            implicitTag=Tag(tagClassContext, tagFormatSimple, 0)
        )
    ),
    DefaultedNamedType(
        'house', Integer(0).subtype(
            implicitTag=Tag(tagClassContext, tagFormatSimple, 1)
        )
    )
)
"""

exec(asn1sequence)

print(Record.componentType)

The code outputs (with Python 3.8) the definition of the module, which shows it's ready to be used at runtime:

<NamedTypes object at 0x7f6132f27760 types <NamedType object at 0x7f6132f15850 type id=<Integer schema object at 0x7f6132fd40d0 tagSet <TagSet object at 0x7f6132f45550 tags 0:0:2>>>
 <OptionalNamedType object at 0x7f6132f15a00 type room=<Integer schema object at 0x7f6132f27a90 tagSet <TagSet object at 0x7f6132f27b20 tags 128:0:0>>>
 <DefaultedNamedType object at 0x7f6132f27130 type house=<Integer value object at 0x7f6132f31a60 tagSet <TagSet object at 0x7f6132f38070 tags 128:0:1> payload [0]>>>

It sounds like a suitable work-around, although it seems that Pyasn1 does not support Json or XML and so it is requires to use some other library to convert the internal object representation to Json. I found another Python tool called asn1tools that seems to only require a single call to convert a BER/DER encoding to a JER encoding based on an ASN1 module. This should be all we require as the JER encoding includes the attribute names (although there might be a little bit of handling since JER does not include full type information.

It seems the same can be done in JavaScript (translating ASN.X module into JavaScript schema):

//region How to validate ASN.1 against pre-defined schema 
var asn1_schema = new asn1js.Sequence({
    name: "block1",
    value: [
        new asn1js.Null({
            name: "block2"
        }),
        new asn1js.Integer({
            name: "block3",
            optional: true // This block is absent inside data, but it's "optional". Hence verification against the schema will be passed.
        })
    ]
});

Note that this comes from PeculiarVentures, which is the same entity that produced the XMLDSIG library for JavaScript. What a proliferate company.

It looks like the solution from PeculiarVentures is definitely able to validate ASN1 encodings in BER against a specified schema. That is great news! However, it does not seem like it supports loading that schema from an ASN1 description (or ASN.X file). This is less good news. This means that it would still be necessary to write an intermediate parser in Javascript that takes and ASN.X description of the ASN module and translates this into a javascript object model in order to parse the encoded ASN data according to this module. However, we already accepted that this would be needed for the app versions as well so it might not be a deal breaker :slight_smile:

PS. Since we are in javascript I think it might be easier to parse from a JSON description of the ASN schema. Still, we also need to do this for the Android and iOS apps, but given that both XML and JSON parsing is probably equally supported on those platforms, an overall JSON description of the ASN schema might be the best way to go in general.

PPS. I looked a bit more on Google for javascript support for ASN, and unfortunately did not find anything that seems better, or even equally good, to the PeculiarVentures solution. The one thing I noticed was that asn1tools (mentioned in my comment above) writes that they have planned support for parsing in to javascript objects. However, we cannot base our decisions on what some company might do in the future.