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

Posted

技术标签:

【中文标题】使用 APDU 命令获取卡的一些信息【英文标题】:Use APDU commands to get some information for a card 【发布时间】:2016-11-17 19:30:15 【问题描述】:

我有一个终端,它有自己的 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)而不是专有卡? 是的,我正在使用 EMV 规范,正如 EMV 规范所说 (EMV_v4.3_Book_3_Application_Specification_20120607062110791) 我还发送了此示例中的 APDU 命令code.google.com/archive/p/javaemvreader/wikis/… 我必须阅读的卡是 VISA和万事达卡 Y del libro: 【参考方案1】:

您在问题中显示的输入和输出值表明您使用 transceive() 方法是正确的,即第二个参数是命令 APDU,第三个参数填充了响应 APDU:

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

您关于 APDU 命令的格式和有效性的问题相当广泛。一般来说,APDU 的格式和一组基本命令在 ISO/IEC 7816-4 中定义。由于您使用emv 标记了问题并提及了应用程序主帐号,因此您可能正在与某种形式的 EMV 支付卡(例如,来自主要方案之一的信用卡或借记卡)进行交互。在这种情况下,您可能需要研究 EMV 支付系统的各种规范,这些规范定义了这些卡的数据结构和特定于应用程序的命令。

关于您的具体问题:

APDU 是否总是至少包含 5 个字节?

不,当然不是。命令 APDU 至少包含 4 个字节(头字节)。这些是

+-----+-----+-----+------+ |共轭亚油酸 | INS | P1 | P2 | +-----+-----+-----+------+

这样的 4 字节 APDU 称为“案例 1”。这意味着命令 APDU 不包含发送到卡的数据字段,并且不希望卡生成响应数据字段。所以响应 APDU 应该只包含一个响应状态字:

+-----+-----+ | SW1 | SW2 | +-----+-----+

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

第 5 个字节是一个长度字段(或者在扩展长度 APDU 的情况下是长度字段的一部分,我不会在这篇文章中进一步解释)。视情况而定,这个长度字段可能有两种含义:

    如果命令 APDU 没有数据字段,则该长度字段表示响应数据字段的预期长度(Ne):

    +-----+-----+-----+-----+------+ |共轭亚油酸 | INS | P1 | P2 |乐 | +-----+-----+-----+-----+------+ Le = 0x01 .. 0xFF:这意味着预期的响应数据长度 Ne 为 1、2、... 255 个字节(即正好是 Le 的值)。 Le = 0x00:这意味着预期的响应数据长度 Ne 为 256 字节。这通常用于指示卡为您提供尽可能多的可用字节(最多 256 个字节)。因此,即使 Le 设置为 0x00,您也不会总是从卡中获得正好 256 个字节。

    如果命令 APDU 本身有一个数据字段,该长度字段表示命令数据字段的长度(Nc):

    +-----+-----+-----+------+-----+------+ |共轭亚油酸 | INS | P1 | P2 | LC |数据(Nc 字节) | +-----+-----+-----+------+-----+------+ Lc = 0x01 .. 0xFF:这意味着命令数据长度 Nc 为 1, 2, ... 255 个字节(即正好是 Lc 的值)。 Lc = 0x00:这用于指示扩展长度的 APDU。

    如果有一个命令数据字段并且该命令预计会生成响应数据,则该命令 APDU 可能会再次跟随一个 Le 字段:

    +-----+-----+-----+------+-----+------+- ----+ |共轭亚油酸 | INS | P1 | P2 | LC |数据(Nc 字节) |乐 | +-----+-----+-----+------+-----+------+- ----+

命令00 CA 00 5A正确吗?

可能不是,有几个原因:

    由于您希望卡片传递响应数据字段(即数据对象 0x5A),因此您需要指定一个 Le 字段。因此,一个有效的格式是

    +------+------+------+------+------+ |共轭亚油酸 | INS | P1 | P2 |乐 | +------+------+------+------+------+ | 0x00 | 0xCA | 0x00 | 0x5A | 0x00 | +------+------+------+------+------+

    您收到状态字6E 00 以响应命令。这个状态字的意思是“class not supported”。这表明当前状态不支持 CLA 字节设置为 0x00 的命令。对于某些卡,这也仅仅意味着不支持这种 CLA 和 INS (00 CA) 的组合,尽管这与 ISO/IEC 7816-4 中的定义相矛盾。

    总的来说,您可以假设您的卡在当前执行状态下不支持此命令。

    假设您正在与 EMV 支付卡进行交互,您通常需要先选择一个应用程序。您的问题并未表明您是否已经这样做了,所以我假设您现在不这样做。通过发送 SELECT(通过 AID)命令来选择应用程序:

    +------+------+------+------+------+-------------- --+--------+ |共轭亚油酸 | INS | P1 | P2 |乐 |数据 |乐 | +------+------+------+------+------+-------------- --+--------+ | 0x00 | 0xA4 | 0x04 | 0x00 | 0xXX |申请援助 | 0x00 | +------+------+------+------+------+-------------- --+--------+

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

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

    +------+------+------+------+------+ |共轭亚油酸 | INS | P1 | P2 |乐 | +------+------+------+------+------+ | 0x80 | 0xCA | 0x00 | 0x5A | 0x00 | +------+------+------+------+------+

    最后,即便如此,我也不知道有任何方案允许您通过 GET DATA 命令检索卡。通常,只能通过基于文件/记录的访问来访问 PAN。由于您没有透露您的卡的具体类型/品牌,因此无法判断您的卡可能实际支持或不支持什么。

【讨论】:

迈克尔你救了我的命!问题是 AID 我没有选择一个,还有一个问题我已经阅读了 SFI 记录 1,如何将其解析为纯文本? 谢谢!我需要获取一些EMV标签,但我不知道如何制作,你能举一个APDU命令的例子来获取一些标签吗? 我尝试阅读例如标签 9c 并具有以下 APDU 命令:80 CA 00 9C 01 或标签 5A:80 CA 00 5A 00 但总是返回 6A 88 我确定我做错了什么 读取特定标签是使用 GET DATA 还是使用 GET APPLICATION OPTIONS?我真的不明白 @mareyes 您使用 GET DATA 命令读取特定数据对象。但是,EMV 卡通常不会通过该接口公开其数据结构。因此,您通常需要使用 READ RECORD 命令来读取包含您想要的数据的记录文件。【参考方案2】:

开始

标准 ISO 7816 包括几个部分。 当终端设备供应商注意到 ISO 7816 时,他们只是确认通用物理特性(第 1 部分)、尺寸和触点(第 2 部分)以及传输协议(第 3 部分)已应用于设备阅读器。

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

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

EMV 是针对支付卡的 ISO 7816 的定制版本。 Global Card Brands 使用基于 EMV 和 ISO 7816 的自定义规格。例如 Amex “AEIPS”、Diners “D-PAS”、MasterCard “M/Chip”、Visa “VIS”等。它们几乎相同与支持的命令、流程和标签列表相关的细微差别。

不幸的是,大多数支付卡不应该使用 GET DATA APDU 命令返回标签 0x5A 值。通常您需要遵循付款程序。至少SELECT卡申请和READ标签值来自SFI卡记录。

根据 EMV GET DATA P1 P2 值应用于标签 0x9F36、0x9F13、0x9F17 或 0x9F4F。

回答您的问题:

第五个参数要送什么?回复的长度是多少?

称为“Le”的第五个字节 - 预期数据的长度。您可以尝试使用 Le = "00"。 如果卡支持 APDU 命令,您可能会得到 SW1SW2 为 0x"6Cxx" 其中 xx 是请求数据的十六进制长度。当您可以使用正确的 Le 值重复相同的命令时。

例如,读取 PIN Counter

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 命令和响应使用 BYTE 编码。根据提供的终端 API 示例,您将获得 Array of Bytes。

作为开发人员,您可以将字节转换为所需的格式或按原样使用。请记住,根据 EMV 规范,标签数据的格式可以是可变的:

HEX(或 binary)用于数字标签的样本,例如金额; BCD 用于日期/时间或货币等数字的示例。 PAN 也是 BCD 编码器; 不同字符集(ASCII、Unicode、...)中的字符串,用于持卡人姓名、应用程序名称的示例。 等

标签 0x5A - 应用主帐号 (PAN) 编码为 BCD,如果 PAN 长度为奇数,可以用 0xF 填充。

【讨论】:

非常感谢!我已经测试了你给我的例子并且有效!还有一个问题,如果我读过 SFI Record 1,如何将其解析为纯文本? 在 EMV 世界中,SFI 记录中的数据通常包含一个或多个带有标签 + 长度 + 值 (TLV) 数据的块。十六进制数据解析示例您可以在这里看到***.com/questions/31965261/… 或尝试在我们的EMV TLV 解析器iso8583.info/lib/EMV/TLVs 中发布您的十六进制回复@【参考方案3】:

只是回答如何阅读您的特定标签数据,因为 APDU 和应用程序状态行为已经得到回答。 选择应用程序后,您可以启动 GET PROCESSING OPTIONS。这是事务的实际开始。在这里,您将返回一个名为 AFL(应用程序文件定位器)的标签。您需要解析此元素并执行多个 READ RECORDS 直到找到数据。 AFL是一组四字节数据(如果你有两组SFI,就会有八字节数据)。

第一个字节表示 SFI(5 个最高有效字节是 P2 的输入 的阅读记录)。第二个字节表示要读取的第一条记录(输入 到阅读记录的 P1)。第三个字节表示要读取的最后一条记录。( 您需要多次循环 READ RECORD)第四个字节 donotes 离线数据认证涉及的记录数。

当您解析时,您会找到所需的数据。如果您不确定如何解析,请复制十六进制数据并尝试一下here

【讨论】:

以上是关于使用 APDU 命令获取卡的一些信息的主要内容,如果未能解决你的问题,请参考以下文章

从 emv 卡中获取 IBAN 号码

APDU 命令获取智能卡的序列号

如何在 C++ 中使用单个 APDU 发送和获取数据?

APDU 命令读取 SLE4432/42 卡

如何检索 PIV 卡的打印信息容器?

APDU 命令将更改的 PIN 写入卡