为什么我的Java卡小程序返回16字节的零而不是AES加密值?
编写以下程序是为了加密16字节的传入APDU命令数据段,并返回该加密值:为什么我的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);
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");