Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用读取二进制文件读取超过256个字节_Java_Smartcard - Fatal编程技术网

Java 使用读取二进制文件读取超过256个字节

Java 使用读取二进制文件读取超过256个字节,java,smartcard,Java,Smartcard,我正在尝试使用javax.smartcardio读取智能卡() 在EF“PD”的示例中,其长度指定为850字节。内容应该是指定的gzip编码的ISO5589-15 XML字符串 作为我的命令 00 B0 00 00 00 获取前256个字节。 发送后 00 B0 00 FF 00 我得到接下来的256个字节 但是我怎么才能得到剩下的呢 我如何知道二进制数据何时结束 | 偏移量位于P1&P2中,尽管最高位用于指示您要选择具有给定SFI的内容。因此,您也可以对字节使用P1。在此之后,您将不得不使

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

在EF“PD”的示例中,其长度指定为850字节。内容应该是指定的gzip编码的ISO5589-15 XML字符串

作为我的命令

00 B0 00 00 00
获取前256个字节。 发送后

00 B0 00 FF 00
我得到接下来的256个字节

但是我怎么才能得到剩下的呢

我如何知道二进制数据何时结束

|

偏移量位于
P1
&
P2
中,尽管最高位用于指示您要选择具有给定SFI的内容。因此,您也可以对字节使用
P1
。在此之后,您将不得不使用奇数INS(
B1
)读取二进制文件

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

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

高级主题:
如果使用带奇数INS的
读取二进制文件
,则每次增加偏移量时都需要减去DO的标题。在这种情况下,读取到末尾会变得有点麻烦,因为您需要将头的开销添加到
Le
字节。

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

我无法读取您链接的规格,但让我们假设您卡上的
读取二进制文件
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字节,请执行以下操作:

偏移量600(0x258):

在代码中,如果使用Java
int
存储偏移量,通常会以如下方式递增P1:

int offset;
int P1, P2;

while (continueReading)
{
    // ...
    P1 = (offset >> 8) & 0xFF;
    P2 = offset & 0x00FF;
    // ...
    // send APDU
}
文件大小的指示方式取决于实现。通常,您可以从EF上的SELECT返回的文件控制信息(FCI)结构中获取文件大小(
00A4 0002 fileId
)。但是,文件的大小也可以嵌入到文件的内容中。如果可能的话,您不应该依靠状态词来告诉您文件的大小


添加:Le、Ne和奇数INS

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


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

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

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

尝试使用Le进行长时间读取非常棘手:

  • 扩展Le也需要使用扩展Lc
  • 根据标准,扩展Lc不能为0,因此不能从偏移量0开始
  • 如果您的信用证不是0,您需要使用“B1”INS
  • 然后B1使计算正确的尺寸变得更加复杂,正如Maarten Bodewes解释的那样
除此之外,您需要首先了解该卡是否支持扩展Lc/Le;关于这一点的信息分布在ATR历史字节、EF.ATR和当前EF信息上

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


在您尝试使用扩展Le进行阅读之前,请考虑上面的内容。

我尝试了上面的示例来阅读passport的DG2文件,但最后, 我无法获取图像文件。以下是我在科特林所做的:

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)
do{
val offsetStart=(偏移shr 8)和0xFF
val offsetEnd=偏移量和0xFF
LogUtils.d(偏置启动)
日志文件d(偏移结束)
var offsetStartString=if(offsetStart<10){
“0$offsetStart”
}否则{
“$offsetStart”
}
val offsetEndString=if(offsetEnd<10){
“0$offsetEnd”
}否则{
“$offsetEnd”
}
LogUtils.d(偏移开始字符串)
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)
int offset;
int P1, P2;

while (continueReading)
{
    // ...
    P1 = (offset >> 8) & 0xFF;
    P2 = offset & 0x00FF;
    // ...
    // send APDU
}
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)