'Hex String to Byte array conversion java
I know this question is asked a lot of times but please hear me out.
Previously I have tried following methods to convert hex string to byte array.
say my keyA = "D14E2C5A5B5F", I use byte[] of this key to authenticate a mifare card
First Approach:
byte[] ka = new BigInteger(keyA, 16).toByteArray();
(With this approach using ka
as key authenticates few cards and fails in few cards)
Second Approach:
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;
}
(With this approach using ka
as key authenticates few cards, but success rate is more than first approach and fails in few cards).
Am I missing anything? Is there any better way to convert hex string to byte array in java?
Thanks in advance.
Solution 1:[1]
The difference is in the leading 0
values created by 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;
}
prints
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]
See the extra leading 0
s.
Also, your hexStringToByteArray
is assuming an even number of hex digits - this may be an issue.
Something like this should be correct. It ensure the byte[]
is always the right length whatever the length of the string. You may wish to add an exception for when the string is too long.
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;
}
Solution 2:[2]
Try this.
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;
}
Solution 3:[3]
This is what works for me:
public static byte[] hexToByteData(String hex)
{
byte[] convertedByteArray = new byte[hex.length()/2];
int count = 0;
for( int i = 0; i < hex.length() -1; i += 2 )
{
String output;
output = hex.substring(i, (i + 2));
int decimal = (int)(Integer.parseInt(output, 16));
convertedByteArray[count] = (byte)(decimal & 0xFF);
count ++;
}
return convertedByteArray;
}
Solution 4:[4]
Here is my code that showed the best performance...
public static byte[] hex2bytes(String str) {
if( str == null || str.length() == 0 )
return null;
byte[] hex = new byte[str.length() / 2];
int tmp1, tmp2;
for(int i=0; i < hex.length; i++) {
tmp1 = str.charAt(i*2);
tmp2 = str.charAt(i*2+1);
hex[i] = (byte)( (tmp1 < 0x41 ? (tmp1 & 0x0F) << 4 : ((tmp1 & 0x0F) + 9) << 4)
| (tmp2 < 0x41 ? tmp2 & 0x0F : (tmp2 & 0x0F) + 9) );
}
return hex;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Community |
Solution 2 | Nakesh |
Solution 3 | gbossa |
Solution 4 |