En-/Decryption output in Java Card + corresponding APDUs

风流意气都作罢 提交于 2019-12-22 09:43:32

问题


I'm new to the whole topic of Java Card and tried to look at a few code examples to get a better understanding. I found a sample for AES usage in the oracle forum but have a few problems with the following part:

     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);
     }

From my understanding this code takes the first 24 data bytes from the incoming APDU, encrypts them and puts them into the byte array a. Then it takes the next 24 data bytes, decrypts them and puts them into a too.

But the following commands don't use these output data since

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

uses b for the output data ... this is probably not correct so please help me understand where I went wrong.

Also: what would a simple command APDU for encrypting a small text with this and the corresponding answer look like ?


回答1:


The code from the Oracle forum is not very good, actually. It does not follow basic rules of memory usage and it is not a real-world example at all. Moreover, it would be very slow and it could even damage your smart card if used too often.

I think you should firstly read through the Java Card tutorials and learn what APDU is and something about its structure, see this question:

How to get started with Java Cards?

Then you could proceed to Java Card encryption/decryption. Something like this might help you:

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: I initialize the key value from an input command in my example. My key is stored in RAM, which means the value disappears after each card reset or another applet selection. This does not have to fit your business case and it may be wiser to generate a secret key on the card just once and store it in the persistent memory. If so, you have to use a different keytype: KeyBuilder.TYPE_AES instead of KeyBuilder.TYPE_AES_TRANSIENT_DESELECT.



来源:https://stackoverflow.com/questions/32395400/en-decryption-output-in-java-card-corresponding-apdus

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!