银联55域TLV子域信息说明
基本信息子域列表
子域中文名称 | 子域英文名称 | 子域缩写 | 子域tag标签值 | 子域所占长度 (单位:字节) | 子域属性 |
应用密文 | Application Cryptogram | AC | 9F26 | 8 | B |
密文信息数据 | Cryptogram Information Data | - | 9F27 | 1 | B |
二磁道信息 | 57 | ||||
银行卡号 | | ||||
发卡行应用数据 | Issuer Application Data | IAD | 9F10 | 最大到32 | B |
不可预知数 | Unpredictable Number | - | 9F37 | 4 | B |
应用交易计数器 | Application Transaction Counter | ATC | 9F36 | 2 | B |
终端验证结果 | Terminal Verificaion Result | TVR | 95 | 5 | B |
交易日期 | Transaction Date | - | 9A | 3 | CN(包含6位有效数字,格式YYMMDD) |
交易类型 | Transaction Type | - | 9C | 1 | CN(包含2位有效数字) |
授权金额 | Transaction Amount or Amount Authorized | - | 9F02 | 6 | CN(包含12位有效数字) |
交易货币代码 | Transaction Currency Code | - | 5F2A | 2 | CN(包含3位有效数字) |
应用交互特征 | Application Interchange Profile | - | 82 | 2 | B |
终端国家代码 | Terminal Country Code | - | 9F1A | 2 | CN(包含2位有效数字) |
其它金额 | Amount Other | - | 9F03 | 6 | CN(包含12位有效数字) |
终端性能 | Terminal Capabilities | - | 9F33 | 3 | B |
可选信息子域列表
子域中文名称 | 子域英文名称 | 子域缩写 | 子域tag标签值 | 子域所占长度 (单位:字节) | 子域属性 |
持卡人验证方法结果 | Cardholder Verfication Method Results | CVM | 9F34 | 3 | B |
终端类型 | Terminal Type | - | 9F35 | 1 | CN(两位有效数字) |
接口设备序列号 | Interface Device Serial Number | IFD | 9F1E | 8 | AN |
专用文件名称 | Dedicated File Name | DF | 84 | 5~16 | B |
应用版本号 | Terminal Application Version Number | - | 9F09 | 2 | B |
交易序列计数器 | Transaction Sequence Counter | - | 9F41 | 2~4 | CN(包含4到8个有效数字) |
发卡行认证数据 | Issuer Authentication Data | - | 91 | 8~16 | B |
发卡行脚本1 | Issuer Script Template 1 | - | 71 | var. up to 128 | B |
发卡行脚本 2 | Issuer Script Template 2 | - | 72 | var. up to 128 | B |
发卡方脚本结果 | Issuer Script Results | - | DF31 | var. up to 21 | B |
Form Factor Indlicator(FFI) | Form Factor Indlicator(FFI) | - | 9F6E | 4 | B |
脱机交易专用子域列表
子域中文名称 | 子域英文名称 | 子域缩写 | 子域tag标签值 | 子域所占长度 (单位:字节) | 子域属性 |
授权响应码 | Authorization Response Code | - | 8A | 2 | an |
TLV是一种可变格式,意思就是:
Type类型, Lenght长度,Value值;
Type和Length的长度固定,一般那是2、4个字节(这里统一采用4个字节);
Value的长度有Length指定;
解码方法:
1. 读取type 用ntohl转换为主机字节序得到类型,指针偏移+4
2. 读取lengh用ntohl转换为主机字节序得到长度;指针偏移+4
3. 根据得到的长度读取value,若value数据类型为int、char、short,用ntohl转换为主机字节序,指针偏移+4;若value数据类型为字符串类型,指针偏移+length
类型(Type)字段是关于标签和编码格式的信息;
长度 (Length)字段定义数值的长度;
内容(Value)字段表示实际的数值。
因此,一个编码值又称TLV(Type,Length,Value)三元组。编码可以是基本型或结构型,如果它表示一个简单类型的、完整的显式值,那么编码就是基本型 (primitive);如果它表示的值具有嵌套结构,那么编码就是结构型(constructed)。
以上是对tlv的简单解释,从网上搜集的资源来看,用C、C++来写的开源软件都非常的复杂,我这里使用了很少的OC代码实现了一个简单实用的TLV解析库,供各位参考使用
例1.报文81 29 40 2c XX XX XX...
tag:
对应前2个字节为:81 29(该值没啥具体含义,实际可能为工作中定义的一些标签)
length:
我们首先长度域的第一个字节40,0x40二进制 0100 0000,最高位为0,因此0x40就代表value该TLV的value域长度,即value域长度为从第四个字节2c开始往后(包含2c)的64个字节。
value:
2c开始往后64个字节。
例2.报文81 29 07 2c XX XX XX...
tag:
对应前2个字节为:81 29
length:
长度域第一个字节为07查看表格在范围0x00-0x7f,即长度域为就占1个字节。对应二进制0111,最高位至0,因此value域的长度为0111,7个字节
value:
2c开始往后7个字节。
BER 编码一种,ASN.1标准 ASN.1 浅析,全称 Type(类型),Length(长度),Value(值)。
IS-IS 数据通信领域中,TLV 三元组:
Type-length-value(TLV)
T、L 字段的长度往往固定 ( 通常为 1~4bytes )
V 字段长度可变
T 字段表示报文类型,L 字段表示报文长度、V 字段往往用来存放报文的内容。
TLV 结构数据解析:
TAG 类别:
分为 3 部分,最高两位,第六位和低五位,其具体表示含义如下;
编码规则:
1、第一个字节的 bit8~bit7 位标识 tag 所属类型
00 通用级 universal class
01 应用级 application class
10 规范级 context-specific class
11 私有级 private class
在智能卡中见得较多的是应用类与上下文相关类,通用类与行业无关,只有一个(0x06:Object Identifier);
应用类很多如前文中的 0x6F,还有经常碰到的 0x4F 表示 AID (应用标识符),在7816中定义。
0x6F: '0110 1111'
0x4F: '0100 1111'
2、第一个字节的 bit6 位标识本 tag 的 value 部分是否包含子 tag
3、第一个字节的 bit5~bit1 位标识是否需要配合第二个字节一起标识 tag
全为 1 表示需要第二个字节
4、第二个字节 bit8 为 1,同时 bit7~bit1 大于 0 表示有下一个 tag
5、第三~N个字节同第二个字节
TAG 编号:
例如:
TLV 结构十六进制字节流:
6F328407A0000000031010A5278701019F38129F1A029F33039F40059F1B049F09029F35015F2D086573656E667264659F110101
tag 为 0x6F,lenth 为 0x32,后面为 0x32=50 个字节的 value 值。
TLV 有两种格式:
BER、嵌套格式
示例是一个复合的嵌套格式:
一个父节点:0x6F
有两个子节点 0x84、0xA5
0x84 节点是不可再分的基础格式
0xA5 节点又是一个父节点
可以再拆分为 4 个子节点 87、 9F 38、 5F 2D、 9F 11
编码解析和过程:
1、根据第一个字节分解,bit1–bit5 判断 tag 长度,bit6 判断是否是复合 tag
2、根据 tag 长度,找到 len,根据 len 画出后面数据长度
3、根据是否是复合结构,继续循环如上分解过程
几乎所有的需要在卡片和终端之间传送的数据都是TLV格式的.
TLV是tag, length和value的缩写.一个基本的数据元就包括上面三个域. Tag唯一标识该数据元, length是value域的长度. Value就是数据本身了. 举个例子, 下面是一个tlv格式的AID(应用标识符)字节串”9F0607A0000000031010”, 其中9F06是tag, 07是长度, A0000000031010就是AID本身的值了.
对于程序编写人员来说,如果有类似上面这样的一串TLV编码的字节串从卡片传过来, 怎么样从中提取我们想要的数据. 这就牵扯出TLV解码的问题了
TLV一种可变格式,TLV的意思就是:Type类型, Lenght长度,Value值;
Type和Length的长度固定,一般那是2、4个字节;
Value的长度有Length指定;
解析方法:
1.读取type 转换为ntohl、ntohs转换为主机字节序得到类型;指针偏移+2或4
2.读取lenght,转换为ntohl、ntohs转换为主机字节序得到长度;指针偏移+2或4
3.根据得到的长度读取value,指针偏移+Length;
。。。。
继续处理后面的tlv;
TLV编码就是指先对Tag编码,再对Length编码,最后对Value编码。BER编码的长度确定的编码方式就是这样的。
BER编码有两种方式:
一种是长度确定的编码方式。这由3部分组成Identifier octets、Length octets和Contents octets(可以和TLV对应)。另一种是长度不确定的编码方式。这由4部分组成Identifier octets、Length octets、Contents octets、End-of-contents octets。其中Length octets为0x80,End-of-contents octets为0x00 00。每种类型都能够编码成长度确定的编码方式,但是有的类型不能够编码成长度不确定的编码方式。DER编码只能使用长度确定的编码方式。
Identifier octets由3部分组成Class、P/C和Tag number。Identifier octets的第一个字节的高2位为Class,接下来一位为P/C,其他位表示Tag number。Class有4中类型Universal(00)、Application(01)、Context-specific(10)和Private(11)。P/C位如果为1则表示是Constructed的,为0表示是Primitive。如果0<=Tag number<=30,则整个Identifieroctets只有一个字节,否则第一个字节的后5位前为1,接下来找第一个最高位为0的字节,该字节就是Identifier octets的最后一个字节。从第二个字节到最后一个字节去掉最高位的值拼起来就是Tagnumber的值。
长度确定的编码方式的Length octets有两种方法编码长度,一种是只用一个字节表示长度,其最高位为0,后7位表示长度值,显然这样只能表示0-127。另一种是第一个字节的最高位为1,其他位表示后面还有多少个字节属于Length octets。后面的那些字节组成的就是长度值。长度值表示的是Contents octets所占的字节数。DER要求如果长度为0-127则要使用第一种方式,如果大于127则使用后一种方式。
其中BER-TLV编码是ISO定义一种规范,然后到了PBOC/EMV里被简化了, 哪里被简化了呢?举一个例子, tag域在ISO里可以有多个字节, 而PBOC/EMV里规定只用前两个字节. 我下面要讲的TLV解码就是基于PBOC/EMV的简化版本.
首先看一下tag域是怎样编码的. Tag域占最多占两个字节. 编码规则如下面两幅图
一下这两幅图. 第一个图是第一个字节的编码规则. b8和b7两位标识tag所属类别. 这个可以暂时不用理. b6决定当前的TLV数据是一个单一的数据和复合结构的数据. 复合的TLV是指value域里也包含一个或多个TLV, 类似嵌套的编码格式. b5~b1如果全为1,则说明这个tag下面还有一个子字节.占两个字节, 否则tag占一个字节.
第二幅图是说明如果tag占用两个字节, 第二个字节的编码格式. B8决定tag是否还有后绪的字节存在,因为前面说过,PBOC/EMV里的tag最多占两个字节,所以该位保持为0.
清楚了上面tag编码格式,可很容易写出tag域解码的代码了. 假设,终端接收到一人字节串,这个字节串保存在tlvData的字节数组里, 伪代码如下:
if ( (tlvData[i]&0x20) != 0x20)//单一结构
{
if ((tlvData[i]&0x1f) == 0x1f)//tag两字节
{
tagIndex++;
//解析length域
//解析value域
}
else//tag单字节
{
//解析length域
//解析value域
}
}
else//复合结构
{
//复合结构可以考虑用递归的方法来实现.
}
Length域的编码比较简单,最多有四个字节, 如果第一个字节的最高位b8为0, b7~b1的值就是value域的长度. 如果b8为1, b7~b1的值指示了下面有几个子字节. 下面子字节的值就是value域的长度.
refer:
http://www.doc88.com/p-864119027073.html
https://blog.csdn.net/Enjoy_endless/article/details/78259529
https://www.cnblogs.com/SCPlatform/p/5076935.html