JavaCard AES128密码DoFinal异常

j2cgzkjk  于 2023-06-28  发布在  Java
关注(0)|答案(1)|浏览(184)

我调用了split()方法来散列PIN(MD5)并将其用作AES128的密钥。但是我得到了错误0x6306,这意味着CryptoException.ILLEGAL_USE。我读过这个文档:https://docs.oracle.com/javacard/3.0.5/api/javacardx/crypto/Cipher.html但无法解决我的问题。下面是我的代码:

package baocao;

import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.*;

public class test extends Applet {

    private final static byte INS_IMPORT = (byte) 0x00;
    private final static byte INS_EXPORT = (byte) 0x01;
    private final static byte INS_VERIFY = (byte) 0x02;
    private final static byte INS_VERIFY_PIN = (byte) 0x03;
    private final static byte INS_CHANGE_PIN = (byte) 0x04;
    private final static byte INS_RECHARGE = (byte) 0x03;
    private final static byte INS_PAYMENT = (byte) 0x04;
    private final static byte INS_RESET_PIN = (byte) 0x07;
    private final static byte P1_EXPORT_ID = (byte) 0x00;
    private final static byte P1_EXPORT_REST = (byte) 0x01;
    private final static byte P1_EXPORT_AVATAR = (byte) 0x02;

    private final static byte PIN_TRY_LIMIT = 0x03;
    private final static byte PIN_SIZE = 0x10;
    private final static short SW_PIN_BLOCKED = 0x6300;
    private final static short SW_VERIFICATION_FAILED = 0x6301;
    private final static short SW_PIN_DUPPLICATED = 0x6302;
    private final static short SW_PIN_VERIFICATION_REQUIRED = 0x6303;
    private final static short SW_UNINITIALIZED_KEY = 0x6304;
    private final static short SW_INVALID_INIT = 0x6305;
    private final static short SW_ILLEGAL_USE = 0x6306;
    private short failedAttempts = 0;

    private MessageDigest sha;
    private Cipher cipher;
    private AESKey aesKey;
    private RSAPrivateKey rsaPrivKey;
    private RSAPublicKey rsaPubKey;
    private Signature rsaSig;
    private OwnerPIN pin;

    private byte[] temp, buffer1, buffer2;
    private final static short MAX_SIZE = (short) 1024;

    private short dataLen, restDataLen, avatarLen, hashedPinLen = (short) 16;
    private byte[] id;
    private byte[] avatar;
    private byte[] restData;
    private byte[] hashedPin;

    private test() {
        temp = new byte[MAX_SIZE];
        buffer1 = new byte[MAX_SIZE];
        buffer2 = new byte[MAX_SIZE];
        sha = MessageDigest.getInstance(MessageDigest.ALG_MD5, false); // MD5 -> 16bytes
        cipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, false);
        aesKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, (short) 128, false);
        rsaPrivKey = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, (short) 1024, false);
        rsaPubKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, (short) 1024, false);
        KeyPair keyPair = new KeyPair(KeyPair.ALG_RSA, (short) 1024);
        keyPair.genKeyPair();
        rsaPrivKey = (RSAPrivateKey) keyPair.getPrivate();
        rsaPubKey = (RSAPublicKey) keyPair.getPublic();
        pin = new OwnerPIN(PIN_TRY_LIMIT, PIN_SIZE);
    }
    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new test().register(bArray, (short)(bOffset + 1), bArray[bOffset]);
    }

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

        byte[] buf = apdu.getBuffer();
        short recvLen = apdu.setIncomingAndReceive();
        short pointer = 0;
        switch (buf[ISO7816.OFFSET_INS]) {
            case INS_IMPORT:
                dataLen = (short)(buf[ISO7816.OFFSET_LC] & 0xf);
                if (dataLen > MAX_SIZE) {
                    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
                }
                short dataOffset = (short) ISO7816.OFFSET_CDATA;
                pointer = 0;
                while (recvLen > 0) {
                    Util.arrayCopy(buf, dataOffset, temp, pointer, recvLen);
                    pointer += recvLen;
                    recvLen = apdu.receiveBytes(dataOffset);
                }
                split();
                short len = rsaPubKey.getModulus(buffer1, (short) 0);
                Util.arrayCopy(buffer1, (short) 0, buf, (short) 0, len);
                apdu.setOutgoingAndSend((short) 0, len);
                break;

            default:
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

    public void split() {
        short i = 0, j = 0, len = 0, old_i = 0, lenTemp;
        byte opt = 0;

        for (; i < dataLen; i++) {
            if (temp[i] == (byte) 0x00) {
                len = (short)(i - old_i);

                switch (opt) {
                    case 0: // pin
                        Util.arrayCopy(temp, old_i, buffer1, (short) 0, len);
                        sha.doFinal(buffer1, (short) 0, (short) buffer1.length, buffer2, (short) 0);
                        hashedPin = new byte[16];
                        Util.arrayCopy(buffer1, (short) 0, hashedPin, (short) 0, (short) 16);
                        pin.update(hashedPin, (short) 0, (byte) hashedPin.length);
                        aesKey.setKey(hashedPin, (short) 0);
                        cipher.init(aesKey, Cipher.MODE_ENCRYPT);
                        break;

                    case 1: // id
                        id = new byte[len];
                        Util.arrayCopy(temp, old_i, id, (short) 0, len);
                        break;

                    case 2: // avatar
                        avatarLen = len;
                        lenTemp = len;
                        if(len % 8 > 0) lenTemp = (short) (len + 8 - len % 8);
                        byte[] avatarTemp = new byte[lenTemp];
                        avatar = new byte[lenTemp];
                        Util.arrayCopy(temp, old_i, avatarTemp, (short) 0, lenTemp);
                        for (j = len; j < lenTemp; j++) {
                            avatarTemp[j] = 0x00;
                        }
                        try {
                            cipher.doFinal(avatarTemp, (short) 0, lenTemp, avatar, (short) 0);
                        } catch (CryptoException e) {
                            short reason = e.getReason();
                            switch (reason) {
                                case CryptoException.UNINITIALIZED_KEY:
                                    ISOException.throwIt(SW_UNINITIALIZED_KEY);
                                    break;
                                case CryptoException.INVALID_INIT:
                                    ISOException.throwIt(SW_INVALID_INIT);
                                    break;
                                case CryptoException.ILLEGAL_USE:
                                    ISOException.throwIt(SW_ILLEGAL_USE);
                                    break;
                                default:
                                    break;
                            }
                        }
                        
                        break;
                }
                opt++;
                old_i = (short)(i + 1);
            }
        }

        len = (short)(dataLen - old_i);
        restDataLen = len;
        restData = new byte[len];
        Util.arrayCopy(temp, old_i, restData, (short) 0, len);
    }
}
ufj5ltwl

ufj5ltwl1#

我已经修复了这个错误。问题是AES是一种处理16字节块的块密码,但在我的代码中,我将其设置为8字节加密。
所以我只需要在split(),case 2中进行更改:if(len % 16 > 0) lenTemp = (short) (len + 16 - len % 16);

相关问题