Преобразование шестнадцатеричной строки в байтовый массив Java - PullRequest
0 голосов
/ 06 июня 2018

Я знаю, что этот вопрос задавался много раз, но, пожалуйста, выслушайте меня.

Ранее я пробовал следующие методы для преобразования шестнадцатеричной строки в байтовый массив.

say my keyA = "D14E2C5A5B5F ", я использую байт [] этого ключа для аутентификации карты mifare

Первый подход:

byte[] ka = new BigInteger(keyA, 16).toByteArray();

(При этом подходе используется ka в качестве ключапроверяет подлинность нескольких карточек и дает сбой в нескольких карточках)

Второй подход:

byte[] ka = hexStringToByteArray(keyA);
public byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

(При таком подходе использование ka в качестве ключа проверяет подлинность нескольких карточек, но вероятность успеха больше, чем первый подход ине удается в нескольких картах).

Я что-то упустил?Есть ли лучший способ преобразовать шестнадцатеричную строку в байтовый массив в Java?

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Попробуйте это.

public static byte[] hexStringToByteArray(String s) {
    byte[] b = new byte[s.length() / 2];
    for (int i = 0; i < b.length; i++) {
      int index = i * 2;
      int v = Integer.parseInt(s.substring(index, index + 2), 16);
      b[i] = (byte) v;
    }
    return b;
  }
0 голосов
/ 06 июня 2018

Разница в ведущих 0 значениях, созданных BigInteger.

public void test() {
    test("D14E2C5A5B5F");
    test("00D14E2C5A5B5F");
    test("614E2C5A5B5F");
    test("00614E2C5A5B5F");
}

private void test(String s) {
    byte[] ka = new BigInteger(s, 16).toByteArray();
    byte[] kb = hexStringToByteArray(s);
    if (!Arrays.equals(ka, kb)) {
        System.out.println(s + ":" + Arrays.toString(ka) + " != " + Arrays.toString(kb));
    }
}

public byte[] hexStringToByteArray(String s) {
    byte[] data = new byte[s.length()/2];
    for (int i = 0; i < data.length; i ++) {
        data[i] = (byte) ((Character.digit(s.charAt(i*2), 16) << 4)
                + Character.digit(s.charAt(i*2 + 1), 16));
    }
    return data;
}

отпечатками

D14E2C5A5B5F: [0, -47, 78, 44,90, 91, 95]! = [-47, 78, 44, 90, 91, 95]

00614E2C5A5B5F: [97, 78, 44, 90, 91, 95]! = [0, 97,78, 44, 90, 91, 95]

См. Дополнительные ведущие 0 s.

Кроме того, ваш hexStringToByteArray равен при условии четногоколичество шестнадцатеричных цифр - это может быть проблемой.

Примерно так должно быть правильно.Это гарантирует, что byte[] всегда будет правильной длины независимо от длины строки.Вы можете добавить исключение, если строка слишком длинная.

public byte[] asKey(String hex, int bytes) {
    // Make sure the byte [] is always the correct length.
    byte[] key = new byte[bytes];
    // Using i as the distance from the END of the string.
    for (int i = 0; i < hex.length() && (i / 2) < bytes; i++) {
        // Pull out the hex value of the character.
        int nybble = Character.digit(hex.charAt(hex.length() - 1 - i), 16);
        if ((i & 1) != 0) {
            // When i is odd we shift left 4.
            nybble = nybble << 4;
        }
        // Use OR to avoid sign issues.
        key[bytes - 1 - (i / 2)] |= (byte) nybble;
    }
    return key;
}
...