使用APDU命令获取卡片的一些信息

4
我是一名有用的助手,可以为您翻译文本。

我有一个终端,它有自己的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 是否会在强制类型转换为字符串时显示为纯文本信息?

在继续之前,我们可以假设(1)您正在遵循APDU命令的emv标准,(2)您正在使用流行的卡应用程序,如vsdc、m/chip、d-pas(分别是visa、mastercard、discover),而不是专有卡吗? - Adarsh Nanu
是的,我正在使用EMV规范(EMV_v4.3_Book_3_Application_Specification_20120607062110791)中所述的规范。另外,我发送了在此示例https://code.google.com/archive/p/javaemvreader/wikis/ExampleOutput.wiki中的APDU命令,我要读取的卡是VISA和MasterCard。 - angelreyes17
3个回答

20

你所展示的输入和输出值表明你在使用transceive()方法时是正确的,即第二个参数是一个命令APDU,第三个参数则装有响应APDU:

resultCode = SmartCardInterface.transmit(cardHandle, commandAPDU, ResponseAPDU);

您对APDU命令的格式和有效性的问题比较广泛。一般而言,APDU的格式和基本指令集在ISO/IEC 7816-4中定义。由于您标记了问题并提到了应用程序主帐号,您可能正在与某种EMV支付卡(例如来自主要方案之一的信用或借记卡)交互。在这种情况下,您可能需要研究各种EMV支付系统的规范,这些规范定义了这些卡的数据结构和应用程序特定的命令。
关于您具体的问题:

APDU是否总是至少由5个字节组成?

不是的。命令APDU至少由4个字节(标题字节)组成。它们是:

+-----+-----+-----+-----+
| CLA | INS | P1  | P2  |
+-----+-----+-----+-----+
一种4字节的APDU被称为“case 1”。这意味着命令APDU不包含发送到卡片的数据字段,并且不期望卡片生成响应数据字段。因此,响应APDU只包含响应状态字:
+-----+-----+ | SW1 | SW2 | +-----+-----+

命令APDU的第5个字节是什么?

第5个字节是长度字段(对于扩展长度APDU的情况,这是长度字段的一部分,本文不再进一步解释)。根据情况,该长度字段可能有两个含义:
如果命令APDU没有数据域,则长度字段表示响应数据域的预期长度(Ne): +-----+-----+-----+-----+-----+ | CLA | INS | P1 | P2 | Le | +-----+-----+-----+-----+-----+
Le = 0x01 .. 0xFF:这意味着预期的响应数据长度Ne为1、2、... 255字节(即Le的确切值)。 Le = 0x00:这意味着预期的响应数据长度Ne为256字节。这通常用于指示卡提供尽可能多的字节(最多256字节)。因此,即使将Le设置为0x00,您也不会总是从卡中获得确切的256字节。
如果命令APDU本身具有数据域,则该长度字段表示命令数据域的长度(Nc): +-----+-----+-----+-----+-----+-----------------+ | CLA | INS | P1 | P2 | Lc | DATA(Nc个字节)| +-----+-----+-----+-----+-----+-----------------+
Lc = 0x01 .. 0xFF:这意味着命令数据长度Nc为1、2、... 255字节(即Lc的确切值)。 Lc = 0x00:这用于指示扩展长度APDU。
如果存在命令数据域并且期望生成响应数据的命令APDU可能再次跟随Le字段: +-----+-----+-----+-----+-----+-----------------+-----+ | CLA | INS | P1 | P2 | Lc | DATA(Nc个字节)| Le | +-----+-----+-----+-----+-----+-----------------+-----+

命令00 CA 00 5A是否正确?

可能不正确,原因如下:

  1. 由于您期望卡片返回响应数据字段(即数据对象0x5A),因此需要指定Le字段。因此,有效的格式应为:

    +------+------+------+------+------+
    | CLA  | INS  | P1   | P2   | Le   |
    +------+------+------+------+------+
    | 0x00 | 0xCA | 0x00 | 0x5A | 0x00 |
    +------+------+------+------+------+
    
  2. 您会收到响应中的状态字6E 00。该状态字的含义是“不支持的类”。这表明CLA字节设置为0x00的命令在当前状态下不受支持。对于某些卡片,这也意味着该CLA和INS的组合(00 CA)不受支持,尽管这与ISO/IEC 7816-4中的定义相矛盾。

    总体而言,可以假设您的卡片在其当前执行状态下不支持此命令。

  3. 假设您正在与EMV支付卡交互,通常需要首先选择一个应用程序。您的问题没有表明您是否已经这样做,因此我假设您现在还没有这样做。通过发送SELECT(by AID)命令来选择应用程序:

    +------+------+------+------+------+-----------------+------+
    | CLA  | INS  | P1   | P2   | Le   | DATA            | Le   |
    +------+------+------+------+------+-----------------+------+
    | 0x00 | 0xA4 | 0x04 | 0x00 | 0xXX | Application AID | 0x00 |
    +------+------+------+------+------+-----------------+------+
    

    应用程序AID的值当然取决于卡片应用程序,并可以通过遵循EMV规范中定义的发现过程来获取。

  4. 即使在选择应用程序之后,EMV应用程序的GET DATA APDU命令也是在专有类中定义的。因此,CLA字节必须设置为0x80:

    +------+------+------+------+------+
    | CLA  | INS  | P1   | P2   | Le   |
    +------+------+------+------+------+
    | 0x80 | 0xCA | 0x00 | 0x5A | 0x00 |
    +------+------+------+------+------+
    
  5. 最后,即使如此,我也不知道任何计划允许您通过GET DATA命令检索PAN的方案。通常,只能通过基于文件/记录的访问才能访问PAN。由于您没有透露特定类型/品牌的卡片,因此无法确定您的卡片实际上支持什么或不支持什么。


Michael,你救了我的命!问题是我没有选择AID。还有一个问题,我已经读取了SFI记录1,如何将其解析为纯文本? - angelreyes17
谢谢!我需要获取一些EMV标签,但我不知道如何制作,请问你能给出一个获取标签的APDU命令示例吗? - angelreyes17
我试图读取例如标签9c,并使用以下APDU命令:80 CA 00 9C 01或对于标签5A:80 CA 00 5A 00,但总是返回6A 88。我确定我做错了什么。 - angelreyes17
特定标签的读取是使用GET DATA还是GET APPLICATION OPTIONS?我真的不明白。 - angelreyes17
我必须使用GET DATA函数读取特定标签,但是什么都没有,我已经读取了一些记录,但从来没有一个给出我需要的标签,我不知道还能做什么。 - angelreyes17
显示剩余2条评论

3

开始

标准ISO 7816包括多个部分。 当终端设备供应商注意到ISO 7816时,他们只确认常见的物理特征(第1部分)、尺寸和接触点(第2部分)以及传输协议(第3部分)适用于设备读取器。

在ISO 7816第4部分(以及其他几个部分)定义的APDU命令和响应是通用定义,可能不完全受您的智能卡支持。

您需要了解与您的卡类型相关的卡终端交互层:

  • EMV是面向支付卡的ISO 7816定制版本。
  • 全球卡品牌使用基于EMV和ISO 7816的自定义规格。例如,美国运通公司的“AEIPS”,大来集团的“D-PAS”,万事达卡的“M/Chip”,Visa的“VIS”等。它们几乎相同,只有一些支持的命令、流程和标签列表方面略有不同。

不幸的是,大多数支付卡不应使用GET DATA APDU命令返回标记0x5A的值。通常,您需要遵循支付程序。至少要SELECT卡应用程序并从SFI卡记录中READ标记值。

根据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,那么将这个答案字符串化后会显示原始文本吗?
APDU命令和响应使用字节编码。根据提供的终端API示例,您将获得字节数组。
作为开发人员,您可以将字节转换为所需的格式或直接使用。请记住,根据EMV规范,标签数据的格式可以是可变的:
- 十六进制(或二进制),例如数值标签(如金额); - BCD编码,例如日期/时间或某些数字(如货币)。PAN也是BCD编码器; - 不同字符集(ASCII、Unicode等)的字符串,例如持卡人姓名、应用程序名称; - 等等。
标签0x5A - 应用程序主帐号(PAN)编码为BCD,并且如果PAN长度为奇数,则可以用0xF填充。

非常感谢!我已经测试了你给我的示例,它运行正常!还有一个问题,如果我读取了SFI记录1,如何将其解析为纯文本? - angelreyes17
在EMV世界中,SFI记录中的数据通常包含一个或多个带有标签+长度+值(TLV)数据的块。您可以在此处查看十六进制数据解析示例https://dev59.com/e47da4cB1Zd3GeqP7gIY#32106543,或尝试在我们的EMV TLV解析器https://iso8583.info/lib/EMV/TLVs上发布您的十六进制回复。 - iso8583.info support

1
只需回答如何读取您的特定标签数据,因为APDU和应用程序状态行为已经得到解答。 选择应用程序后,您可以启动GET PROCESSING OPTIONS。这是交易的实际开始。在这里,您将返回一个名为AFL(应用程序文件定位器)的标签。您需要解析此元素并进行多个READ RECORDS,直到找到数据。 AFL是一组四个字节的数据(如果您有两组SFI,则会有八个字节的数据)。
  • 第一个字节表示SFI(5个最高有效字节是READ RECORD的P2输入)。第二个字节表示要读取的第一条记录(READ RECORD的P1输入)。第三个字节表示要读取的最后一条记录。(您需要循环READ RECORD这么多次)第四个字节表示离线数据认证涉及的记录数。
当您解析时,您将找到所需的数据。如果您不确定如何解析,请复制十六进制数据并在此处尝试。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接