How to decrypt magnetic track data using DUKPT

Tomcat

Professional
Messages
2,380
Reputation
4
Reaction score
407
Points
83
Recently I needed to decrypt card data from a magnetic stripe reader. It would seem that it is simple. I take the key and perform a certain decryption algorithm. But it was not there.

It turned out that my readers use a scheme known as DUKPT (Derived Unique Key Per Transaction). The idea behind this scheme is that for each transaction (or in our case, for each card rental) the data is encrypted using the key calculated for the individual card rental.

Thus, in order to decrypt data that has been encrypted using this scheme, you must be able to calculate the key for an individual card rental. The process of calculating such a key (session key) is far from simple.

The process is described in the document ANSI X9.24 part 1. However, the document costs approximately $140. Free, easily accessible documentation describing this process is difficult to find. The best resource I could find is here; there is a pretty good explanation of how IPEK (Initial Pin Encryption Key) is calculated. Unfortunately, this is only part of the complete scheme. In this post I will try to explain the DUKPT circuit in detail.

Definitions​


BDK : This is short for Base Derivation Key. This key is known only to the manufacturer and developer of the software that interacts with the magnetic track scanner.

IPEK : This is short for Initial Pin Encryption Key. This key is determined from the BDK. This key is downloaded to the device by the manufacturer and is used to generate future keys. Compromising IPEK does not compromise BDK.

KSN : This is short for Key Serial Number. KSN is a combination of the magnetic stripe scanner serial number and a counter for the number of card swipes that have been made on the device.

How it works​


The BDK is used by the manufacturer to generate the IPEK, which is downloaded to the device during development. The device uses IPEK and KSN to calculate the session key, which encrypts the data read from the card.

BDK is required by software developers to calculate IPEK. Once they receive the IPEK, they can request the KSN from the device. IPEK and KSN are used to obtain the key for an individual transaction/card rental. With these keys, developers can decrypt card data.

IPEK calculation​


To obtain the Initial Key Computation Key (IPEK), we need the Algorithm Base Key (BDK) and the Key Serial Number (KSN). IPEK is determined using the TripleDES algorithm. TripleDES is a simple DES algorithm performed in three passes.

The algorithm uses a key 24 bytes long. The DES algorithm is used three times, first with a key of 1-8 bytes, then 9-16 bytes, and finally 17-24 bytes separately for each pass.

TripleDES can use a 16-byte key, a method called EDE3. Bytes 1-8 will be used first, then 9-16 and again 1-8, producing a 24-byte key.

Some TripleDES implementations may not automatically use a short key. Before realizing this, I spent a lot of time trying to figure out what the problem was. Assuming that this was a special implementation of TripleDES, I used an emitted 24 byte key of 16 bytes.

After much torment, it occurred to me to try to take the first 8 bytes and add them to the end of the key before passing it to the TripleDES algorithm. This solved the problem.

Details​


IPEK consists of two 8-byte parts, which are obtained as a result of two separate passes of the TripleDES algorithm. Both are obtained by encrypting the high 8 bytes of KSN with the counter reset. The difference between the left and right sides is that the right side is obtained by encrypting KSN using a slightly modified version of the BDK. I will describe this process below.

Let's assume there is a 16 byte BDK represented by the hexadecimal string "0123456789ABCDEFFEDCBA9876543210". We also have a 10 byte KSN with a counter equal to 8, represented by the hexadecimal string “FFFF9876543210E00008”.

Let's get the BDK to encrypt the left side of the IPEK by adding the first 8 bytes to the end of the BDK, this will be the next 24 byte key.

0123456789ABCDEFFEDCBA98765432100123456789ABCDEF

If the length of KSN is not 10 bytes, then we pad it to 10 bytes of hexadecimal “F” (1111). It is important to note that the IPEK is the very first key on the device. This means that we calculate it with a counter in KSN equal to 0. To get a KSN with a counter of 0, we impose a mask on it with a hexadecimal representation of which is the string “FFFFFFFFFFFFFE00000”.

FFFF9876543210E00008
and FFFFFFFFFFFFFFE00000
= FFFF9876543210E00000

Amazing. Now we have a zero KSN. However, we need the upper 8 bytes of KSN. We obtain them by shifting the KSN to the right by 16 bits.

FFFF9876543210E00000 >> 16 = FFFF9876543210E0

Great. The next step is TripleDES encryption of the string “FFFF9876543210E0” using the 24-byte BDK key “0123456789ABCDEFFEDCBA98765432100123456789ABCDEF”. The result of this encryption will be the left side of the IPEK.

6AC292FAA1315B4D

If you remember, I mentioned that a slightly modified version of the BDK will be used to obtain the right part. So, to do this, we need to take the original 16 byte BDK "0123456789ABCDEFFEDCBA9876543210" and XOR the following mask "C0C0C0C000000000C0C0C0C000000000". This appears to be a completely arbitrary mask, but alas, it is necessary to obtain the correct IPEK.

0123456789ABCDEFFEDCBA9876543210
xor C0C0C0C000000000C0C0C0C000000000
= C1E385A789ABCDEF3E1C7A5876543210

We will do the same thing as we did with the key for the left side, take the most significant 8 bytes and add them to the end, we will get the next 24 byte key.

C1E385A789ABCDEF3E1C7A5876543210C1E385A789ABCDEF

Next, let's take the most significant 8 bytes of KSN with a zero counter (which we calculated earlier) and encrypt it using TripleDES with the key we just calculated. This will give us the right IPEK register, giving us the next 16 byte IPEK (I separated the left and right parts for clarity).

6AC292FAA1315B4D 858AB3A3D7D5933A

Calculating session keys​


We have IPEK. Next, we need to obtain a unique key from IPEK for individual card rental (session key). To obtain it, a certain subroutine is used, let's call it a black box, the purpose of which is to return a separate session key. What happens in the black box is not our concern yet. Right now we'll look at the input of this subroutine.

Our black box has two inputs. One is the key and the second is the encryption string. The line represents the modified KSN.

If you remember, the lower 21 bits of KSN contain a counter for the number of card rentals on the device. We will pass the modified KSN to the subroutine as many times as there are units in the binary representation of the counter. The key that is transmitted with the modified KSN is IPEK at the first iteration, and at subsequent iterations it will be the key obtained from the black box at the previous iteration.

Let's start with changing KSN. First, we will take the low 8 bytes of KSN and reset the counter value in KSN. This can be done by masking the KSN using the following mask.

FFFF9876543210E00008
and 0000FFFFFFFFFFE00000
= 00009876543210E00000

We will use the resulting value to calculate each message sent to the black box. In our example with a counter of 8, we must pass the binary representation of the number 8 (1000) to the black box. For demonstration, let's assume the counter has a more complex value of 10 (1010).

We will extract a set of binary numbers from the counter. In our case, for the number 10 (1010), there will be two binary numbers: 1000 and 0010. Do you catch the pattern? We get a set of numbers representing each binary unit of the number 10.

Next, we take the first number and OR it with the KSN, which has its counter reset to zero, as shown earlier (note that the hexadecimal representation of the first number is 0008).

9876543210E00000
OR 0000000000000008
= 9876543210E00008

Now we pass the IPEK as a key and the newly modified KSN to the black box. The black box will return a new key. This is the first session key (represented in hexadecimal): "27f66d5244ff62e1aa6f6120edeb4280".

Next, we repeat the process with the next binary number calculated earlier, 2 (0010). This time, we will use the first session key that we just received and calculate a new modification of KSN.

To calculate a new KSN modification, we will perform an OR operation with the last received modification: 9876543210E00008.

9876543210E00008
OR 0000000000000002
= 9876543210E0000A

Now let’s transfer our new key “27f66d5244ff62e1aa6f6120edeb4280” and the new modification of KSN “9876543210E0000A” to the black box and get another future key, “6cf2500a22507c7cc776ceadc1e33014”. This is the session key for our device with a counter of 10.

However, our real counter was 8, and we calculated the real session key “27F66D5244FF62E1AA6F6120EDEB4280” in the first step.

The last operation we must perform with the received value is the final transformation of the key with which we will decrypt the data. We must XOR the key with the mask “00000000000000FF00000000000000FF”.

27F66D5244FF62E1AA6F6120EDEB4280
XOR 00000000000000FF00000000000000FF
= 27F66D5244FF621EAA6F6120EDEB427F

This is the key that is required to decrypt the data.

Black box​


I called the algorithm that calculates session keys a black box. The black box accepts the current session key, which I'll denote as current_sk , and the KSN modification, which I'll denote as ksn_mod .

If at the beginning the assumption is that the IPEK received above was passed as current_sk and ksn_mod was equal to the value “9876543210E00008” that we calculated above.

First we need to take current_sk , get the high 8 bytes and shift them 64 bits to the right, we get “6AC292FAA1315B4D”. This can be achieved using a bitmask.

6AC292FAA1315B4D858AB3A3D7D5933A
AND FFFFFFFFFFFFFFFF0000000000000000
= 6AC292FAA1315B4D0000000000000000

Here we need to shift this value 64 bits to the right to get "6AC292FAA1315B4D". Let's call it left_key (looks like the left side of current_sk ).

Next, we get the 8 low bytes of current_sk using a mask.

6AC292FAA1315B4D858AB3A3D7D5933A
AND 0000000000000000FFFFFFFFFFFFFFFF
= 0000000000000000858AB3A3D7D5933A

Let's call this value (you guessed it) right_key . Next, take right_key and perform XOR with ksn_mod “9876543210E00008”.

858AB3A3D7D5933A
AND 9876543210E00008
= 1DFCE791C7359332

Let's call this value message. Next, we take the message and encrypt it using DES (simple DES). We will pass the message algorithm to DES as the data that needs to be encrypted, and left_key as the key that needs to be encrypted. The result will be “2FE5D2833A3ED1BA”. Now we need to XOR this value with right_key .

2FE5D2833A3ED1BA
XOR 858AB3A3D7D5933A
= AA6F6120EDEB4280

This is the value of the lower 8 bytes of our session key! Now we need to repeat the operations just described with other input data. This time we take current_sk and XOR it with "C0C0C0C000000000C0C0C0C000000000". This value is arbitrary as far as I can tell, but it is part of the ANSI standard, so you'll just have to take my word for it.

6AC292FAA1315B4D858AB3A3D7D5933A
XOR C0C0C0C000000000C0C0C0C000000000
= AA02523AA1315B4D454A7363D7D5933A

If we take the value "AA02523AA1315B4D454A7363D7D5933A" and substitute it for current_sk in the operation described above, we will get "27F66D5244FF62E1". These are the most significant 8 bytes of our session key. Combining them we get “27F66D5244FF62E1AA6F6120EDEB4280”.

Conclusion​


I hope I have explained the DUKPT circuit and how it relates to the efficiency of magnetic trace scanners. I welcome corrections and questions in the comments section.

(c) https://www.parthenonsoftware.com/blog/how-to-decrypt-magnetic-stripe-scanner-data-with-dukpt/
 
Top