The most important limitation on a package is the 64KB limitation on the maximum component size.
. . .
You can overcome the component size limitation by dividing the application into separate application and library components.
. . .
Keep in mind that there are important differences between library packages and applet packages:
In a library package, all public fields are available to other packages for linking.
In an applet package, only interactions through a shareable interface are allowed by the firewall.
package com.example.javacard.appPackageB;
import javacard.framework.Shareable;
public interface AdderInterface extends Shareable {
public short add(short a, short b);
}
然后编写Applet B, 实现AdderInterface
package com.example.javacard.appPackageB;
import javacard.framework.*;
public class B extends Applet implements AdderInterface {
public B() {
register();
}
public static void install(byte[] bArray, short bOffset, byte bLength) {
new B();
}
public short add(short a, short b) {
return (short)(a + b);
}
public Shareable getShareableInterfaceObject(AID clientAID, byte parameter) {
return this;
}
public void process(APDU apdu) {
return;
}
}
Test Applet
接下来编写应用Applet A, 该应用接受INS为0x52和0x54的APDU指令, 并分别调用库C和Applet B的add方法对APDU的P1和P2进行相加, 并将结果返回
package com.example.javacard.appPackageA;
import javacard.framework.*;
import com.example.javacard.appPackageB.AdderInterface;
import com.example.javacard.libPackageC.C;
public class A extends Applet {
private static byte[] bAppAIDBytes = {(byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02, (byte)0x01};
private static short ERROR_APPLET_AID_NOT_FOUND = (short)0x910D;
private static short ERROR_SHAREABLE_NOT_FOUND = (short)0x910E;
protected A() {
register();
}
public static void install(byte[] bArray, short offset, byte length) {
new A();
}
public void process(APDU apdu) {
if (selectingApplet()) {
return;
}
byte[] buffer = apdu.getBuffer();
byte ins = buffer[ISO7816.OFFSET_INS];
short p1 = (short)(buffer[ISO7816.OFFSET_P1] & 0xFF);
short p2 = (short)(buffer[ISO7816.OFFSET_P2] & 0XFF);
short sum = 0;
switch (ins) {
case (byte)0x52:
sum = C.add(p1, p2);
Util.setShort(buffer, (short)0, sum);
apdu.setOutgoing();
apdu.setOutgoingLength((short)2);
apdu.sendBytes((short)0, (short)2);
break;
case (byte)0x54:
AID bAppAID = JCSystem.lookupAID(bAppAIDBytes, (short)0, (byte)bAppAIDBytes.length);
if (bAppAID == null) {
ISOException.throwIt(ERROR_APPLET_AID_NOT_FOUND);
}
AdderInterface adder = (AdderInterface)(JCSystem.getAppletShareableInterfaceObject(bAppAID,(byte)0));
if (adder == null) {
ISOException.throwIt(ERROR_SHAREABLE_NOT_FOUND);
}
sum = adder.add(p1, p2);
Util.setShort(buffer, (short)0, sum);
apdu.setOutgoing();
apdu.setOutgoingLength((short)2);
apdu.sendBytes((short)0, (short)2);
break;
default:
break;
}
}
}
Java Card Development Kit 2.2.2的User Guide中说道
简单来说就是我们可以将应用的部分功能分离到另外的库(library)或者应用(applet)中, 以达到减少应用大小的目的
本文接下来对library package和applet package两种方式进行实践
library package
我们编写一个库C, 对外提供一个两数相加的功能
applet package
接下来创建一个applet B, 该applet作为shareable interface object供其他applet访问, 与库C一样对外提供两数相加的接口
先编写加法器接口AdderInterface, 继承自Shareable
然后编写Applet B, 实现AdderInterface
Test Applet
接下来编写应用Applet A, 该应用接受INS为0x52和0x54的APDU指令, 并分别调用库C和Applet B的add方法对APDU的P1和P2进行相加, 并将结果返回
编译, 安装及测试
开发环境
工具链: JCDK2.2.2
JCRE模拟器: JCDK2.2.2中的CREF
关于如何使用JCDK中的converter, scriptgen, apdutool, CREF工具完成代码的编译, 转换, 安装及运行这里不详细介绍, 在JCDK中的Users Guide手册中有很详细的讲解.
下面列出一些开发过程需要注意的点
APDU指令测试结果如下
结果符合预期
参考