我正在编写一个JavaCard 2.2.1小程序,该小程序对输入数据进行一些繁重的数学处理并将结果返回到计算机。我的代码有很多for
和while
循环。问题是,当我从PC调用卡时,与卡的连接不等待卡完成所有过程,而是返回PC / SC协议错误。我在C#中使用PCSC library从PC与卡进行通信,并收到此错误:检测到智能卡通信错误。
为重现该问题,我准备了一个带有一些虚拟计算的测试小程序:
package my.testapplet;
import javacard.framework.*;
public class TestApplet extends Applet
{
public static void install(byte[] bArray, short bOffset, byte bLength)
{
new TestApplet().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
}
public void process(APDU apdu)
{
if (selectingApplet())
{
return;
}
byte[] buf = apdu.getBuffer();
short result = 0;
if (buf[ISO7816.OFFSET_CLA] == ISO7816.CLA_ISO7816) {
switch (buf[ISO7816.OFFSET_INS])
{
case (byte)0x00:
{
short temp1 = 0;
short temp2, temp3 = 0;
while(temp1 < 30000) {
temp1++;
temp2 = 0;
while(temp2 < 30000) {
temp2++;
if(temp2 > 0) {
temp3 = (short)(temp1 * 2 + 1);
}
}
}
result = 100;
}
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
buf[0] = (byte) (result & 0xff);
buf[1] = (byte) (result >>> 8);
apdu.setOutgoingAndSend((short) 0, (short) 2);
} else {
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
}
我已经在3种不同的Java卡模型(来自不同的供应商)上测试了此applet,所有结果均相同。我还要注意,在Java卡模拟器中运行代码时没有问题。该问题发生在实际的物理Java卡上。看来java卡上的虚拟机为false时,会将正在运行的代码中的某些循环检测为无限循环,并中断了连接。
我对这个问题一无所知。有任何类似的Java卡使用经验吗?关于为何在Java卡上会发生这种行为以及如何解决它的任何想法? Java卡上是否有任何特殊的指令/配置来禁用此行为并等待Java卡准备并返回结果?
答案 0 :(得分:3)
WTX(等待时间延长)是必要的,它可以通知读者它将不得不等待,因为尚无响应,否则它将超时并断开连接。 WTX不能在APDU层中可以看出,因为它在较低的水平T = 0,T = 1和T = CL协议的水平操作。可以看出有类似作用的TLS心跳或其他信息,以保持传输层活着。顺便说一句,可以通过ATR配置标准等待时间。
即使不需要实现该功能,较新的卡通常也能够自动处理WTX。较旧的卡通常只为特定的API调用启用了WTX扩展,而扩展可能需要更长的时间才能完成。显然,RSA密钥对的生成是这里的主要罪魁祸首,但是其他操作(如启动时的垃圾回收和安装Applet的操作)也可以使用WTX。
如果您使用的方法运行时间更长,则可能必须定期发出WTX。你想发出WTX相对较小的时期,让更多的细粒度控制 - 如果你能估计它正确地花费的时间。最好你协议包括精细的晶APDU的为好,让WTX用尽可能少。正如Mahdipour M所发现的那样,发行WTX可能会使读卡器永远等待,因此这并非完全没有风险(请参阅问题下方的注释)。
总之,使Java卡发送低电平WTX消息的方法是静态APDU.waitExtension()方法。