< back index next >

Data Structure

ASN.1 - Abstract Syntax Notation One

ASN.1 is a formal language to describe data structures. It consists of primitive data objects (boolean, integer, UTF8 string) that can be constructed to define more complex data structures (Sequences, Sets).

e.g.

Record ::= SEQUENCE
{
 Name::= UTF8 String
 Age::= Integer
 Vegetarian::= Boolean OPTIONAL
 Smoker::= [0] Boolean OPTIONAL
}

Based on ASN.1, instances of data structures can be defined:

Record
{
 Name::= "Möller"
 Age::= "30"
 Vegetarian::= "false"
 Smoker::= "true"
}

TLV - [T]ag [L]ength [V]alue

To encode ASN.1 instances in a computer readable form, a notation called TLV is used. Every data object consists of a tag, a length byte and the value/data.
The tag defines, for example, if the object is an integer, boolean or something else.

Tag
30 : Sequence
OC : UTF8 String
02 : Integer
01 : Boolean

Here we have the ASN.1 example from above encoded as TLV structure:

30 11 OC 06 4D 7E 6C 6C 65 72 02 01 1E 01 01 00 80 01 00

which means

Tag Length Value

30 11                   Sequence with a length of 17 bytes
OC 06 4D 7E 6C 6C 65 72 UTF8 String with a length of 6 bytes and the value Möller
02 01 1E                Integer with a length of 1 and the value 30
01 01 00                Optional Boolean with the value false
80 01 FF                Optional Boolean with the value true

Coding of the Tag

b8 b7 b6 b5 b4 b3 b2 b1 Meaning
0 0 universal class
0 1 application class
1 0 context specific class
1 1 private class
0 primitiv data object
1 constructed data object
x x x x x tag value
1 1 1 1 1 tag continoues on a 2nd byte

Optional Byte 2:
b8 b7 b6 b5 b4 b3 b2 b1 explanation
x b8 = 0 : this is the last byte of the tag
x x x x x x x tag value

Tags are divided into four classes defined by b8 and b7.

The universal class contains basic data types like integer, boolean, etc.

The application class is used for data elements defined by an application specification or industry standard (e.g. EMV).

The context specific class is used for data elements that are unique within it's enclosing context (Like the concept of local variables in a programming language). For example the second optional boolean "smoker" is a context specific class so that it has a tag different from "vegetarian".

The private class is used for all privately defined data objects.

Example

The SEQEUNCE tag '30' decodes to :
b8 b7 b6 b5 b4 b3 b2 b1
0  0                    = universal class 
      1                 = constructed
         1  0  0  0  0  = tag value

0011 0000
  '30'

  ---------------
  
The UTF8 String tag '0C' decoded:
b8 b7 b6 b5 b4 b3 b2 b1
0  0                    = universal class
      0                 = primitive
         0  1  1  0  0  = tag value

0000 1100
   '0C'

Length field

Depending on the length of the value field we have one or more bytes in the length field.

The length field has the following structure:

Number of length bytes Length of value Coding
1 0-127 0xxxxxxx
2 128-255 10000001 xxxxxxxx
3 256-65535 10000010 xxxxxxxx xxxxxxxx

For length encodings > 127, the first byte contains the number of subsequent bytes, while the most significant bit is set to 1. The actual length is then encoded as integer value on the subsequent bytes with the most significant byte first.

Here we have two examples read from a credit card using the reademv.js script:


Example 1:

A2 C: 00 A4 04 00 - SELECT Lc=7 
      0005  A0 00 00 00 04 10 10                             .......
      Le=0 
   R: SW1/SW2=9000 (Normal processing: No error) Lr=28
      0000  6F 1A 84 07 A0 00 00 00 04 10 10 A5 0F 50 0A 4D  o............P.M
      0010  61 73 74 65 72 43 61 72 64 87 01 01              asterCard...

// We will focus on the response value:
6F 1A 84 07 A0 00 00 00 04 10 10 A5 0F 50 0A 4D 61 73 74 65 72 43 61 72 64 87 01 01

Tag: "6F"
Application class
Primitive data object

Length: "1A"
'1A' = binary 00011010 = decimal 26 . There are 26 value bytes

Value:
"84 07 A0 00 00 00 04 10 10 A5 0F 50 0A 4D 61 73 74 65 72 43 61 72 64 87 01 01"

Example 2:

A2 C: 00 B2 01 1C - READ RECORD      Le=0 
   R: SW1/SW2=9000 (Normal processing: No error) Lr=195
      0000  70 81 C0 8F 01 04 9F 32 01 03 92 24 9F FB FB 7F  p......2...$....
      0010  EE C7 B0 43 67 B3 E4 C6 71 C3 0B 4A EE AD A2 C1  ...Cg...q..J....
      0020  93 49 58 DD 61 04 D1 50 EA FD 3C 05 2C 97 0E 8D  .IX.a..P..<.,...
      0030  90 81 90 52 D7 78 E3 33 2B 72 0F 4F E4 1D 7C 1B  ...R.x.3+r.O..|.
      0040  ED 06 45 EA 7D EF 14 E4 E3 6F 80 90 A1 42 B7 E1  ..E.}....o...B..
      0050  B1 7D DE CF AA 80 FC B4 BF 04 1C 2D 44 04 AD 1E  .}.........-D...
      0060  7F 19 C9 56 5B 93 7F 5E B5 02 90 6F EE 32 F5 21  ...V[..^...o.2.!
      0070  E5 32 AB FC 37 F0 46 1E 91 AA 46 79 8D 74 C4 BA  .2..7.F...Fy.t..
      0080  FA 08 81 A3 0E 1F 9B B8 7A B7 85 C7 E2 9A 45 46  ........z.....EF
      0090  D1 B7 FD 6F 98 A4 65 19 FB 7F 53 20 3A 93 AA C9  ...o..e...S :...
      00A0  5C 5B 53 B8 CC 6E 9A D3 DB C9 25 CC 72 B9 6E DD  \[S..n....%.r.n.
      00B0  78 3B B0 D7 B6 E8 E9 78 BB 35 5E 45 5E 7A 5B CA  x;.....x.5^E^z[.
      00C0  57 C4 95                                         W..

Tag: "70"
Application class
Constructed data object

Length: "81 C0"
1st byte '81' = binary 10000001 . There are two length bytes in the range 128 and 255.
2nd byte 'C0' = binary 11000000 = decimal 192. There are 192 value bytes.

Value:
"8F 01 04 9F 32 01 03 92 24 9F FB FB 7F EE C7 B0 43 67 B3 E4 C6 71 C3 0B 4A EE AD A2 C1 04 D1 50 EA FD 3C 05 2C 97 0E 8D 78 E3 33 2B 72 0F 4F E4 1D 7C 1B EF 14 E4 E3 6F 80 90 A1 42 B7 E1 B1 7D DE CF AA 80 FC B4 BF 04 1C 2D 44 04 AD 1E 7F 19 C9 56 5B 93 7F 5E B5 02 90 6F EE 32 F5 21 E5 32 AB FC 37 F0 46 1E 91 AA 46 79 8D 74 C4 BA FA 08 81 A3 0E 1F 9B B8 7A B7 85 C7 E2 9A 45 46 D1 B7 FD 6F 98 A4 65 19 FB 7F 53 20 3A 93 AA C9 5C 5B 53 B8 CC 6E 9A D3 DB C9 25 CC 72 B9 6E DD 78 3B B0 D7 B6 E8 E9 78 BB 35 5E 45 5E 7A 5B CA 57 C4 95"

< back index next >