Java Card +相应的APDU中的En- / Decryption输出 [英] En-/Decryption output in Java Card + corresponding APDUs

查看:244
本文介绍了Java Card +相应的APDU中的En- / Decryption输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

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

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

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

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

推荐答案

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

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.

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

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

如何开始使用Java卡?

然后你可以进行Java Card加密/解密。这样的事情可能对你有所帮助:

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

}

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

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.

这篇关于Java Card +相应的APDU中的En- / Decryption输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆