Tag Archives: ASN.1

Dr StrangeEncoding or: How I learned to stop worrying and love ASN.1

Australia is a strange country; As a kid I was scared of dogs, and in response, our family got a dog.

This year started off with adventures working with ASN.1 encoded data, and after a week of banging my head against the table, I was scared of ASN.1 encoding.

But now I love dogs, and slowly, I’m learning to embrace ASN.1 encoding.

What is ASN.1?

ASN.1 is an encoding scheme.

The best analogy I can give is to image a sheet of paper with a form on it, the form has fields for all the different bits of data it needs,

Each of the fields on the form has a data type, and the box is sized to restrict input, and some fields are mandatory.

Now imagine you take this form and cut a hole where each of the text boxes would be.

We’ve made a key that can be laid on top of a blank sheet of paper, then we can fill the details through the key onto the blank paper and reuse the key over and over again to fill the data out many times.

When we remove the key off the top of our paper, and what we have left on the paper below is the data from the form. Without the key on top this data doesn’t make much sense, but we can always add the key back and presto it’s back to making sense.

While this may seem kind of pointless let’s look at the advantages of this method;

The data is validated by the key – People can’t put a name wherever, and country code anywhere, it’s got to be structured as per our requirements. And if we tried to enter a birthday through the key form onto the paper below, we couldn’t.

The data is as small as can be – Without all the metadata on the key above, such as the name of the field, the paper below contains only the pertinent information, and if a field is left blank it doesn’t take up any space at all on the paper.

It’s these two things, rigidly defined data structures (no room for errors or misinterpretation) and the minimal size on the wire (saves bandwidth), that led to 3GPP selecting ASN.1 encoding for many of it’s protocols, such as S1, NAS, SBc, X2, etc.

It’s also these two things that make ASN.1 kind of a jerk; If the data structure you’re feeding into your ASN.1 compiler does not match it will flat-out refuse to compile, and there’s no way to make sense of the data in its raw form.

I wrote a post covering the very basics of working with ASN.1 in Python here.

But working with a super simple ASN.1 definition you’ve created is one thing, using the 3GPP defined ASN.1 definitions is another,

With the aid of the fantastic PyCrate library, which is where the real magic happens, and this was the nut I cracked this week, compiling a 3GPP ASN.1 definition and communicating a standards-based protocol with it.

Watch this space for more fun with ASN.1!

ASN.1 Encoding in a Nutshell

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.


Let’s take this XML encoded data:

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

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:


Here we’ll describe each of our fields

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


Now we’ll list the values.

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.


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:

Message ::= SEQUENCE {
number INTEGER,
text UTF8String

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!'})
    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: