为什么我的Java卡小程序返回16字节的零而不是AES加密值?

为什么我的Java卡小程序返回16字节的零而不是AES加密值?,java,cryptography,javacard,Java,Cryptography,Javacard,编写以下程序是为了加密16字节的传入APDU命令数据段,并返回该加密值: public class DoAES extends Applet { //Required Objects static Cipher myCipher; static AESKey myAESKey; byte[] cipheredData = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_RESET);

编写以下程序是为了加密16字节的传入APDU命令数据段,并返回该加密值:

public class DoAES extends Applet {

    //Required Objects
    static Cipher myCipher;
    static AESKey myAESKey;
    byte[] cipheredData = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_RESET);
    //Supported APDU commands INS byte
    final static byte SET_KEY = (byte) 0x12;
    final static byte WRITE_TEXT = (byte) 0x04;
    final static byte READ_TEXT = (byte) 0xC0;

    private DoAES() {

        try {
            myCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, false);
            myAESKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
                    KeyBuilder.LENGTH_AES_128, false);
        } catch (CryptoException e) {
            ISOException.throwIt(((CryptoException) e).getReason());
        }
    }

    public static void install(byte bArray[], short bOffset, byte bLength)
            throws ISOException {
        (new DoAES()).register();
    }

    public void process(APDU apdu) throws ISOException {
        if (selectingApplet()) {
            return;
        }

        byte[] buffer = apdu.getBuffer();

        if ((buffer[ISO7816.OFFSET_CLA] & 0x00FF) != 0x80) {
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
        }

        try {
            switch (buffer[ISO7816.OFFSET_INS]) {

                case SET_KEY:
                    myAESKey.setKey(buffer, (short) ISO7816.OFFSET_CDATA);
                    myCipher.init(myAESKey, Cipher.MODE_ENCRYPT);
                    break;

                case WRITE_TEXT:
                    myCipher.doFinal(buffer, (short) ISO7816.OFFSET_CDATA, (short) 0x10, cipheredData, (short) 0);
                    break;

                case READ_TEXT:
                    Util.arrayCopyNonAtomic(cipheredData, (short) 0, buffer, (short) 0, (short) 0x10);
                    apdu.setOutgoingAndSend((short) 0, (short) 0x10);
                    break;

                default:
                    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
            }
        } catch (CryptoException e) {
            ISOException.throwIt(((CryptoException) e).getReason());
        }
    }
}
问题是,它只返回零:

OSC:> opensc-tool.exe -s 00a4040006010203040501 -s 801200001000112233445566778899aabbccddeeff -s 80c00000
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 06 01 02 03 04 05 01
Received (SW1=0x90, SW2=0x00)
Sending: 80 12 00 00 10 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
Received (SW1=0x90, SW2=0x00)
Sending: 80 C0 00 00
Received (SW1=0x90, SW2=0x00):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
为了解决这个问题,我替换了

    byte[] cipheredData = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_RESET);
    byte[] cipheredData = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_RESET);
与:

    byte[] cipheredData = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_RESET);
还有

    byte[] cipheredData = new byte[16];
但一切都没有改变

请注意,由于我想在卡上进行旁道攻击,我想尽量少用EEPROM,而是使用RAM。因此,如果你有任何意见,以改善我可以少用EEPROM的方式程序,请让我知道


还请注意,由于我的侧通道板,我“必须”使用三种不同的命令来设置按键、写入文本和读取文本。我的意思是不要建议混合命令的方法。

您跳过了加密APDU,请发送

80 04 00 00 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
其中11..11是要加密的数据


然后尝试通过
80 C000 00
读取数组。首先,这两种方法是相同的:

为了解决这个问题,我替换了

    byte[] cipheredData = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_RESET);
    byte[] cipheredData = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_RESET);
与:

    byte[] cipheredData = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_RESET);
第二:

现在
cipheredData
不包含任何内容,它是一个空字节数组,因此无论是
write\u text
还是
read\u text
都没有任何好处

你不需要加密APDU吗

你错过什么了吗

更新 由于您询问有关保存密钥的问题:

用于生成密钥:

要保存密钥,请执行以下操作:

要加载保存的密钥:


第一个替换代码是相同的???@GingerHead,它是一个未命中键入的代码。更正,谢谢。:)将三个未使用的参数传递给
install()
方法到底有什么意义?@EJP这些是javacard规范中
install()
方法的必需参数。我不直接使用它们,但Java卡运行时环境使用它们来创建传入小程序的实例。例如,安装小程序的AID(小程序标识符)在这些参数中指定。啊!你是对的!我错过了
WRITE\u TEXT
APDU命令(加密命令)!!两个答案都是正确的,但亲爱的阿努拉格先回答了,我检查了他的答案。谢谢:)没关系,没关系,不用担心,你以后可以随时更改决定。@Abraham好的,现在它会根据你的需要进行更新再次感谢亲爱的朋友。我认为您混合了JavaAPI和JavaCardAPI。Java卡API中没有
KeyGenerator
readFileToBytes
decodeHex
类。此外,我不想在卡上生成密钥,我想从外部设置密钥。现在每个人都在工作。我只是想更有效地使用RAM而不是EEPROM。谢谢:)Anurag,有没有办法在RAM中定义
myAESKey
而不是在EEPROM中定义静态字段?@Abraham它不能进入RAM,但你可以使用“(AESKey)KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_RESET,KeyBuilder.LENGTH_AES_128,false);“重置后它会隐式清除密钥。
String keyHex = new String(readFileToByteArray(file));
byte[] encoded = decodeHex(keyHex.toCharArray());
SecretKey myKey = new SecretKeySpec(encoded, "AES");