我正在创建一个通过PC / SC非接触式读卡器和javax.smartcardio API与Mifare DESFire卡通信的Java应用程序 . 我设法定期发送ISO 7816 APDU(CLA,INS,P1-P2,Lc,Command数据,Le) .
我在Ridrix's Blog上读到DESFire卡(至少我使用的EV1版本)支持APDU和Native命令,其中大多数命令只有1个字节长 .
例如,“获取版本”命令:
Command: 60
Response: af 04 01 01 00 02 18 05
我使用SpringCard的PC / SC Diag程序(available here)测试了该命令,得到了正确的响应 .
但我无法使用javax.smartcardio发送此命令:此API似乎是为真正的APDU创建的,因此不允许1字节长的命令 .
这是我做的:
public static void main(String[] args){
TerminalFactory factory = TerminalFactory.getDefault();
CardTerminals terminalList = factory.terminals();
try {
CardTerminal ct = terminalList.list().get(0);
ct.waitForCardPresent(0);
Card card = ct.connect("*");
CardChannel channel = card.getBasicChannel();
byte[] command = { 0x60 };
channel.transmit(new CommandAPDU(command));
} catch (CardException e) {
e.printStackTrace();
}
}
它给了我以下错误:
Exception in thread "main" java.lang.IllegalArgumentException: apdu must be at least 4 bytes long
at javax.smartcardio.CommandAPDU.parse(Unknown Source)
at javax.smartcardio.CommandAPDU.<init>(Unknown Source)
我尝试了唯一的(AFAIK)其他方式发送命令:
ByteBuffer command = ByteBuffer.allocate(1);
command.put((byte) 0x60);
ByteBuffer response = ByteBuffer.allocate(512);
channel.transmit(command, response);
并得到一个类似的错误:
Exception in thread "main" java.lang.IllegalArgumentException: Command APDU must be at least 4 bytes long
at sun.security.smartcardio.ChannelImpl.checkManageChannel(Unknown Source)
at sun.security.smartcardio.ChannelImpl.doTransmit(Unknown Source)
at sun.security.smartcardio.ChannelImpl.transmit(Unknown Source)
你知道使用javax.smartcardio或其他什么方式发送这种命令吗?
我知道可以包装这些命令,但我更喜欢使用(更简单的)本机命令 .
谢谢 .
3 回答
差不多4年后,但是为了防止这个问题有人发茬,我确实找到了答案 . 今天许多读者都支持在ISO 7816-4命令中包装Desfire APDU帧 . 我确实发现了数据不能超过55个字节的限制 .
在本文档中查看第23页以获取完整信息:http://neteril.org/files/M075031_desfire.pdf
这意味着您可以指定以下内容来包装APDU帧
响应也包括如下:
因此可以使用以下代码
javax.smartcardio
是为使用ISO 7816-4命令而编写的API . 因此无法发送"native"命令 . 基本上,本机命令可以是任何东西,因此很难支持这些命令 .您要么恢复为JNI,要么尝试找到使用transmitControlCommand的内容 . 但是,如果没有额外的库,我担心没有真正的方法可以使用DESFire .
我个人认为使用包装层要容易得多 .
这里有答案:命令APDU必须至少为4个字节 .