使用READ BINARY读取超过256个字节
我正在尝试使用javax.smartcardio读取智能卡( 德语Gesundheitskarte )
在EF“PD”的定义中,其长度被指定为850字节。 内容应该是这里指定的经过压缩的ISO5589-15编码的XML字符串
作为我发送的CommandAPDU
00 B0 00 00 00
得到前256个字节。 发送后
00 B0 00 FF 00
我得到接下来的256个字节。
但我怎么得到其余的?
我怎么知道二进制数据何时结束?
德国规范第1部分 | 德国规范第2部分
READ BINARY
APDU允许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
在你的代码中,如果你使用Java int
存储偏移量,你通常会用这样的东西来增加P1:
int offset; int P1, P2; while (continueReading) { // ... P1 = (offset >> 8) & 0xFF; P2 = offset & 0x00FF; // ... // send APDU }
如何指示文件的大小取决于实现。 通常,您可以从EF( 00 A4 00 00 02 fileId
)上的SELECT返回的文件控制信息(FCI)结构中获取文件大小。 但是,文件的大小也可以嵌入文件的内容中。 如果可能,您不应该依赖状态字来告诉您文件的大小。
增加:Le,Ne和奇INS
重要的是,您只需使用响应数据(RDATA)中实际接收的字节数来增加偏移量。 注意,如果P3 = Le,则Le编码Ne,这是响应数据的最大大小。 你可能收到的不到那个。
如果文件大小为32Ki或更大,则需要使用带有奇数INS( B7
)的READ BINARY来读取32Ki以上的数据。 在这种情况下,RDATA也可能包含开销。 显然, – 反过来 – 可能会影响偏移计算和读取到文件末尾的计算。
偏移量在P1
和P2
,但最高位用于表示您要选择具有给定SFI的内容。 所以你也可以使用P1
作为字节。 之后,您将不得不READ BINARY with an odd INS
( B1
)移向READ BINARY with an odd INS
。
因此,您可以使用正常读取二进制读取最多2 ^ 15 – 1个字节。 这是32Ki – 1.当然还有几个字节,因为APDU返回了字节。
我总是使用以下方法从智能卡中读出文件:1确定文件大小,例如使用带有SELECT by FILE ID( 00 A4 02 00 02 ${FILE_ID}
)返回的FCI(文件控制信息),你需要解析响应。 然后每次增加偏移量返回的字节数。 永远不要求超过最大文件大小,因为大多数卡的行为不同,没有定义或只是明显错误)。
高级主题:如果将READ BINARY with ODD INS
使用,则每次增加偏移量时都需要减去DO的标题。 在这种情况下,读到最后会变得有点麻烦,因为您需要将标头的开销添加到Le
字节。
IMO对IMO的一个小补充非常有用的答案是Maarten Bodewes关于阅读更大的文件,以及stajo建议使用扩展的Le。 我希望这能为他人节省一些时间和精力。
尝试使用Le进行长读取是很棘手的:
- Extended Le也需要使用扩展Lc。
- 根据标准,扩展Lc不能为0,因此不能从偏移0开始
- 如果你的Lc不是0,你需要使用“B1”INS。
- 然后,就像Maarten Bodewes解释的那样,B1计算正确的尺寸会变得有点复杂。
除此之外,您需要先了解该卡是否支持扩展Lc / Le; 有关此信息的信息分布在ATR历史字节,EF.ATR和当前EF信息上。
因此,虽然理论上可以从单个文件中读取大批量数据,但在实践中需要付出很多努力,而且您也无法使用一个命令读取整个文件。
在您努力使用扩展Le进行阅读之前,请考虑以上内容。
如果卡支持它,您可能可以使用扩展长度格式。 如果在lc / le字段中指定00,则可以使用以下两个字节作为长度