我调用了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);
}
}
1条答案
按热度按时间ufj5ltwl1#
我已经修复了这个错误。问题是AES是一种处理16字节块的块密码,但在我的代码中,我将其设置为8字节加密。
所以我只需要在
split()
,case 2中进行更改:if(len % 16 > 0) lenTemp = (short) (len + 16 - len % 16);
。