【Java Card】CLEAR_ON_DESELECT和CLEAR_ON_RESET的区别
文章目录
- 前言
- 一、先说结论
- 1.卡片离场断电
- 2.卡片一直在场且保持连接
- 2.1 CLEAR_ON_DESELECT
- 2.2 CLEAR_ON_RESET
- 二、测试步骤
- 1.设计Applet
- 2.读卡器程序
- 3.测试结果
前言
一开始进行Applet开发的时候,对于CLEAR_ON_DESELECT和CLEAR_ON_RESET总是分不清楚,他们都是用于创建临时的byte数组数据的,好像用起来也没多大的差别。
本文就一个例子来说明CLEAR_ON_DESELECT和CLEAR_ON_RESET到底有什么区别,对于代码的执行结果会有什么差异。
一、先说结论
1.卡片离场断电
当NFC卡片离开读卡器时,此时卡片断电,那么无论是CLEAR_ON_DESELECT还是CLEAR_ON_RESET创建的数据都会被清除掉,在这种情况下,CLEAR_ON_DESELECT和CLEAR_ON_RESET是没有什么区别的。
2.卡片一直在场且保持连接
2.1 CLEAR_ON_DESELECT
当Applet处理deselect时,该Applet中的CLEAR_ON_DESELECT的数据会被清除。
场景描述:
1)读卡器发送了select指令选择到了Applet A。
2)读卡器发送apdu指令,Applet A中处理了apdu,给CLEAR_ON_DESELECT的数据做了赋值。
3)读卡器再次发送了select指令。
4)此时Applet A中的CLEAR_ON_DESELECT的数据被清除。
当NFC卡片收到select指令时,会首先deselect当前active的Applet。即使要select的Applet就是当前active的Applet也会做该处理,所以当前Applet中的CLEAR_ON_DESELECT的数据会由于deselect被清除。
2.2 CLEAR_ON_RESET
前面的CLEAR_ON_DESELECT清楚了,这个就很好理解了。当Applet处理deselect时,该Applet中的CLEAR_ON_RESET的数据也依然存在,不会被清除。当卡片离场断电或者读卡器card.disconnect断开与卡片的连接时才会清除
场景描述:
1)读卡器发送了select指令选择到了Applet A。
2)读卡器发送apdu指令,Applet A中处理了apdu,给CLEAR_ON_RESET的数据做了赋值。
3)读卡器再次发送了select指令。
4)此时Applet A中的CLEAR_ON_RESET的数据依然存在。
二、测试步骤
1.设计Applet
我们设计Applet中有一个临时数组,是以CLEAR_ON_DESELECT或者CLEAR_ON_RESET来创建的。
index = JCSystem.makeTransientByteArray((short) 4, JCSystem.CLEAR_ON_DESELECT);
或者
index = JCSystem.makeTransientByteArray((short) 4, JCSystem.CLEAR_ON_RESET);
该Applet处理一个APDU指令,用来给这个index数组进行+1处理,并返回这个数组的数据。
即处理一次APDU后index变为 00 00 00 01,如果不清除,那么再次处理后index变为 00 00 00 02。
但是如果发生了清除,那么执行APDU后index仍是00 00 00 01
private void handleAPDU(APDU apdu) {byte buffer[] = apdu.getBuffer();increaseIndex();Util.arrayCopyNonAtomic(index, (short) 0, buffer, (short) 0, (short) index.length);apdu.setOutgoing();apdu.setOutgoingLength((short) 4);apdu.sendBytesLong(buffer, (short) 0, (short) 4);
}//4个字节的index+1
private byte increaseIndex() {int Value = (index[0] & 0xFF) << 24 | (index[1] & 0xFF) << 16 | (index[2] & 0xFF) << 8| (index[3] & 0xFF);Value++;index[0] = (byte) ((Value >> 24) & 0xFF);index[1] = (byte) ((Value >> 16) & 0xFF);index[2] = (byte) ((Value >> 8) & 0xFF);index[3] = (byte) (Value & 0xFF);return OK;
}
这样我们通过向Applet发送APDU指令,可以看到index的值是否发生了重置。
2.读卡器程序
CardTerminal t = getCardTerminal();
if (t == null) {return;
}
if (t.waitForCardPresent(10000)) {TestScript testScript = new TestScript().append(selectApplet).append(new CommandAPDU(0x80, 0x10, 0x00, 0x00));testScript.run(c.getBasicChannel());TestScript testScriptNew = new TestScript()//.append(selectApplet).append(new CommandAPDU(0x80, 0x10, 0x00, 0x00));testScriptNew .run(c.getBasicChannel());c.disconnect(true);
}
读卡器的程序如上,在发送了select之后,发送一条apdu指令给到Applet让index进行+1,并获得index的值。
之后可以选择重新发送select,再发送APDU,以触发Applet的deselect。也可以调整代码,仅发送APDU,这样Applet不会触发deselect。
3.测试结果
index的初值为00 00 00 00 ,卡片一直放置在读卡器上不离开,在经过指令的处理后,index的值为
发送指令\数据类型 | CLEAR_ON_DESELECT | CLEAR_ON_RESET |
---|---|---|
select、APDU、APDU | 00 00 00 02 | 00 00 00 02 |
select、APDU、select、APDU | 00 00 00 01 | 00 00 00 02 |
可以看到,在select时,由于Applet发生了deselect的执行,所以CLEAR_ON_DESELECT的数据被清除了,所以之后再次执行APDU指令后,得到的index为 00 00 00 01。
而对于CLEAR_ON_RESET的数据,虽然applet也处理了deselect,但是数据并没有清除,故index为 00 00 00 02。