Personalizing test (U)SIM cards for different customers, a new challenge arose where a customer actually wanted different serial numbers on the cards. Our test cards have the same ICCID number on all cards. Anyway, this is handled by the file 2F E2 - IC Card Identifier, under MF. This file contains the IC card's serial number coded on 10 bytes and allows the operator to identify the card unambiguously for billing purposes.

The coding of the serial number for cards of Phase2/2+ onwards it is defined in ITU-T E118. CCITT E118 specifies a Serial Number length between 0 and 18 digits plus an extra byte containing a **checksum** written in its least significant (that is, rightmost) digit. The checksum is always stored in this byte whatever the length of the serial number (if the serial number is shorter than 18 digits it is padded (One or more bits appended to a message in order to ensure that it contains the required number of bits or bytes.) with Fh up to digit 20. Coding the serial number on 20 digits overwrites the checksum. Some operators today use 19 digits followed by the checksum without any padding.

It's composed of the following subparts:

– Major Industry Identifier (MII);

– country code;

– issuer identifier;

– individual account identification number;

– parity check digit

Now, using a tool like Gemalto Card Admin I can automatically get the correct **checksum** for the ICCID I choose to enter. But in our automated processes where we use APDU scripts, I needed to know how to calculate this checksum so it could be automatically appended to the serial number and the card correctly personalised.

I found out that the **Luhn algorithm** or **Luhn formula**, also known as the "modulus 10" or "mod 10" algorithm, is used to calculate the checksum.

So very simply, assume an example of a serial number "896588081210001114" that will have a check digit added, making it of the form 896588081210001114x:

ICCID | 8 | 9 | 6 | 5 | 8 | 8 | 0 | 8 | 1 | 2 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 4 | |

Double every other | 8 | 18 | 6 | 10 | 8 | 16 | 0 | 16 | 1 | 4 | 1 | 0 | 0 | 0 | 1 | 2 | 1 | 8 | |

example: 18=>8+1=9 | 8 | 9 | 6 | 1 | 8 | 7 | 0 | 7 | 1 | 4 | 1 | 0 | 0 | 0 | 1 | 2 | 1 | 8 | Sum of digits= 64 |

First double every other number starting from the end. Add the digits if >1. For example 18=1+8=9

The check digit (x) is obtained by computing the sum of digits then computing 9 times that value modulo 10 (so that's: (67 * 9 mod 10)). In layman's terms:

- Compute the sum of the digits (64).
- Multiply by 9 (576).
- Take the last digit (6).
- The result is your check digit.

So in this case the complete ICCID is 8965880812100011146

Example:

- -The first two digits are fixed and are the Industry Identifier. “89” refers to the Telecommunications Industry.-The next two or three digits refer to the Mobile Country Code (MCC) as defined by ITU-T recommendation E.164. “310” refers to the United States.
- -The next one to four digits refer to the Mobile Network Code (MNC). This is a fixed number for a country or world zone. “410” refers to the operator, AT&T Mobility.
- -The next two digits, “10,” pertain to the Home Location Register.

- Individual Account Information - is variable in length:

- -The next nine digits, “654378930” represent the individual account identification number. Every number under one IIN has the same number of digits.

- Check Digit – the last digit, “1,” is computed from the other 18 digits using the Luhn algorithm.

Created : 2016-04-29 10:13:06, Last Modified : 2017-06-14 14:53:31

Below you'll find our PGP public key. Use it to exchange encrypted messages with us.

-----BEGIN PGP PUBLIC KEY BLOCK-----

Version: PGP Universal 3.4.2 (Build 502)

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

b0sfmPZ3

=jOBj

-----END PGP PUBLIC KEY BLOCK-----