我想使用java卡2.2.1将4字节十六进制数转换为十进制数。
例如:50ef7f19 - > 1357872921
对于此转换,我需要使用32位数字,因此最好将数据类型用作整数。但我不确定在Java卡中使用'int'。在规范中,'optional'表示整数。使用它有什么限制?如果我不使用int,还有其他方法可以用大数字进行计算吗?
答案 0 :(得分:2)
在Java Card Classic上使用int
的最大限制是,大多数实施Java Card Classic的智能卡都不支持它。另一个重要的限制是API几乎不支持整数。因此,即使您可以使用整数运算,API也只接受字节或短路。
我已经创建了一个特殊的类JCInteger,如果你感兴趣的话,它也可以执行32位算术。我仍然没有发布我的测试用例,所以要小心使用。您当然可以创建类似的方法来执行整数运算。如果你(非常)幸运,你的芯片也可以实现BigNumber
。
请注意,最初您可以从表示十六进制字符(ASCII或ASCII兼容编码)的字节转换为字节。之后,只有在需要时才能使用整数。通常,在终端上执行十六进制到字节转换,而不是在智能卡内。
如果您感兴趣,这里是一个快速(最小数量的分支)但字节码密集的方法从十六进制生成字节。不要忘记为它提供偶数个字节,可能会在混合中添加offset
和length
参数。
警告:未经测试的数组处理(已测试解码)
public static short fromHex(final byte[] hex, short hexOff, final short hexLen, final byte[] bin, short binOff) {
// reuses offsets parameters for reasons of (unproven) optimization
// === check hex input parameters ===
if (hexOff < 0 || hexOff >= hex.length) {
CardRuntimeException.throwIt((short) 'H');
}
final short hexEnd = (short) (hexOff + hexLen);
if (hexLen < 0 || hexEnd > hex.length || hexEnd < 0 || hexLen % 2 != 0) {
CardRuntimeException.throwIt((short) 'H');
}
// === calculate final output size ===
final short binLen = (short) (hex.length / 2);
// === check bin output parameters ===
if (binOff < 0 || binOff > bin.length) {
CardRuntimeException.throwIt((short) 'H');
}
if (binOff + binLen > bin.length || binOff + binLen < 0) {
CardRuntimeException.throwIt((short) 'H');
}
// === main loop ===
// pre-create the array
// set validity = 0 (0 = valid, anything else is not valid)
short validity = 0;
short c, isLetter, value, validDigitStruct, validDigit, validLetterStruct, validLetter;
while (hexOff < hexEnd) {
// --- calculate the value of the higher (more significant) tuple ---
c = hex[hexOff];
// check using calculation over bits to see if first char is a letter
// isLetter is zero if it is a digit, 1 if it is a letter (upper & lowercase)
isLetter = (short) ((c >> 6) & 1);
// calculate the tuple value using a multiplication to make up the difference between
// a digit character and an alpha-numerical character
// minus 1 for the fact that the letters are not zero based
value = (short) (((c & 0xF) + isLetter * (-1 + 10)) << 4);
// check validity of all the other bits
validity |= c >>> 7;
validDigitStruct = (short) ((c & 0x30) ^ 0x30);
validDigit = (short) (((c & 0x8) >> 3) * (c & 0x6));
validity |= (isLetter ^ 1) * (validDigitStruct | validDigit);
validLetterStruct = (short) (c & 0x18);
validLetter = (short) ((((c - 1) & 0x4) >> 2) * ((c - 1) & 0x2));
validity |= isLetter * (validLetterStruct | validLetter);
// --- do the same with the lower (less significant) tuple ---
c = hex[(short) (hexOff + 1)];
isLetter = (short) ((c >> 6) & 1);
value ^= (c & 0xF) + isLetter * (-1 + 10);
bin[binOff] = (byte) value;
// check validity of all the other bits
validity |= c >>> 7;
validDigitStruct = (short) ((c & 0x30) ^ 0x30);
validDigit = (short) (((c & 0x8) >> 3) * (c & 0x6));
validity |= (isLetter ^ 1) * (validDigitStruct | validDigit);
validLetterStruct = (short) (c & 0x18);
validLetter = (short) ((((c - 1) & 0x4) >> 2) * ((c - 1) & 0x2));
validity |= isLetter * (validLetterStruct | validLetter);
// --- update offsets ---
hexOff += 2;
binOff++;
}
if (validity != 0) {
// rewrite this for java card using e.g. CardRuntimeException.throwIt(short reason)
CardRuntimeException.throwIt((short) 'H');
}
return binLen;
}
答案 1 :(得分:1)
如果您只想将十六进制字节转换为十进制字符串(在字节数组中),那么您可以使用以下代码:
static byte[] output = new byte[10];
static short[] input = new short[4];
// the weights table for hex byte: 256^1 = 256, 256^2 = 65536, and 256^3 = 16777216
// 256^0 is moved outside the table for optimization (assigned as initial result value)
public static byte[] weight = {
6, 6, 6,
1, 3, 5,
2, 5, 2,
7, 5, 0,
7, 6, 0,
7, 0, 0,
6, 0, 0,
1, 0, 0,
0, 0, 0,
0, 0, 0
};
// the method to convert 4 bytes of hex into decimal string (10 byte arrays)
// final result is stored in output byte array
public static void convertHexToDecimalString(byte[] hex) {
// convert input to positive (byte array to short array)
for (byte i = 0; i < 4; i++) {
input[i] = (short) (hex[i] & 0x00FF);
}
// assign the least significant hex byte to result
short result = input[3];
byte offset = 0;
// loop to calculate and assign each decimal digit
for (byte i = 0; i < 10; i++) {
result = (short) ((weight[offset] * input[0])
+ (weight[offset + 1] * input[1])
+ (weight[offset + 2] * input[2]) + result);
output[9 - i] = (byte) (0x30 + result % 10);
result /= 10;
offset += 3;
}
}