Categories
Linux Python RFCs & Standards

ASN.1 Encoding in a Nutshell

Introduction to Encoding & Decoding data in ASN.1 (Using Python)

What is ASN.1 and why is it so hard to find a good explanation or example?

ISO, IEC & ITU-T all got together and wrote a standard for describing data transmitted by telecommunications protocols, it’s used by many well known protocols X.509 (SSL), LDAP, SNMP, LTE which all rely on ASN.1 to encode data, transmit it, and then decode it, reliably and efficiently.

Overview

Let’s take this XML encoded data:

<?xml version="1.0" encoding="UTF-8"?>
<Message>
  <number>61412341234</number>
  <text>Hello my friend!</text>
</Message>

As you can see it’s human readable and pretty clear.

But what if we split this in two, had the definitions in one file and the values in another:

Definitions:

Here we’ll describe each of our fields

Message:
NumberĀ – Intiger- Destination of Message
Text – String – Message to be sent

Values:

Now we’ll list the values.

61412341234
Hello my friend!

By taking the definitions out our data is now 28 bytes, instead of 122, so we’re a fraction of the size on the wire (becomes important if you’re sending this data all the time or with a limited link budget), and we’ve also defined the type of each value as well, so we know we shouldn’t have an integer as the heading for example, we can see it’s a string.

The sender and the receiver both have a copy of the definitions, so everyone is clear on where we stand in terms of what each field is, and the types of values we encode. As a bonus we’re down to less than 1/4 of our original size. Great!

That’s ASN.1 in a nutshell, but let’s dig a little deeper and use a real example.

ASN.1 IRL

Now let’s actually encode & decode some data.

I’ll be using asn1tools a Python library written by Erik Moqvist, you can add it through pip:

pip install asn1tools

We’ll create a new text file and put our ASN.1 definitions into it, so let’s create a new file called foo.asn which will contain our definitions in ASN.1 format:

HelloWorld DEFINITIONS ::= BEGIN
Message ::= SEQUENCE {
number INTEGER,
text UTF8String
}
END

Copy and paste that into foo.asn and now we’ve got a definition, with a Module called Message containing a field called number (which is an integer) and a filed called text (which is a string).

Now let’s fire up our python shell in the same directory as our new file:

>>import asn1tools
>>foo = asn1tools.compile_files('foo.asn')
>>encoded = foo.encode('Message',  {'number': 61412341234, 'text': u'Hello my friend!'})
>>encoded
    bytearray(b'0\x19\x02\x05\x0eLu\xf5\xf2\x0c\x10Hello my friend!')

(You’ll need to run this in the Python shell, else it’ll just output encoded as plain text and not as a Byte Array as above)

So now we’ve encoded our values (number = 2 and text = ‘Hi!’) into bytes, ready to be sent down the wire and decoded at the other end. Not exactly human friendly but efficient and well defined.

So let’s decode them, again, Python shell:

>>> import asn1tools
>>> foo = asn1tools.compile_files('foo.asn')
>>> decoded = foo.decode('Message', '0\x19\x02\x05\x0eLu\xf5\xf2\x0c\x10Hello my friend!')
>>> decoded
    {'text': u'Hello my friend!', 'number': 61412341234}

So there you have it, an introduction to ASN1, how to encode & decode data.

We can grow our definitions (in the .asn file) and so long as both ends have the same definitions and you’re encoding the right stuff, you’ll be set.

Further Reading

There’s a whole lot more to ASN1 – Like how you encode the data, how to properly setup your definitions etc, but hopefully you understand what it actually does now.

Some further reading:

Leave a Reply