首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用AES的Java卡加密返回6F00

使用AES的Java卡加密返回6F00
EN

Stack Overflow用户
提问于 2016-04-20 05:32:24
回答 2查看 1.6K关注 0票数 2

我对Java卡编程很陌生。我看到了一个关于针对Java卡的AES加密方法的例子,并且能够创建和安装applet。当我试图与applet通信时,它会返回一个6F00错误消息。我做错了什么?

下面是我的代码示例:

代码语言:javascript
复制
private void SendData(APDU apdu) 
{

    aesKeyTrial= (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false);
    byte[] outBuffer;
    outBuffer = new byte[16];
    byte[] trialKey;
    trialKey = new byte[16];
    byte[] input = {(byte)0x44,(byte)0x22,(byte)0x33,(byte)0x44,(byte)0x55,(byte)0x66,(byte)0x77,(byte)0x88,(byte)0x99,0x10,(byte)0xA2, 0x35, (byte)0x5E,0x15,0x16,0x14};
    byte[] key = {0x2d, 0x2a, 0x2d, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x41, 0x43, 0x4f, 0x44, 0x45, 0x2d, 0x2a, 0x2d};
    byte[] buffer = apdu.getBuffer();
    short len = (short) input.length;


    aesKeyTrial.setKey(trialKey,(short)0);
    if(len<=0||len%16!=0)
    {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    aesCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
    aesCipher.init(aesKeyTrial, Cipher.MODE_ENCRYPT);
    aesCipher.doFinal(input, ISO7816.OFFSET_CDATA, len, outBuffer, (short)0); 
    Util.arrayCopyNonAtomic(input, (short)0, buffer, (short)0, (short)len);
    apdu.setOutgoing();
    apdu.setOutgoingLength(len);
    apdu.sendBytes((short) 0, (short)len);
}

我想加密的是“输入”。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-20 07:03:53

正如您在回答中所说的,代码的问题在于您向doFinal (byte[] inBuff, short inOffset, short inLength,byte[] outBuff, short outOffset)方法传递了错误的参数。

但是,您正在使用的示例代码看起来非常糟糕。我认为这是写得不好的原因:

它在一个被多次调用的方法中使用了动态变量。动态变量是使用new关键字创建的变量。这些变量将在EEPROM中分配。在EEPROM中转换确实比RAM慢,而且它在磨损之前也有一个有限的擦除操作,因此强烈建议在不需要在不同的CAD (读卡器)会话之间共享数据的情况下使用RAM而不是EEPROM。另外,由于Java Card中没有强制/自动垃圾收集器,所以不要重复定义不同的动态变量,而是使用一个全局变量(类变量或实例变量而不是局部变量)。

2-由于int数据类型在JavaCards中是可选的,因此必须尽可能多地使用shortbyte,还需要将所有值转换为这些类型,以防止有符号/无符号问题。

最后,我向您提供了您的程序的升级版本:

代码语言:javascript
复制
package soQusetion;

import javacard.framework.*;
import javacard.security.AESKey;
import javacard.security.KeyBuilder;
import javacardx.crypto.Cipher;

public class SOQ1 extends Applet {

    Cipher aesCipher;
    AESKey aesKey;

    //Two different types of memory for different usage. each one has 16 (= 0x10) byte capacity.
    private byte[] volatileMem;
    private byte[] nonVolatileMem;

    //INS value for APDU command
    public static final byte INS_SET_KEY = 0x10;
    public static final byte INS_ENCRYPT = 0x20;
    public static final byte INS_DECRYPT = 0x30;

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new SOQ1();
    }

    protected SOQ1() {
        volatileMem = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_DESELECT);
        nonVolatileMem = new byte[(short) 0x10];
        aesCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, false);
        aesKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false);
        register();
    }

    public void process(APDU apdu) {
        if (selectingApplet()) {
            return;
        }
        byte[] buffer = apdu.getBuffer();
        apdu.setIncomingAndReceive();

        if (buffer[ISO7816.OFFSET_LC] != (byte) 0x10) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }

        switch (buffer[ISO7816.OFFSET_INS]) {
            case INS_SET_KEY:
                aesKey.setKey(buffer, ISO7816.OFFSET_CDATA);
                break;
            case INS_ENCRYPT:
                aesCipher.init(aesKey, Cipher.MODE_ENCRYPT);
                aesCipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short) 0x10, volatileMem, (short) 0x00);
                Util.arrayCopyNonAtomic(volatileMem, (short) 0x00, buffer, (short) 0x00, (short) 0x10);
                apdu.setOutgoingAndSend((short) 0x00, (short) 0x10);
                break;
            case INS_DECRYPT:
                aesCipher.init(aesKey, Cipher.MODE_DECRYPT);
                aesCipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short) 0x10, volatileMem, (short) 0x00);
                Util.arrayCopyNonAtomic(volatileMem, (short) 0x00, buffer, (short) 0x00, (short) 0x10);
                apdu.setOutgoingAndSend((short) 0x00, (short) 0x10);
                break;
            default:
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }

    }
}

它的工作如下:

代码语言:javascript
复制
Select Applet begin...
Select Applet successful.
//Loading AES Key APDU Command
Send: 00 10 00 00 10 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 00
Recv: 90 00
//Encrypt APDU Command
Send: 00 20 00 00 10 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 00
Recv: 62 F6 79 BE 2B F0 D9 31 64 1E 03 9C A3 40 1B B2 90 00
//Decrypt APDU Command
Send: 00 30 00 00 10 62 F6 79 BE 2B F0 D9 31 64 1E 03 9C A3 40 1B B2 00
Recv: 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 90 00

任何使上述程序更有效的建议,我都欢迎。

票数 3
EN

Stack Overflow用户

发布于 2016-04-20 06:57:42

嗨,我发现我的错误是什么,或者我的代码有什么问题。我误解了函数doFinal,它混淆了在卡中安装的内容。

下面是新的、干净的代码:

代码语言:javascript
复制
Cipher aesCipher;
  AESKey aesKeyTrial;
  aesKeyTrial= (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_128, false);
  byte[] buffer = apdu.getBuffer();
  byte[] aesKey;
  aesKey = new byte[16];
  byte[] input = {(byte)0x11,(byte)0x22,(byte)0x33,(byte)0x44,(byte)0x55,(byte)0x66,(byte)0x77,(byte)0x88,(byte)0x99,0x10,(byte)0xA2, 0x35, (byte)0x5E,0x15,0x16,0x14};
  byte[] key = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26};

  short len = (short) input.length;
  if (len <= 0 || len % 16 != 0)
    {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

  aesKeyTrial.setKey(key,(short)0);
  aesCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, false);
  aesCipher.init(aesKeyTrial, Cipher.MODE_ENCRYPT); 
  aesCipher.doFinal(input, (short)0, len, buffer, (short)0);
  apdu.setOutgoingAndSend((short)0, len);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36734616

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档