我有一个终端,它有自己的API来在芯片和终端之间建立和发送命令,有一个函数可以传输APDU命令并以字节数组的形式返回答案。
例如,如果想要读取标签5A(应用程序PAN),我发送以下命令:
byte[] byteArrayAPDU = new byte[]{(byte)0x00, (byte)0xCA, (byte)0x00, (byte)0x5A};
int nResult = SmartCardInterface.transmit(nCardHandle, byteArrayAPDU, byteArrayResponse);
变量byteArrayResponse
获取对APDU命令的响应。
当我将byteArrayAPDU
的值转换为十六进制数字字符串时,这会给我:00 CA 00 5A
。对该命令的响应是6E 00
(不支持类)。
我的设备使用ISO 7816作为技术规格。我发送APDU命令的方式是否正确?我问这个是因为我已经读过APDU命令至少必须有5个值,但我不知道第五个参数要发送什么。我不知道答案的长度是什么。
您能举例说明如何在APDU命令中获取标签5A或其他内容吗?
如果命令正确,取代我此刻看到的6E 00
,我会在投射到字符串时将其视为纯文本吗?
答案 0 :(得分:11)
您在问题中显示的输入和输出值表明您使用方法transceive()
是正确的,即第二个参数是命令APDU,第三个参数用响应APDU填充:
resultCode = SmartCardInterface.transmit(cardHandle, commandAPDU, ResponseAPDU);
关于APDU命令的格式和有效性的问题相当广泛。通常,APDU的格式和一组基本命令在ISO / IEC 7816-4中定义。由于您使用emv标记了问题并提及了应用程序主帐号,因此您可能正在与某种形式的EMV支付卡进行交互(例如,来自其中一个主要方案的信用卡或借记卡)。在这种情况下,您可能希望研究EMV支付系统的各种规范,这些规范定义了这些卡的数据结构和特定于应用程序的命令。
关于您的具体问题:
不,当然不是。命令APDU至少包含4个字节(标头字节)。这些是
+-----+-----+-----+-----+ | CLA | INS | P1 | P2 | +-----+-----+-----+-----+
这种4字节的APDU称为“情况1”。这意味着命令APDU不包含发送到卡的数据字段,并且不期望卡生成响应数据字段。因此,响应APDU应仅包含响应状态字:
+-----+-----+ | SW1 | SW2 | +-----+-----+
第5个字节是长度字段(或者在扩展长度APDU的情况下长度字段的一部分,我将在本文中不再进一步解释)。根据具体情况,此长度字段可能有两个含义:
如果命令APDU没有数据字段,则该长度字段表示响应数据字段的预期长度(Ne):
+-----+-----+-----+-----+-----+ | CLA | INS | P1 | P2 | Le | +-----+-----+-----+-----+-----+
如果命令APDU本身有数据字段,则该长度字段表示命令数据字段的长度(Nc):
+-----+-----+-----+-----+-----+-----------------+ | CLA | INS | P1 | P2 | Lc | DATA (Nc bytes) | +-----+-----+-----+-----+-----+-----------------+
如果存在命令数据字段并且该命令应该生成响应数据,则该命令APDU可以再次跟随Le字段:
+-----+-----+-----+-----+-----+-----------------+-----+ | CLA | INS | P1 | P2 | Lc | DATA (Nc bytes) | Le | +-----+-----+-----+-----+-----+-----------------+-----+
00 CA 00 5A
是否正确?可能不是,原因有几个:
由于您希望卡提供响应数据字段(即数据对象0x5A),因此您需要指定Le字段。因此,有效的格式将是
+------+------+------+------+------+ | CLA | INS | P1 | P2 | Le | +------+------+------+------+------+ | 0x00 | 0xCA | 0x00 | 0x5A | 0x00 | +------+------+------+------+------+
您会收到状态字6E 00
以响应该命令。此状态字的含义是“ class not supported ”。这表示当前状态不支持CLA字节设置为0x00的命令。对于某些卡,这也仅仅意味着不支持CLA和INS(00 CA
)的这种组合,尽管这与ISO / IEC 7816-4中的定义相矛盾。
总的来说,您可以假设您的卡在当前执行状态下不支持此命令。
假设您正在与EMV支付卡进行交互,通常需要先选择一个应用程序。你的问题并不表明你是否已经这样做了,所以我想,你现在不这样做。通过发送SELECT(通过AID)命令来选择应用程序:
+------+------+------+------+------+-----------------+------+ | CLA | INS | P1 | P2 | Le | DATA | Le | +------+------+------+------+------+-----------------+------+ | 0x00 | 0xA4 | 0x04 | 0x00 | 0xXX | Application AID | 0x00 | +------+------+------+------+------+-----------------+------+
应用程序AID的值当然取决于卡应用程序,可以通过遵循EMV规范中定义的发现程序获得。
即使在应用程序选择之后,EMV应用程序的GET DATA APDU命令也在专有类中定义。因此,CLA字节必须设置为0x80:
+------+------+------+------+------+ | CLA | INS | P1 | P2 | Le | +------+------+------+------+------+ | 0x80 | 0xCA | 0x00 | 0x5A | 0x00 | +------+------+------+------+------+
最后,即便如此,我也不知道任何卡允许您通过GET DATA命令检索PAN的方案。通常,PAN只能通过基于文件/记录的访问来访问。由于您没有透露卡的具体类型/品牌,因此无法确定您的卡可能支持或不支持的内容。
答案 1 :(得分:3)
开始时
标准ISO 7816包括几个部分。 当终端设备供应商注意到ISO 7816时,他们只是确认公共物理特性(第1部分),尺寸和触点(第2部分)和传输协议(第3部分)已应用于设备读取器。
ISO 7816第4部分中定义的APDU命令和响应(以及其他一些部分)是通用定义,您的智能卡可能不完全支持。
您需要了解与您的卡片类型相关的卡片终端互动图层:
不幸的是,大多数支付卡都不应该使用 GET DATA APDU命令返回Tag 0x5A值。通常您需要遵循付款程序。至少 SELECT 卡片应用程序和阅读 SFI 卡片记录中的标记值。
根据EMV GET DATA P1 P2值应该用于标签0x9F36,0x9F13,0x9F17或0x9F4F。
回答你的问题:
第五个参数要发送什么?回复的长度是多少?
第五个字节称为" Le" - 预期数据的长度。您可以尝试使用Le =" 00 "。 如果卡支持APDU命令,则可以将SW1SW2设为0x" 6Cxx "其中 xx 是所请求数据的十六进制长度。当您可以使用正确的Le值重复相同的命令时。
如需样品,请阅读PIN计数器
Get Data (Tag = '9F 17')
Request : 80 CA 9F 17 00
Response: 6C 04
SW1 SW2: 6C 04 (SW_Warning Wrong length(Le))
Get Data (Tag = '9F 17')
Request : 80 CA 9F 17 04
Response: 9F 17 01 00 90 00
Data : 9F 17 01 03 // Tag + Length + Value
Tag 9F 17: Personal Identification Number (PIN) Try Counter : 03
SW1 SW2 : 90 00 (SW_OK)
如果命令在令人满意的地方看到6E 00,那么在回答字符串的时候我会把这些信息视为纯文字吗?
使用BYTE编码的APDU命令和响应。根据提供的终端API示例,您将获得字节数组。
作为开发人员,您可以将字节转换为所需格式或按原样使用。请记住,根据EMV规范,标签数据的格式可以是变量:
标签0x5A - 应用主帐号(PAN)编码为BCD,在奇数PAN长度的情况下可以用0xF填充。
答案 2 :(得分:1)
回答如何阅读您的特定标签数据,因为已经回答了APDU和应用程序状态行为。 在SELECT应用程序之后,您可以启动GET PROCESSING OPTIONS。这是交易的实际开始。在这里,您将返回一个名为AFL(应用程序文件定位器)的标签。您需要解析此元素并执行多个READ RECORDS,直到找到数据。 AFL是一组四字节数据(如果有两组SFI,则会有八个字节数据)。
在您解析时,您将找到所需的数据。如果您不确定如何解析,请尝试复制十六进制数据here