TLV格式详解:BER-TLV、EMV TLV编码规则与解析
目录
一、TLV是什么
TLV(Tag-Length-Value)是一种广泛应用于智能卡、通信协议和数据交换领域的数据编码格式。TLV格式由三个字段组成:Tag(标签,标识数据类型)、Length(长度,指示数据字节数)、Value(值,实际数据内容)。
TLV是什么?简单说,它是一种自描述数据结构——任何TLV解析器都可以仅凭数据本身(无需外部schema)就能正确识别和提取每个数据元素。TLV编码的这种自描述特性使其非常适合带宽有限、处理能力受限的嵌入式环境,如智能卡、NFC标签和POS终端。
TLV编码在以下领域广泛使用:
- EMV支付:所有EMV标签数据(如卡号、有效期、公钥证书)均使用EMV TLV编码
- 智能卡:ISO7816标准中的FCI(文件控制信息)和数据对象使用BER-TLV
- ASN.1:抽象语法记法1的BER/DER编码本质上就是TLV结构
- LDAP协议、SNMP协议:均基于TLV或类TLV的数据编码
- NFC:NDEF消息格式使用类似TLV的Record结构
二、Tag字段详解
Tag(标签)是TLV三元组的第一个字段,用于标识数据的类型和语义。TLV Tag的长度为1到3字节,编码规则如下:
Tag字节结构(第一字节)
Tag首字节 = b8 b7 b6 b5 b4 b3 b2 b1
b8-b7: Class(类别)
00 = Universal class(通用类,如ASN.1定义的标准类型)
01 = Application class(应用类,如EMV应用数据)
10 = Context-specific class(上下文相关类)
11 = Private class(私有类,厂商自定义)
b6: Data Object 类型
0 = Primitive(基本类型,Value是原始数据)
1 = Constructed(构造类型,Value包含嵌套的子TLV)
b5-b1: Tag Number
如果 Tag Number = 11111 (0x1F),则使用多字节Tag扩展
多字节Tag扩展
当Tag Number需要大于30(0x1E)时,使用多字节Tag:首字节低5位全置1(=0x1F),后续字节的bit7=1表示"还有更多字节",bit7=0表示"Tag结束"。bit6~0拼接形成最终Tag Number。
# 单字节Tag示例
Tag 0x5A = 01 0 11010
Class=Application(01), Primitive(0), Tag Number=26
含义:EMV应用主账号(PAN,Primary Account Number)
# 两字节Tag示例
Tag 0x9F 0x33 = 100 1 11111 0 0110011
首字节: Class=Context(10), Constructed(1), Tag标识=31(需扩展)
第二字节: bit7=0(结束), Tag Number=51(0x33)
含义:EMV终端功能(Terminal Capabilities)
三、Length字段详解
TLV Length字段表示后续Value字段的字节长度。长度编码分为短格式和长格式:
短格式(Short Form)
如果长度值 ≤ 127(0x7F),Length字段使用1字节直接表示。最高位bit8 = 0。
Length = 0x08 → Value有8个字节
Length = 0x7F → Value有127个字节
长格式(Long Form)
如果长度值 > 127,Length字段首字节的bit8=1,bit7~1表示后续有多少个字节用于表示长度值。
# 长度=256的情况
Length = 82 01 00
0x82: bit8=1(长格式), bit7~1=2(后续2字节表示长度)
0x01 0x00 = 256
# 长度=65535的情况
Length = 82 FF FF
后续2字节 0xFFFF = 65535
四、Value字段详解
TLV Value是实际数据内容。根据Tag中b6(Primitive/Constructed)的不同:
- Primitive TLV:Value直接包含原始数据(如二进制数值、ASCII字符串)
- Constructed TLV:Value本身由多个嵌套子TLV组成,形成TLV嵌套结构(树形结构)
TLV嵌套是TLV最强大的特性之一:一个Constructed TLV的Value可以包含任意多个子TLV,每个子TLV又可以是Primitive或Constructed类型,从而实现任意深度的层次化数据表示。这正是EMV TLV能承载复杂支付应用数据(如公钥证书链、AFL应用文件定位器)的核心原因。
五、BER-TLV编码规则
BER-TLV(Basic Encoding Rules - TLV)是ISO7816-4和ASN.1 BER定义的标准TLV编码格式。BER-TLV的特点:
- Tag字段1~3字节,支持完整的Class和Constructed/Primitive语义
- Length字段支持短格式和长格式
- 支持无限长度编码(Length首字节=0x80,以EOC标记结束,但智能卡领域很少使用)
- EMV规范使用的TLV格式(EMV TLV)是BER-TLV的子集
六、EMV TLV编码规则
EMV TLV是BER-TLV在支付领域的特定应用。EMV规范(EMV Book 3)对TLV做了一些约束:
| 特性 | BER-TLV | EMV TLV |
|---|---|---|
| Tag长度 | 1~3字节(通用) | 1~2字节(EMV Co.定义了所有tag为1或2字节) |
| Length短格式 | ≤127(0x7F) | 同BER-TLV |
| Length长格式 | 支持 | 支持(但实际数据很少超过127字节) |
| 嵌套深度 | 无限制 | 实际最多3~4层 |
| DGI(Data Grouping Identifier) | 不存在 | EMV定义了DGI伪TLV用于分组 |
EMV Tag完整参考
关于所有EMV定义的Tag及其含义(Tag '5A'=PAN、Tag '5F24'=有效期、Tag '9F33'=终端功能等),请查阅本站的EMV Tag详解,其中列出了所有EMV标签的完整列表。
七、ASN.1 TLV区别
ASN.1 TLV(即BER/DER编码)是TLV概念的最早实现。ASN.1 TLV区别于BER-TLV,主要体现在:
| 维度 | ASN.1 BER-TLV | EMV/ISO7816 BER-TLV |
|---|---|---|
| 定义来源 | ITU-T X.690 | ISO/IEC 7816-4 Annex D / EMV Book 3 |
| Tag Class支持 | Universal/Application/Context/Private全支持 | 主要使用Application(01)和Context(10) |
| Universal Tag | 定义了标准类型Tag(INTEGER=0x02, OCTET STRING=0x04, SEQUENCE=0x30等) | 不使用Universal Tag |
| Schema依赖 | 有ASN.1 schema定义类型 | Tag值本身携带语义 |
| 典型应用 | X.509证书、PKCS、LDAP、SNMP | 智能卡APDU、EMV交易、NFC标签 |
延伸阅读
深入理解ASN.1的BER/CER/DER/PER编码规则,请阅读ASN.1完全教程。
八、TLV解析算法
TLV解析(TLV Parser)的核心算法是递归下降解析:
# TLV解析伪代码
def parse_tlv(data, offset=0):
results = []
while offset < len(data):
# 1. 解析Tag
tag, offset = read_tag(data, offset)
# 2. 解析Length
length, offset = read_length(data, offset)
# 3. 读取Value
value = data[offset:offset + length]
offset += length
# 4. 如果是Constructed类型,递归解析子TLV
if is_constructed(tag):
children = parse_tlv(value, 0)
results.append((tag, length, children))
else:
results.append((tag, length, value))
return results
TLV在线解析工具(见下文第十节)实现了上述算法,可以快速解析和可视化TLV数据。
九、TLV编码实例
以下是一个EMV TLV数据的完整解析实例:
# 原始TLV字节序列
5F 20 10 44 4F 45 2F 4A 4F 48 4E 20 4D 52 20 20 20 20 20
5F 24 03 26 12 31
5F 25 03 26 12 31
5F 28 02 01 56
5F 2A 02 01 56
5F 30 01 02
5F 34 01 01
5F 35 01 00
9F 33 03 60 E0 C0
# 解析结果:
Tag=5F20 Len=16 Val="DOE/JOHN MR " (持卡人姓名,ASCII)
Tag=5F24 Len=03 Val=26 12 31 (应用有效期,YYMMDD=261231)
Tag=5F25 Len=03 Val=26 12 31 (应用生效日期)
Tag=5F28 Len=02 Val=01 56 (发卡行国家代码,0156=中国)
Tag=5F2A Len=02 Val=01 56 (交易国家代码)
Tag=5F30 Len=01 Val=02 (服务码)
Tag=5F34 Len=01 Val=01 (应用PAN序列号)
Tag=5F35 Len=01 Val=00 (持卡人验证方法CVM列表)
Tag=9F33 Len=03 Val=60 E0 C0 (终端功能)
十、TLV在线解析工具
在实际开发中,TLV在线解析工具可以极大提高调试效率。以下是推荐的TLV在线工具使用场景:
- 开发调试:将POS日志中的十六进制TLV数据粘贴到在线工具,快速验证数据完整性
- 学习研究:查看Constructed TLV的嵌套结构,理解EMV数据层次
- 合规验证:检查卡片返回的TLV数据是否符合EMV规范要求的Tag列表
TLV解析常见错误
- Tag字节数判断错误:忘记检查多字节Tag扩展(0x1F),导致后续字节被误认为是Length
- Length长格式解析错误:混淆"Length的Length"与Length值本身
- Primitive/Constructed混淆:将Constructed TLV当Primitive处理,错过嵌套子TLV
- 字节序错误:TLV使用Big-Endian大端序
学习路径
TLV格式是智能卡数据编码的基础。推荐学习路径:ISO7816完整教程 → APDU命令大全 → TLV格式详解(本文)→ ASN.1完全教程 → EMV Tag详解(支付数据实战)。