Let’s Demystify that 20-digit utility token-Part 2

Mwangi Patrick
CodeX
Published in
7 min readJul 30, 2021

--

Welcome to part 2 of this interesting series where we uncover STS tokens. In the previous post, we discussed decoder key generation. That was important because the decoder key is used in both encryption and decryption of the information within the token. You must recall that this decoder key is stored inside you meter, whereas the service provider generates a similar one on the fly during token purchase by using your meter number. In this post, we will explore the sections that make up a token and their significance. If you are not familiar with the basics you can find them by reading part 1.

Token Format

Before being converted to a 20-digit number, a token is normally in binary form (0 and 1). Inside this binary data block is the token class, subclass, random number (RND), token identifier (TID), utility amount and a cyclic redundancy check (CRC) block. The entire data block is 66 bits, that is a total of 66 (0s and 1s).

Figure 1: Token data block

The token class defines the type of token. Class 0 tokens are credit tokens, i.e. they are used to credit your meter with more units. Class 1,2 and 3 tokens also exist for additional configurations e.g. clearing of credit from the meter of a customer who accidentally over-purchased. We will concentrate on class 0 henceforth. Other token sections will be relevant to class 0 tokens only.

Subclass defines the type of utility. It is a number between 0 and 15. Subclass 0 is used for electricity,1 for water, 2 for gas, 3 for time etc. The random number range is 0–15 and is generated to ensure no token has a similar binary signature to another. Token identifier is the date and time of token issue and is represented in terms of the number of minutes since the base date. For some meters manufactured before 2014, the base date is 1st January 1993. These meters will have to be updated by 24th November 2024 in order to have a base date of 2014. Otherwise they will no longer accept tokens. This rollover happens every ~31 years and this post will show you why. The amount section contains the number of units a customer has been allocated whereas the CRC is used to ensure the data block is authentic and not corrupted. More about it in the coming paragraphs.

Binary Basics

This section is vital in putting you up to speed because a lot of binary is coming our way and understanding the basics will make it so easy to grasp the entire process. A computer stores information in binary form. The smallest unit of data that can be stored is 1 binary digit (bit) which is either a 1 or 0. A binary block can be converted to a decimal (a number like 1,5,19 etc) and vice versa. Consider the binary 0111 as shown;

Figure 2: Binary Form

To get the decimal value of that binary block of data we can use the formula; 2³ * b0 + 2² * b1 + 2¹ * b2 + 2⁰ *b3 generalized as the sum of 2^bit_position * bit value at that position. That translates to 2³ * 0 + 2² * 1 + 2¹ * 1 + 2⁰ * 1 = 7. Bit positions are greatest to the left as the left most bit is the most significant. Revisiting the table shown in Figure 1, we notice that the token class is represented by just 2 bits. These two bits can represent 4 different numbers. For instance binary 00 translates to decimal number 0, 01 translates to 1,10 translates to 2 and 11 translates to 3. You can confirm by using the formula given above only that the bit positions here are 1 and 0, given there are only 2 bits. Similarly for the subclass and random number, 4 bits can represent 16 different numbers. Binary 0000 translates to 0, whereas 1111 translates to 15. You can use this online tool for quick conversion. With this knowledge, you will be in a position to understand the upcoming sections.

Token Identifier (TID)

The token identifier is a very important part of the entire token block. This timestamp value is the main reason why you cannot reuse your token. Once a valid token is entered, the TID is saved in a table. A token with the same TID is rejected on entry. As stated previously, the value is calculated as the number of minutes that have elapsed since the base date. The minutes are subsequently converted into a 24 bit binary number. It is important to note that the seconds are truncated and do not count in the calculation of elapsed minutes. Take a look at the example below.

Figure 3: Token Identifier Calculation Sample

Here’s something interesting. Assuming you purchase tokens a number of times within the same minute for a single meter. The vending unit has to increment the TID by one minute for every token generated after the first one and later resets. This prevents the tokens you have just purchased from sharing a common TID that would lead to acceptance of only one token and rejection of the rest.

The maximum value of the TID in binary form is 111111111111111111111111. It translates to 16,777,215 minutes, about 31.9 years after which it rolls over to 0. This is the reason why the base date in a meter has to be updated to the recent base date. Meters with base date 93 have to be updated to base date 14 (represents 2014) and will later be updated to base date 35 (represents 2035) to handle this rollover and continue accepting tokens.

Utility Amount

The amount field takes up 16 bits in the token block and unlike the TID, the formula for calculating the amount in decimal from binary is different. The amount data block has the following structure;

Figure 4: Amount data block

In the above diagram e is the base 10 exponent whereas m is the mantissa. Don’t let that confuse you. Given that this is binary, the decimal value of e is obtained by converting the two bits at position 15 and 14 as if they were just at position 1 and 0 respectively. The decimal value of m is obtained by converting the binary number starting at bit position 13 to bit position 0. For example, consider an amount block 0100000000000101. To calculate the exponent and mantissa we have to split the block. Binary 01 for exponent and 00000000000101 for the mantissa. Using the formula discussed in the binary basics section, the decimal value of the exponent is 1 whereas the value of the mantissa is 5. With the exponent and mantissa the number of units for electricity can be calculated using the following formulas;

Figure 5: Formula 1
Figure 6: Formula 2

Our example amount block requires the second formula because the exponent is greater than 0. The number of kilowatt hours the customer receives would be computed as (10¹ * 5 + 2¹⁴ *10⁰ )/10 = 1643.4 units. Each value of e offers different ranges of transfer amounts depending on the value of the mantissa.

Figure 7: Exponent and corresponding amount range

Using the above range of values makes it possible to compute an amount block in binary from its initial decimal state by simply working the formula backwards.

Cyclic Redundancy Check (CRC)

CRC is used as an error checking technique in data processing to check for any accidental changes in the token block. The CRC method used for STS tokens is CRC-16 (Modbus) with a generator polynomial of the value x¹⁶+x¹⁵+x²+1 whose binary form is 11000000000000101. The reason for that binary form is because only bit positions 16, 15, 2, and 0 have a coefficient of 1 in the generator polynomial. All other bit positions have a coefficient of 0. After the CRC is calculated, the value is appended to the token data block and is used during the error checking process inside the meter. If you are curious about CRC, someone made a nicely explained video including a step by step calculation guide. You can watch the video here.

Code Examples

With all the information discussed, we are going to construct a token data block and display it in binary form. This is its raw form before it undergoes the encryption process using a decoder key. This data block is only 64 bits as the initial class bits are inserted into the block after it has been encrypted. However, the 2 class bits are present during CRC calculation. The diagram below shows what we will be simulating. In order to guarantee the same result, the random number will be constant. So will the issue date and time even though in real life both fields are constantly changing.

Figure 8: Token block building

Running the above code gives us an output similar to what we have in Figure 8.

Figure 9: Program Output

As usual you are free to run the code and view the output by clicking the link below;

Once again, we have gone deeper and explored the structure of a token and the process by which the token block is built. In the next post, we will check out encryption and build a program to encrypt the token and convert it into a 20-digit output representing what a customer receives. I hope you have enjoyed and learnt a lot from this series so far.

See ya in Part 3 and thanks for reading!

--

--

Mwangi Patrick
CodeX

Fullstack Software Engineer with a preference for Backend. Does small desktop applications during free time. In love with aircrafts.