3

考虑一个具有多个实例的 Java Card Classic 小程序,这些实例需要共享 byte[] 变量中的一些数据(例如持久可变,即 EEPROM/Flash),其中包含所有实例共有的信息。

一个静态的 byte[] 变量将是一个完美的选择,但这些恰好被强加给我的验证规则所禁止(我被告知:作为一种全面的方式来证明取消实例化实例会释放它在实例化时分配的内容)。

如果从属实例可以在主实例的上下文中调用小程序的方法之一(可能最初由 AID 标识,或/和/然后以某种其他方式),这将得到解决。如何才能做到这一点?有什么例子吗?


更新:this other question 中的代码旁边是做我想要的共享对象,但似乎没有在另一个实例的上下文中调用方法。

4

1 回答 1

3

正如承诺的那样,一个经过测试的示例:

package nl.owlstead.javacard.sharedarray;

import javacard.framework.*;

/**
 * The master and slave AID should only differ in the last byte; the master should end with the 'm' ASCII character.
 * This applet is for demonstration purposes only.
 * 
 * @author owlstead@stackoverflow
 */
public class SharingApplet extends Applet {

    public interface SharedArray extends Shareable {
        public byte[] getSharedArray();
    }

    public static class SharedArrayImpl implements SharedArray {
        private byte[] sharedArray;

        public SharedArrayImpl(final byte[] arrayToShare) {
            this.sharedArray = arrayToShare;
        }

        public byte[] getSharedArray() {
            return sharedArray;
        }
    }

    private static final short MAX_AID_SIZE = 16;
    private static final short START = 0;
    private static final byte SHARABLE_PARAM = 0;
    private static final byte PARAM_SHARED_ARRAY = 0;

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        final byte aidLength = bArray[bOffset++];
        final byte lastAIDByte = bArray[(short) (bOffset + aidLength - 1)];
        final boolean isMaster = lastAIDByte == 'm';
        final SharingApplet applet = new SharingApplet(isMaster);
        applet.register(bArray, bOffset, aidLength);
        applet.setMasterAID();
    }

    // if null, it is not the master
    private final SharedArray sharedArray;
    private AID masterAID;

    public SharingApplet(final boolean isMaster) {
        if (isMaster) {
            final byte[] sa = new byte[] { 'm' };
            sharedArray = new SharedArrayImpl(sa);
        } else {
            sharedArray = null;
        }
    }

    public void process(APDU apdu) {
        if (selectingApplet()) {
            return;
        }

        byte[] buf = apdu.getBuffer();
        switch (buf[ISO7816.OFFSET_INS]) {
        case (byte) 0x00: {
            final SharedArray theSharedArray;
            if (sharedArray == null) {
                theSharedArray = (SharedArray) JCSystem.getAppletShareableInterfaceObject(masterAID, SHARABLE_PARAM);
            } else {
                theSharedArray = sharedArray;
            }
            final byte[] sa = theSharedArray.getSharedArray();
            Util.arrayCopy(sa, START, buf, START, (short) sa.length);
            apdu.setOutgoingAndSend(START, (short) sa.length);
            break;
        }
        case (byte) 0x02: {
            final SharedArray theSharedArray;
            if (sharedArray == null) {
                theSharedArray = (SharedArray) JCSystem.getAppletShareableInterfaceObject(masterAID, SHARABLE_PARAM);
                final byte[] sa = theSharedArray.getSharedArray();
                sa[START] = 's';
            } else {
                theSharedArray = sharedArray;
                final byte[] sa = theSharedArray.getSharedArray();
                sa[START] = 'm';
            }
            break;
        }
        default:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

    private void setMasterAID() {
        final byte[] workspace = new byte[MAX_AID_SIZE];
        final AID slaveOrMasterAID = JCSystem.getAID();
        final byte aidLength = slaveOrMasterAID.getBytes(workspace, START);
        workspace[(short) (aidLength - 1)] = 'm';
        this.masterAID = new AID(workspace, START, aidLength);
    }

    public Shareable getShareableInterfaceObject(AID clientAID, byte parameter) {
        if (sharedArray == null || parameter != PARAM_SHARED_ARRAY) {
            return null;
        }
        return sharedArray;
    }
}
于 2013-01-10T11:36:10.070 回答