APDU读取文件java卡程序
Posted
技术标签:
【中文标题】APDU读取文件java卡程序【英文标题】:APDU read file java card program 【发布时间】:2012-11-14 11:46:33 【问题描述】:我使用 netbeans 制作了 java card 经典小程序
当我对读取操作进行编程时,我检查 APDU 中的第一个字节为 0x80,然后第二个字节为0xB0
,然后从字节 2 和 3 中获取我将从文件中读取的偏移量,然后获取要从字节 4 读取的字节数
作为默认的APDU
0x80 0xB0 0x00 0x03 0x60
这从当前文件中读取 60 个字节,从偏移量 3 开始
当我尝试这个命令时,它返回错误Input data length != Lc around line 12
。
重试后发现问题
问题是编译器假设字节 4 是数据的长度,所以在我的命令中他等待 60 个字节
当我搜索时,我发现字节 4 并不意味着INS=B0
时的发送数据长度
我不知道为什么会这样,当我尝试调试时,编译器甚至没有进入进程函数。
我的脚本文件是
0x00 0xA4 0x04 0x00 0X06 0X87 0XF1 0X3F 0X5E 0X22 0X47 0x7F;
0x80 0xA4 0x00 0x00 0x02 0x3F 0x00 0x7F;
0x80 0xA4 0x00 0x00 0x02 0x50 0x15 0x7F;
0x80 0xA4 0x00 0x00 0x02 0x53 0x00 0x7F;
0x80 0xA4 0x00 0x00 0x02 0x50 0x31 0x7F;
0x80 0xB0 0x00 0x00 0x33 0x7F ;
powerdown;
读取函数是
void read(APDU apdu)
if(current.isDF())//can not read DF file
ISOException.throwIt((short)27014);
EFile f = (EFile)current;
byte[]data=apdu.getBuffer();
short offset = Util.getShort(data, (short)2);
if(offset < 0 || offset > f.length)//can not read
ISOException.throwIt((short)27270);
data=apdu.getBuffer();
short len = (short)(data[4]&0xFF);
if(offset + len > f.length)//can not read
ISOException.throwIt((short)26368);
apdu.setOutgoing();
apdu.setOutgoingLength(len);
apdu.sendBytesLong(f.data, (short)(f.offset + offset),len);//return the data
第一个选择程序然后选择文件然后尝试读取不工作的数据
但如果我这样做
0x80 0xB0 0x00 0x00 0x02 0x00 0x00
它从偏移量 0 读取 2 个字节写入,尽管最终的 0x00 0x00
即使在标准中也没有使用
我的问题为什么我必须将命令中的数据设为红色数据的长度
我该如何解决这个错误?
【问题讨论】:
你在这方面进展如何,امير طارق? 请指出在哪里您收到错误或异常。 请注意,您的代码还有很多不足之处,例如多次获取缓冲区,不使用十六进制表示状态字,不使用ISO7816
类作为常量,而是使用data[4]
setOutgoing()
,并使用硬编码文字而不是常量。您可能会在无处不在(现在稍微过时)Java Card book 中找到很多相关信息
【参考方案1】:
首先,您为什么使用 0x80 作为 CLS 字节?实际上 0x80 是为全局平台命令保留的。如果您的卡是 2G,您应该使用 0xA0,如果您的卡是 3G,最好使用 0x0x(通常 0x00 用于通道 0)。第二个 - 读取二进制 APDU 是 OUT APDU 这意味着 P3 正在指定预期的数据长度,即:
0x00 0xB0 P1 P2 P3
其中:P1 编码:
| b8 | B7 | b6 | b5 | b4 | b3 | b2 | b1 | Meaning
----------------------------------------------------------------------------------------------------------------------
| 0 | X | X | X | X | X | X | X | b7-b1 is the offset to the first byte
| | | | | | | | | to read – P2 is the low part of the offset
----------------------------------------------------------------------------------------------------------------------
| 1 | 0 | 0 | X | X | X | X | X | SFI referencing used, b1-b5 are the SFI
| | | | | | | | | and P2 is the offset to the first byte to read
P2 - 偏移
P3 - 是预期长度,您不应在之后指定任何其他字节。如果 P3 等于 0 则将传出 256 字节的数据
有关所有详细信息,请查看标准 ETSI TS 102 221 (http://pda.etsi.org/pda/home.asp?wki_id=,m5nDbNrlEWZbXcW5h86B) - 您不需要帐户,只需输入电子邮件地址即可就可以下载了。
希望它会有所帮助。
韩国, -诺迪尔
【讨论】:
0x80
不是为 Global Platform 保留的,它只是意味着该命令的其余部分尚未由 ISO 7816 指定,换句话说,它是专有的。 Global Platform 使用非 ISO 7816 实现安全消息传递和身份验证,因此类 (CLA) 字节通常设置为 0x80
或 0x84
。
@owlstead 是的,你是对的,但所有全局平台命令在清除 APDU 的情况下都是 0x80,在加密/签名的情况下是 0x84。
我现在有另一个问题,当我做你说什么时我发现它返回的问题 67 00 我发现它这样做是因为出于某种原因我想调试但是当我添加 0x00 0xB0 0x00 0x00 0x03 从偏移量 0 读取三个字节,编译器自身无法运行它并因错误 lc not null 而失败,我如何修改我的编译器以接受任何 apdu 并将其发送到我的代码?
嗨,你能解释一下编译器是什么意思吗? JavaCard 小程序的编译器与 Java 完全相同,然后您必须从 JavaCard SDK 运行转换器才能将其转换为合适的 JAR/CAP/IJC 格式。 SW 6700 是卡片答案而不是编译器。【参考方案2】:
您没有正确使用 Java Card API。下面我添加了一段我从头顶输入的代码。如果无法运行,请尝试代码并对其进行一些编辑。
void read()
final APDU apdu = APDU.getCurrentAPDU();
final byte[] buf = apdu.getBuffer();
if(current.isDF())
ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
final EFile file = (EFile) current;
final short fileOffset = Util.getShort(buf, ISO7816.OFFSET_P1);
if (fileOffset < 0 || fileOffset >= file.length)
ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
// Ne (encoded by Le) is the *maximum* size of the response data
final short ne = apdu.setOutgoing();
// Re is the actual number of the bytes to be returned
final short fileDataLeft = file.length - fileOffset;
final short re = ne < fileDataLeft ? ne : fileDataLeft;
apdu.setOutgoingLength(re);
apdu.sendBytes(file.data, fileOffset, re);
【讨论】:
抱歉,我家的电脑上没有安装 Java Card API :(以上是关于APDU读取文件java卡程序的主要内容,如果未能解决你的问题,请参考以下文章