实际上,Oracle 论坛的代码不是很好。它不遵循内存使用的基本规则,并且根本不是真实世界的示例。此外,它会非常慢,如果使用过于频繁,甚至可能损坏您的智能卡。
我认为你应该首先阅读 Java Card 教程并了解 APDU 是什么及其结构,请参阅这个问题:
如何开始使用 Java 卡? https://stackoverflow.com/questions/7190338/how-to-get-started-with-java-cards
然后就可以进行Java Card加密/解密了。像这样的事情可能会帮助你:
public class MiniApplet extends Applet {
public static void install(byte[] bArray, short bOffset, byte bLength) {
// GP-compliant JavaCard applet registration
new MiniApplet().register(bArray, (short) (bOffset + 1),
bArray[bOffset]);
}
private final AESKey aesKey = (AESKey)KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_128, false);
private final Cipher aes = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
public void process(APDU apdu) {
// Good practice: Return 9000 on SELECT
if (selectingApplet()) {
return;
}
final byte[] buf = apdu.getBuffer();
final short dataLen = apdu.setIncomingAndReceive();
final byte ins = buf[ISO7816.OFFSET_INS];
switch (ins) {
case (byte) 0x00: //KEY VALUE INIT FROM APDU
if (dataLen != 16) //checking key value length
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH)
aesKey.setKey(buf, ISO7816.OFFSET_CDATA);
break;
case (byte) 0x01: //DECRYPTION
case (byte) 0x02: //ENCRYPTION
if ((dataLen & 0x000F) != 0) //checking if input data is block-aligned
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH)
if (!aesKey.isInitialized())
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
aes.init(aesKey, (ins == 0x02) ? Cipher.MODE_ENCRYPT : Cipher.MODE_DECRYPT);
aes.doFinal(buf, ISO7816.OFFSET_CDATA, dataLen, buf, ISO7816.OFFSET_CDATA);
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, dataLen);
break;
default:
// good practice: If you don't know the INStruction, say so:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
}
Note:在我的示例中,我通过输入命令初始化键值。我的密钥存储在 RAM 中,这意味着每次卡重置或另一个小程序选择后该值都会消失。这不必适合您的业务案例,更明智的做法是在卡上仅生成一次密钥并将其存储在持久内存中。如果是这样,您必须使用不同的密钥类型:KeyBuilder.TYPE_AES
代替KeyBuilder.TYPE_AES_TRANSIENT_DESELECT
.