11

我正在尝试使用 javax.smartcardio读取智能卡(德语 Gesundheitskarte )

在 EF“PD”的定义中,它的长度被指定为 850 字节。内容应该是此处指定的 gzip 压缩的 ISO5589-15 编码 XML 字符串

作为我发送的 CommandAPDU

00 B0 00 00 00

获取前 256 个字节。发送后

00 B0 00 FF 00

我得到接下来的 256 个字节。

但是我怎么得到剩下的呢?

我怎么知道二进制数据何时结束?

德国规范第 1 部分| 德国规范第 2 部分

4

5 回答 5

14

READ BINARYAPDU 允许2个字节作为文件偏移量,在 P1 和 P2 中编码,并使用 Le 作为长度,作为READ BINARY响应中的字节数。P1 是高字节,或最高有效字节。然而,P1 的最高位被保留以指示 P1 是否还包含一个短文件标识符0如果您已经在读取文件,它应该保持在值,从而使您的最大偏移量为 32Ki - 1。

我无法阅读您链接的规格,但我们假设READ BINARY您卡上的 APDU 以相同的方式工作。

您读取前 256 个字节的命令似乎是正确的,注意这Le==0x00表示读取了 256 个字节。

要读取从偏移量 256、512 等开始的字节,请开始递增 P1,例如:

00 B0 01 00 00
00 B0 02 00 00
00 B0 03 00 00

要读取从偏移量 257 (0x101) 开始的 256 个字节:

00 B0 01 01 00

偏移量 600 (0x258):

00 B0 02 58 00

在您的代码中,如果您使用 Javaint来存储偏移量,您通常最终会使用以下内容递增 P1:

int offset;
int P1, P2;

while (continueReading)
{
    // ...
    P1 = (offset >> 8) & 0xFF;
    P2 = offset & 0x00FF;
    // ...
    // send APDU
}

如何指示文件的大小取决于实现。通常,您可以从 EF ( ) 上的 SELECT 返回的文件控制信息 (FCI) 结构中获取文件大小00 A4 00 00 02 fileId。然而,文件的大小也可以嵌入到文件的内容中。如果可能,您不应依赖状态字来告诉您文件的大小。


加法:Le、Ne 和奇数 INS

重要的是,您只能根据您在响应数据 (RDATA) 中实际接收到的字节数来增加偏移量。请注意,如果 P3 = Le,则 Le 编码 Ne,这是响应数据的最大大小。你收到的可能少于这个。

如果文件大小为 32Ki 或更大,则需要使用带有奇数 INS ( B7) 的 READ BINARY 来读取 32Ki 以上的数据。在这种情况下,RDATA 也可能包含开销。显然,这反过来可能会影响偏移计算以及要读取到文件末尾的计算。

于 2012-07-02T17:28:46.417 回答
5

偏移量在P1&中P2,尽管最高位用于指示您要选择具有给定 SFI 的内容。所以你也可以使用P1字节。之后,您将不得不向READ BINARY with an odd INS( B1) 移动。

因此,您最多可以使用普通读取二进制文件读取 2^15 - 1 个字节。那是 32Ki - 1。当然还有额外的几个字节,因为 APDU 返回的字节。

我总是使用以下方法从智能卡中读取文件: 1 确定文件大小,例如使用 SELECT by FILE ID ( ) 返回的 FCI(文件控制信息)00 A4 02 00 02 ${FILE_ID},您需要解析响应。然后每次将偏移量增加返回的字节数。永远不要询问超过最大文件大小,因为大多数卡的行为不同,没有定义或完全错误)。

进阶话题:如果使用READ BINARY with ODD INS,每次增加offset都需要减去DO的header。在这种情况下,读到最后会有点麻烦,因为您需要将标头的开销添加到Le字节中。

于 2012-07-02T17:28:29.920 回答
1

Maarten Bodewes 对 IMO 的一个小补充,非常有用的回答是关于读取更大的文件,以及 stajo 建议使用扩展 Le。我希望这可以为其他人节省一些时间和精力。

尝试使用 Le 进行长读很棘手:

  • 扩展 Le 也需要使用扩展 Lc。
  • 根据标准,扩展 Lc 不能为 0,因此您不能从偏移量 0 开始
  • 如果你的 Lc 不是 0,你需要使用“B1”INS。
  • 正如 Maarten Bodewes 解释的那样,B1 使得计算正确尺寸变得更加复杂。

除此之外,您首先需要了解该卡是否完全支持扩展Lc/Le;有关此的信息分布在 ATR 历史字节、EF.ATR 和当前 EF 信息中。

因此,虽然理论上可以从单个文件中读取大量数据,但在实践中需要付出很多努力,而且您也无法使用一个命令读取整个文件。

在您努力使用扩展 Le 进行阅读之前,请考虑以上内容。

于 2015-08-31T14:29:22.357 回答
0

如果卡支持它,您可能可以使用扩展长度格式。如果您在 lc/le 字段中指定 00,您可以使用以下两个字节作为长度

于 2013-08-09T11:08:19.610 回答
0

我尝试使用上述示例读取护照的 DG2 文件,但最后我无法获取图像文件。这是我在 kotlin 中所做的:

do {
            val offsetStart = (offset shr 8) and 0xFF
            val offsetEnd = offset and 0xFF

            LogUtils.d(offsetStart)
            LogUtils.d(offsetEnd)
            var offsetStartString = if(offsetStart < 10){
                "0$offsetStart"
            }else {
                "$offsetStart"
            }
            val offsetEndString = if(offsetEnd < 10){
                "0$offsetEnd"
            }else {
                "$offsetEnd"
            }
            LogUtils.d(offsetStartString)
            LogUtils.d("00B0${offsetStartString}${offsetEndString}00")
            val commandByte = toByteArray("00B0${offsetStartString}${offsetEndString}00")
            resultCommand = this.nfc.transmit(commandByte,commandByte.size)
            val resultHex = StringUtil.toHexString(resultCommand)
            LogUtils.d(resultHex)
            baos.write(resultCommand)
            offset += 1
            LogUtils.d(resultCommand.size)
        } while (resultCommand.size > 4)
于 2020-01-19T23:53:17.627 回答