Java 卡中的 AESKey LinkedList/Array
AESKey LinkedList/Array in Java Card
这个post和我前几天问的一个问题有关:
我想在 Java 卡中实现 LinkedList
来存储 AESKey
。所以我这样写了一个classKeyElement
:
package LinkedList;
import javacard.security.AESKey;
import javacard.security.KeyBuilder;
class KeyElement {
private KeyElement next;
private short id;
private AESKey key;
private boolean isUsed;
/**
* Constructor.
*
* @param upperBound
* An upper bound to indicate of many elements it cans contain at
* maximum. It is essential to instanciate the structure this way
* to reserve all the necessary memory at the installation time.
*/
public KeyElement(short upperBound) {
this.id = (short) 0x0000;
this.key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
KeyBuilder.LENGTH_AES_256, false);
this.isUsed = false;
this.next = null;
for (short i = (short) 0x0001; i < upperBound; i++) {
KeyElement e = new KeyElement();
this.addKeyElement(e);
}
}
public KeyElement() {
this.id = (short) 0x0000;
this.key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
KeyBuilder.LENGTH_AES_256, false);
this.isUsed = false;
this.next = null;
}
public KeyElement getNext() {
return this.next;
}
public short getID() {
return this.id;
}
public boolean isUsed() {
return isUsed;
}
public void setNext(KeyElement e) {
this.next = e;
}
public static boolean addKey(KeyElement main, final short id, byte[] key) {
for (KeyElement p = main; p != null; p = p.getNext()) {
if (!p.isUsed()) {
p.isUsed = true;
p.id = id;
p.key.setKey(key, (short) 0x0000);
return true;
}
}
return false;
}
public void addKeyElement(KeyElement e) {
e.setNext(this.getNext());
this.setNext(e);
}
public static boolean getKey(final KeyElement e, final short id,
byte[] key) {
for (KeyElement p = e; p != null; p = p.getNext()) {
if (p.id == id) {
p.key.getKey(key, (short) 0x0000);
return true;
}
}
return false;
}
}
我有一个小程序 LinkedListKey
,它使用前面描述的 class KeyElement
。
package LinkedList;
import javacard.framework.APDU;
import javacard.framework.APDUException;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.PINException;
import javacard.framework.SystemException;
import javacard.framework.TransactionException;
import javacard.framework.Util;
import javacard.framework.service.ServiceException;
import javacard.security.CryptoException;
import javacard.security.RandomData;
public class LinkedListKey extends Applet {
byte[] rdm;
RandomData rand;
KeyElement e;
private LinkedListKey(final byte[] aidArray, final short aidOffset,
final byte aidLength, final byte[] dataArray, short dataOffset,
final short dataLength) throws ISOException {
e = new KeyElement((short) 0x0064);
rdm = new byte[(short) 0x0020];
KeyElement.addKey(e, (short) 0x7514, new byte[] { (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x14, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x14, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14 });
register();
}
public static void install(final byte[] buffer, short offset,
final byte length) throws ISOException {
if (length == 0) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
short remainingBytes = makeShort(length);
// Save instance AID.
byte aidLength = buffer[offset++];
short aidOffset = offset;
// Skip instance AID.
offset += makeShort(aidLength);
remainingBytes--;
remainingBytes -= makeShort(aidLength);
if (remainingBytes <= (short) 0x0000) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
// Skip control data.
byte infoLength = buffer[offset++];
offset += makeShort(infoLength);
remainingBytes--;
remainingBytes -= makeShort(infoLength);
if (remainingBytes <= (short) 0x0000) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
// Instantiate the application.
// The length of the application data maybe greater than 127 bytes.
short dataLength = makeShort(buffer[offset++]);
remainingBytes--;
if (remainingBytes != dataLength) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
new LinkedListKey(buffer, aidOffset, aidLength, buffer, offset,
dataLength);
}
public void process(final APDU apdu) throws ISOException {
byte[] apduBuffer = apdu.getBuffer();
if (selectingApplet()) {
apdu.setOutgoingAndSend((short) 0x0000, (short) 0x0019);
return;
}
// Send result.
try {
if (apduBuffer[ISO7816.OFFSET_INS] == (byte) 0x00) {
for (short i = 0x0000; i < (short) 0x0008; i++) {
rand.generateData(rdm, (short) 0x0000, (short) rdm.length);
KeyElement.addKey(e, i, rdm);
}
KeyElement.addKey(e, (short) 0x7503, new byte[] { (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x14, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x14, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03 });
}
else if (apduBuffer[ISO7816.OFFSET_INS] == (byte) 0x01){
KeyElement.getKey(e, (short) 0x7503, apduBuffer);
setOutgoingAndSend((short) 0x0000, (short) 0x0020);
}
else {
KeyElement.getKey(e, (short) 0x7514, apduBuffer);
setOutgoingAndSend((short) 0x0000, (short) 0x0020);
}
} catch (ArithmeticException e) {
ISOException.throwIt((short) 0x0100);
} catch (ArrayStoreException e) {
ISOException.throwIt((short) 0x0200);
} catch (APDUException e) {
ISOException.throwIt(Util.makeShort((byte) 0x03,
(byte) e.getReason()));
} catch (CryptoException e) {
ISOException.throwIt(Util.makeShort((byte) 0x04,
(byte) e.getReason()));
} catch (ISOException e) {
ISOException.throwIt(Util.makeShort((byte) 0x05,
(byte) e.getReason()));
} catch (PINException e) {
ISOException.throwIt(Util.makeShort((byte) 0x06,
(byte) e.getReason()));
} catch (ServiceException e) {
ISOException.throwIt(Util.makeShort((byte) 0x07,
(byte) e.getReason()));
} catch (SystemException e) {
ISOException.throwIt(Util.makeShort((byte) 0x08,
(byte) e.getReason()));
} catch (TransactionException e) {
ISOException.throwIt(Util.makeShort((byte) 0x09,
(byte) e.getReason()));
} catch (ClassCastException e) {
ISOException.throwIt((short) 0x0A00);
} catch (IndexOutOfBoundsException e) {
ISOException.throwIt((short) 0x0B00);
} catch (NegativeArraySizeException e) {
ISOException.throwIt((short) 0x0C00);
} catch (NullPointerException e) {
ISOException.throwIt((short) 0x0D00);
} catch (SecurityException e) {
ISOException.throwIt((short) 0x0E00);
} catch (RuntimeException e) {
}
}
static private short makeShort(final byte value) {
return Util.makeShort((byte) 0x00, value);
}
private void setOutgoingAndSend(final short dataOffset, short dataLength) throws ISOException {
APDU.getCurrentAPDU().setOutgoingAndSend(dataOffset, dataLength);
}
}
所以我写了if/else条件来bench需要多少时间:
- 填写列表 (
INS
= 0x00)
- 获取列表的最后一个元素(当
INS
= 0x01)
- 获取列表的第一个元素(当
INS
= 0x02)
所以使用上面给出的代码,我可以毫无问题地将我的小程序安装到 Java 卡上。
但是当我 运行 我的小程序时,我得到一个异常 0x0D00
它引用了 NullPointerException
.
那么,什么?我是否必须得出我的 KeyElement
对象实例化失败的结论?但是,由于它是在安装时制作的,我认为它应该 return 在安装过程中出现错误,但事实并非如此。
更准确地说,它在以下步骤失败:
// Send result.
try {
if (apduBuffer[ISO7816.OFFSET_INS] == (byte) 0x00) {
for (short i = 0x0000; i < (short) 0x0008; i++) {
rand.generateData(rdm, (short) 0x0000, (short) rdm.length);
KeyElement.addKey(e, i, rdm);
}
...
更准确地说,在 KeyElement.addKey(e, i, rdm);
这就是为什么即使安装成功,e
也会引发 NullPointerException
...
我没有详细浏览所有代码,因为你没有真正理解关于
的链表的意义
public KeyElement(short upperBound)
查看一些示例 Java 链表实现,并通过捕获异常或在分配前检查剩余的 space 来安全地使用 EERPOM
您尚未创建 rand
的实例,它会生成 NullPointerException
。您需要使用:
RandomData.getInstance(byte algorithm)
有算法
public static final byte ALG_PSEUDO_RANDOM 1
public static final byte ALG_SECURE_RANDOM 2
这个post和我前几天问的一个问题有关:
我想在 Java 卡中实现 LinkedList
来存储 AESKey
。所以我这样写了一个classKeyElement
:
package LinkedList;
import javacard.security.AESKey;
import javacard.security.KeyBuilder;
class KeyElement {
private KeyElement next;
private short id;
private AESKey key;
private boolean isUsed;
/**
* Constructor.
*
* @param upperBound
* An upper bound to indicate of many elements it cans contain at
* maximum. It is essential to instanciate the structure this way
* to reserve all the necessary memory at the installation time.
*/
public KeyElement(short upperBound) {
this.id = (short) 0x0000;
this.key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
KeyBuilder.LENGTH_AES_256, false);
this.isUsed = false;
this.next = null;
for (short i = (short) 0x0001; i < upperBound; i++) {
KeyElement e = new KeyElement();
this.addKeyElement(e);
}
}
public KeyElement() {
this.id = (short) 0x0000;
this.key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
KeyBuilder.LENGTH_AES_256, false);
this.isUsed = false;
this.next = null;
}
public KeyElement getNext() {
return this.next;
}
public short getID() {
return this.id;
}
public boolean isUsed() {
return isUsed;
}
public void setNext(KeyElement e) {
this.next = e;
}
public static boolean addKey(KeyElement main, final short id, byte[] key) {
for (KeyElement p = main; p != null; p = p.getNext()) {
if (!p.isUsed()) {
p.isUsed = true;
p.id = id;
p.key.setKey(key, (short) 0x0000);
return true;
}
}
return false;
}
public void addKeyElement(KeyElement e) {
e.setNext(this.getNext());
this.setNext(e);
}
public static boolean getKey(final KeyElement e, final short id,
byte[] key) {
for (KeyElement p = e; p != null; p = p.getNext()) {
if (p.id == id) {
p.key.getKey(key, (short) 0x0000);
return true;
}
}
return false;
}
}
我有一个小程序 LinkedListKey
,它使用前面描述的 class KeyElement
。
package LinkedList;
import javacard.framework.APDU;
import javacard.framework.APDUException;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.PINException;
import javacard.framework.SystemException;
import javacard.framework.TransactionException;
import javacard.framework.Util;
import javacard.framework.service.ServiceException;
import javacard.security.CryptoException;
import javacard.security.RandomData;
public class LinkedListKey extends Applet {
byte[] rdm;
RandomData rand;
KeyElement e;
private LinkedListKey(final byte[] aidArray, final short aidOffset,
final byte aidLength, final byte[] dataArray, short dataOffset,
final short dataLength) throws ISOException {
e = new KeyElement((short) 0x0064);
rdm = new byte[(short) 0x0020];
KeyElement.addKey(e, (short) 0x7514, new byte[] { (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x14, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x14, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14, (byte) 0x75, (byte) 0x14,
(byte) 0x75, (byte) 0x14 });
register();
}
public static void install(final byte[] buffer, short offset,
final byte length) throws ISOException {
if (length == 0) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
short remainingBytes = makeShort(length);
// Save instance AID.
byte aidLength = buffer[offset++];
short aidOffset = offset;
// Skip instance AID.
offset += makeShort(aidLength);
remainingBytes--;
remainingBytes -= makeShort(aidLength);
if (remainingBytes <= (short) 0x0000) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
// Skip control data.
byte infoLength = buffer[offset++];
offset += makeShort(infoLength);
remainingBytes--;
remainingBytes -= makeShort(infoLength);
if (remainingBytes <= (short) 0x0000) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
// Instantiate the application.
// The length of the application data maybe greater than 127 bytes.
short dataLength = makeShort(buffer[offset++]);
remainingBytes--;
if (remainingBytes != dataLength) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
new LinkedListKey(buffer, aidOffset, aidLength, buffer, offset,
dataLength);
}
public void process(final APDU apdu) throws ISOException {
byte[] apduBuffer = apdu.getBuffer();
if (selectingApplet()) {
apdu.setOutgoingAndSend((short) 0x0000, (short) 0x0019);
return;
}
// Send result.
try {
if (apduBuffer[ISO7816.OFFSET_INS] == (byte) 0x00) {
for (short i = 0x0000; i < (short) 0x0008; i++) {
rand.generateData(rdm, (short) 0x0000, (short) rdm.length);
KeyElement.addKey(e, i, rdm);
}
KeyElement.addKey(e, (short) 0x7503, new byte[] { (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x14, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x14, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03, (byte) 0x75, (byte) 0x03,
(byte) 0x75, (byte) 0x03 });
}
else if (apduBuffer[ISO7816.OFFSET_INS] == (byte) 0x01){
KeyElement.getKey(e, (short) 0x7503, apduBuffer);
setOutgoingAndSend((short) 0x0000, (short) 0x0020);
}
else {
KeyElement.getKey(e, (short) 0x7514, apduBuffer);
setOutgoingAndSend((short) 0x0000, (short) 0x0020);
}
} catch (ArithmeticException e) {
ISOException.throwIt((short) 0x0100);
} catch (ArrayStoreException e) {
ISOException.throwIt((short) 0x0200);
} catch (APDUException e) {
ISOException.throwIt(Util.makeShort((byte) 0x03,
(byte) e.getReason()));
} catch (CryptoException e) {
ISOException.throwIt(Util.makeShort((byte) 0x04,
(byte) e.getReason()));
} catch (ISOException e) {
ISOException.throwIt(Util.makeShort((byte) 0x05,
(byte) e.getReason()));
} catch (PINException e) {
ISOException.throwIt(Util.makeShort((byte) 0x06,
(byte) e.getReason()));
} catch (ServiceException e) {
ISOException.throwIt(Util.makeShort((byte) 0x07,
(byte) e.getReason()));
} catch (SystemException e) {
ISOException.throwIt(Util.makeShort((byte) 0x08,
(byte) e.getReason()));
} catch (TransactionException e) {
ISOException.throwIt(Util.makeShort((byte) 0x09,
(byte) e.getReason()));
} catch (ClassCastException e) {
ISOException.throwIt((short) 0x0A00);
} catch (IndexOutOfBoundsException e) {
ISOException.throwIt((short) 0x0B00);
} catch (NegativeArraySizeException e) {
ISOException.throwIt((short) 0x0C00);
} catch (NullPointerException e) {
ISOException.throwIt((short) 0x0D00);
} catch (SecurityException e) {
ISOException.throwIt((short) 0x0E00);
} catch (RuntimeException e) {
}
}
static private short makeShort(final byte value) {
return Util.makeShort((byte) 0x00, value);
}
private void setOutgoingAndSend(final short dataOffset, short dataLength) throws ISOException {
APDU.getCurrentAPDU().setOutgoingAndSend(dataOffset, dataLength);
}
}
所以我写了if/else条件来bench需要多少时间:
- 填写列表 (
INS
= 0x00) - 获取列表的最后一个元素(当
INS
= 0x01) - 获取列表的第一个元素(当
INS
= 0x02)
所以使用上面给出的代码,我可以毫无问题地将我的小程序安装到 Java 卡上。
但是当我 运行 我的小程序时,我得到一个异常 0x0D00
它引用了 NullPointerException
.
那么,什么?我是否必须得出我的 KeyElement
对象实例化失败的结论?但是,由于它是在安装时制作的,我认为它应该 return 在安装过程中出现错误,但事实并非如此。
更准确地说,它在以下步骤失败:
// Send result.
try {
if (apduBuffer[ISO7816.OFFSET_INS] == (byte) 0x00) {
for (short i = 0x0000; i < (short) 0x0008; i++) {
rand.generateData(rdm, (short) 0x0000, (short) rdm.length);
KeyElement.addKey(e, i, rdm);
}
...
更准确地说,在 KeyElement.addKey(e, i, rdm);
这就是为什么即使安装成功,e
也会引发 NullPointerException
...
我没有详细浏览所有代码,因为你没有真正理解关于
的链表的意义public KeyElement(short upperBound)
查看一些示例 Java 链表实现,并通过捕获异常或在分配前检查剩余的 space 来安全地使用 EERPOM
您尚未创建 rand
的实例,它会生成 NullPointerException
。您需要使用:
RandomData.getInstance(byte algorithm)
有算法
public static final byte ALG_PSEUDO_RANDOM 1
public static final byte ALG_SECURE_RANDOM 2