Understanding EMV , Introduction to TLV.

Ayooluwa Olosunde
5 min readApr 9, 2023

--

tlv encoding explanation

EMV is a global standard for credit and debit payment cards based on chip card technology. In the previous two articles in this series, we discussed the basics of EMV and the role of APDU command in EMV. In this article, we will delve deeper into the EMV payment process and explore one of the fundamental components of EMV transactions: TLV encoding.

INTRODUCTION TO BER-TLV

TLV or sometimes called BER-TLV, which stands for Basic Encoding Rules — Tag Length Value, is a data encoding scheme used in payment processing systems. In simple terms, it is a method of encoding data in a standardized format that can be easily interpreted by different software systems.

BER-TLV is widely used in the payment industry because it provides a reliable way of transmitting data between different systems. Payment data such as credit card information and transaction details are encoded using BER-TLV and then sent securely over the network. This ensures that the data is not only secure but also accurately interpreted by the receiving system.

TLV stands for Tag-Length-Value, which is a way of encoding data in a structured format. In a TLV data stream, each piece of data is represented by a tag, a length, and a value, as follows:

  1. Tag: A tag is a unique identifier that identifies the type of data being represented. The tag is typically encoded as a binary value or as a hexadecimal string. For example, in EMV payment card data, a tag might represent the cardholder’s name or the expiration date of the card.
  2. Length: The length specifies the size of the value field in bytes. The length field can be one, two, or more bytes in length, depending on the size of the value field. The length field is typically encoded as a binary value or as a hexadecimal string.
  3. Value: The value is the actual data being represented. The value can be any data type, including binary data, ASCII text, or numerical data. The value field is typically encoded as a binary value or as a hexadecimal string.

Here is an example of TLV data representing the cardholder’s name on an EMV payment card:

5F20 0F 4D696B65204A6F686E20536D697468

In this example, the tag 5F20 identifies the data as the cardholder's name. The length field 0F indicates that the value field is 15 bytes long. The value field 4D696B65204A6F686E20536D697468 represents the ASCII text "Mike John Smith".

EXAMPLE OF DATA ENCODED IN TLV

Let’s assume that we have a credit card that sends its data in TLV format. The data contains the cardholder’s name, card number, and expiration date, each of which is represented by a unique tag.

tlvData = "5F200C4A6F686E20536D6974688701015A0F12345678901234565F2403032331F" // Raw TLV data

This is a sample data coming from the card that contains the cardholder's name,
expiration date and the card number

when decoded, it gives us the details below

Tag 5F20: Length: OC(12) Value: (4A6F686E20536D697468870101)John Smith // Cardholder's name
Tag 5A: Length: 0F(15) Value: 1234567890123456 // Card number
Tag 5F24: Length: 03(3) Value: 032331 // Expiration date (MMYY)

In this example, the tag 5F20 represents the cardholder’s name, tag 5A represents the card number, and tag 5F24 represents the expiration date.

DECODING USING A PROGRAMMING LANGUAGE

As a software developer, understanding BER-TLV is crucial when working on payment processing systems. The data format plays a critical role in ensuring the accuracy and security of financial transactions. Developers need to know how to parse BER-TLV encoded data and how to generate BER-TLV encoded data to ensure compatibility with other systems.

To interpret this TLV data using Kotlin, we can use a library such as TLVParser, which provides a simple and efficient way to parse TLV data. Here’s an example of how we can use the TLVParser library to parse the TLV data and extract the cardholder’s name, card number, and expiration date:

val tlvData = "5F200C4A6F686E20536D6974688701015A0F12345678901234565F2403032331F" // Raw TLV data

val parser = TLVParser()
val tlvList = parser.parse(tlvData)

for (tlv in tlvList) {
when (tlv.tag) {
"5F20" -> {
val cardholderName = tlv.value.decodeToString()
println("Cardholder's name: $cardholderName")
}
"5A" -> {
val cardNumber = tlv.value.decodeToString()
println("Card number: $cardNumber")
}
"5F24" -> {
val expirationDate = tlv.value.decodeToString()
println("Expiration date: $expirationDate")
}
else -> {
// Unknown tag
}
}
}

In this example, we first define the TLV data as a raw string. We then create a new instance of the TLVParser class and use it to parse the TLV data. The parser returns a list of TLV objects, each of which contains a tag and a value.

We then iterate over each TLV object in the list and use a when expression to check the tag of each TLV object. If the tag matches one of the tags we’re interested in (5F20, 5A, or 5F24), we extract the value of the TLV object and print it to the console.

Overall, this example demonstrates how TLV data can be passed from a card and how it can be easily parsed and interpreted using Kotlin programming language.

LIBRARY THAT CAN BE USED FOR DECODING TLV ENCODED DATA

There are several libraries available for decoding TLV data in various programming languages. Here are a few examples:

  1. TLV Decoder for Java: This library provides a simple and lightweight implementation of a TLV decoder for Java applications. It supports TLV data with one or two-byte length encoding and provides a simple API for parsing TLV data.
  2. C#: The NDEF Library for Proximity APIs provides a Tlv class for decoding TLV data in C# applications. This library supports various TLV formats, including EMV and ISO 7816-4.
  3. Python: The PyTLV library provides a simple API for decoding and encoding TLV data in Python. This library supports various TLV formats, including EMV and BER-TLV.
  4. Ruby: The TLV library provides a simple API for decoding and encoding TLV data in Ruby. This library supports various TLV formats, including EMV and BER-TLV.
  5. Node.js: The tlv library provides a simple API for decoding and encoding TLV data in Node.js. This library supports various TLV formats, including EMV and BER-TLV.

These libraries can save you a lot of time and effort in implementing a TLV decoder from scratch. However, it’s important to note that you should always review the documentation and code of any third-party library you choose to use, to ensure it meets your specific requirements and security standards.

CONCLUSION

In conclusion, BER-TLV is an essential data encoding scheme used in the payment industry. It ensures the secure and accurate transmission of payment data between different systems, making it a critical component of payment processing. As a software developer, having a solid understanding of BER-TLV is necessary when working on payment processing systems.

See you later guys ✌️❤️✌️❤️✌️❤️✌️❤️✌️❤️✌️❤️✌️❤️✌️❤️

--

--