Java Card +相应的APDU中的En- / Decryption输出

我是Java Card的全部主题的新手,并试图查看一些代码示例以便更好地理解。 我在oracle论坛中找到了一个AES使用示例,但是在以下部分遇到了一些问题:

private void doAES(APDU apdu) { byte b[] = apdu.getBuffer(); short incomingLength = (short) (apdu.setIncomingAndReceive()); if (incomingLength != 24) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); //perform encryption and append results in APDU Buffer a[] automatically cipherAES.init(aesKey, Cipher.MODE_ENCRYPT); cipherAES.doFinal(b, (short) dataOffset, incomingLength, a, (short) (dataOffset + 24)); cipherAES.init(aesKey, Cipher.MODE_DECRYPT); cipherAES.doFinal(b, (short) (dataOffset + 24), incomingLength, a, (short) (dataOffset + 48)); // Send results apdu.setOutgoing(); apdu.setOutgoingLength((short) 72); apdu.sendBytesLong(b, (short) dataOffset, (short) 72); } 

根据我的理解,此代码从传入的APDU获取前24个数据字节,对它们进行加密并将它们放入字节数组a中。 然后它接下来的24个数据字节,解密它们并将它们放入。

但是以下命令不使用这些输出数据

 apdu.sendBytesLong(b, (short) dataOffset, (short) 72); 

使用b作为输出数据…这可能不正确所以请帮助我理解我哪里出错了。

另外:用这个和相应的答案加密小文本的简单命令APDU是什么样的?

实际上,Oracle论坛的代码并不是很好。 它不遵循内存使用的基本规则,它根本不是一个真实的例子。 此外,它会非常慢,如果经常使用它甚至可能会损坏您的智能卡。

我想你应该首先阅读Java Card教程并了解APDU是什么以及它的结构,请看这个问题:

如何开始使用Java卡?

然后,您可以继续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); } } } 

注意:我在示例中从输入命令初始化键值。 我的密钥存储在RAM中,这意味着每次卡复位或其他小程序选择后该值都会消失。 这不一定适合您的业务案例,只需在卡上生成一次密钥并将其存储在持久性内存中可能更明智。 如果是这样,您必须使用不同的键类型: KeyBuilder.TYPE_AES而不是KeyBuilder.TYPE_AES_TRANSIENT_DESELECT