编写以下程序是为了加密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_DESELECT);
以及
byte[] cipheredData = new byte[16];
但没有改变!
请注意,由于我想对卡进行侧通道攻击,我希望尽可能少地使用EEPROM并希望使用RAM。因此,如果您对我可以使用EEPROM的方式有任何改进程序的评论,请告诉我。
同时请注意,由于我的侧面频道板,我“必须”对set_key
,write_text
和read_text
使用三种不同的命令。我的意思是不建议混合命令的方法。
答案 0 :(得分:1)
您跳过加密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 C0 00 00
答案 1 :(得分:1)
首先,这两个是相同的:
要解决此问题,请替换
byte[] cipheredData = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_RESET);
使用:
byte[] cipheredData = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_RESET);
第二
现在 cipheredData
不包含任何内容,它是一个空的字节数组,所以在write_text
和{read_text
的情况下都不会有任何好处。 1}}。
您是否需要加密 APDU ???
你错过了什么吗?
因为你问的是保存密钥:
用于生成密钥:
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256);
SecretKey myKey = keyGenerator.generateKey();
保存密钥:
char[] hex = encodeHex(key.getEncoded());
writeKeyToFile(file, String.valueOf(hex));
用于加载已保存的密钥:
String keyHex = new String(readFileToByteArray(file));
byte[] encoded = decodeHex(keyHex.toCharArray());
SecretKey myKey = new SecretKeySpec(encoded, "AES");