Converting String to byte array for hex values - java

I am using a Android Phone to communicate with a BLE device.
The method to send data for the library needs byte[],
sharing one of the static example snippet:
public static final byte dataRequest[] = { 0x23, 0x57, 0x09, 0x03, (byte) 0xD4};
sendDataToDevice(dataRequest);
The data i am receiving from the user is in String, for example
String str1 = "D4";
now my question is , how to convert this String value (which is actually a hex value in String datatype) to byte, so that i can store these dynamic String values and convert and then insert it into byte[] like ,
byte[0] = convertToByte(str1);
where byte[0] must store value as 0xD9 or like the format given in static example.

You should just be able to use Integer#parseInt with a radix of 16 (hexadecimal) to convert a String to an int (which you can then cast to a byte and store in your array):
String str1 = "D4";
byte b = (byte) Integer.parseInt(str1, 16);
System.out.println(b);
Output:
-44
Note: Byte#parseByte can't be used in your example, as Byte#parseByte uses Integer#parseInt internally and parses D4 as 212, which is not a valid value for a signed byte.

Related

How does encoding/decoding bytes work in Java?

Little background: I'm doing cryptopals challenges and I finished https://cryptopals.com/sets/1/challenges/1 but realized I didn't learn what I guess is meant to be learned (or coded).
I'm using the Apache Commons Codec library for Hex and Base64 encoding/decoding. The goal is to decode the hex string and re-encode it to Base64. The "hint" at the bottom of the page says "Always operate on raw bytes, never on encoded strings. Only use hex and base64 for pretty-printing."
Here's my answer...
private static Hex forHex = new Hex();
private static Base64 forBase64 = new Base64();
public static byte[] hexDecode(String hex) throws DecoderException {
byte[] rawBytes = forHex.decode(hex.getBytes());
return rawBytes;
}
public static byte[] encodeB64(byte[] bytes) {
byte[] base64Bytes = forBase64.encode(bytes);
return base64Bytes;
}
public static void main(String[] args) throws DecoderException {
String hex = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
//decode hex String to byte[]
byte[] myHexDecoded = hexDecode(hex);
String myHexDecodedString = new String(myHexDecoded);
//Lyrics from Queen's "Under Pressure"
System.out.println(myHexDecodedString);
//encode myHexDecoded to Base64 encoded byte[]
byte[] myHexEncoded = encodeB64(myHexDecoded);
String myB64String = new String(myHexEncoded);
//"pretty printing" of base64
System.out.println(myB64String);
}
...but I feel like I cheated. I didn't learn how to decode bytes that were encoded as hex, and I didn't learn how to encode "pure" bytes to Base64, I just learned how to use a library to do something for me.
If I were to take a String in Java then get its bytes, how would I encode those bytes into hex? For example, the following code snip turns "Hello" (which is readable English) to the byte value of each character:
String s = "Hello";
char[] sChar = s.toCharArray();
byte[] sByte = new byte[sChar.length]
for(int i = 0; i < sChar.length; i++) {
sByte[i] = (byte) sChar[i];
System.out.println("sByte[" + i + "] = " +sByte[i]);
}
which yields sByte[0] = 72, sByte[1] = 101, sByte[2] = 108, sByte[3] = 108, sByte[4] = 111
Lets use 'o' as an example - I am guessing its decimal version is 111 - do I just take its decimal version and change that to its hex version?
If so, to decode, do I just take the the characters in the hex String 2 at a time, decompose them to decimal values, then convert to ASCII? Will it always be ASCII?
to decode, do I just take the the characters in the hex String 2 at a time, decompose them to decimal values, then convert to ASCII? Will it always be ASCII?
No. You take the characters 2 at a time, transform the character '0' to the numeric value 0, the character '1' to the numeric value 1, ..., the character 'a' (or 'A', depending on which encoding you want to support) to the numeric value 10, ..., the character 'f' or 'F' to the numeric value 15.
Then you multiply the first numeric value by 16, and you add it to the second numeric value to get the unsigned integer value of your byte. Then you transform that unsigned integer value to a signed byte.
ASCII has nothing to do with this algorithm.
To see how it's done in practice, since commons-codec is open-source, you can just look at its implementation.

Hardcode string on a javacard

I need to save a variable on a JavaCard. Javacard's don't support Strings, so I have to hardcode some String variables as byte arrays.
Unfortunately, I don't know how to achieve this format:
new byte[]{0x4A, 0x61, 0x6E, 0x20, 0x56, 0x6F, 0x73, 0x73, 0x61, 0x65, 0x72, 0x74};
Is there an online tool available? Or is there a program that output's it that way so I can copy paste the output and use that for hardcoding?
You don't need any tool for that. If you want to store an string in your applet in the applet developing step (I mean in the programming phase) use a byte array as below :
public static byte[] myFiled = {(byte)'T', (byte)'E', (byte)'S', (byte)'T'};
or use Hex values instead of the letters:
public static byte[] myFiled = {(byte)0x10, (byte)0x11, (byte)0x12, (byte)0x13};
It's necessary to cast the array elements to byte explicitly
And if you want to store the string after developing in installing your applet, first convert it to its hex value using this online tool for example, and then send it to card in the data field of an APDU command. And then using arrayCopy or arrayCopyNonAtomic methods store it in you byte array.
Just use String::getBytes():
String a = "HelloWorld";
byte[] inBytes = a.getBytes();
System.out.println(Arrays.toString(inBytes));
OUTPUT:
[72, 101, 108, 108, 111, 87, 111, 114, 108, 100]
IDEONE DEMO
ADD ON: as #AndyTurner mentioned, you can specify charset using String::getBytes(Charset).
Find here a nice explanation.
Here's a method to convert a string to an array literal that represents US-ASCII–encoded bytes.
static String format(String str)
{
byte[] encoded = str.getBytes(StandardCharsets.US_ASCII);
return IntStream.range(0, encoded.length)
.mapToObj(idx -> String.format("0x%02X", encoded[idx]))
.collect(Collectors.joining(", ", "{ ", " }"));
}
Because it uses ASCII, the high bit of each byte is zero, and no downcasts to byte are required.

Convert int to hex byte value

I want to read block wise data of NFC tag. For which the command is a byte array and it needs block number.
public static byte[] readSingleBlockCmd(int blockNo) {
byte[] cmd = new byte[3];
cmd[0] = (byte) 0x02;//flag
cmd[1] = (byte) 0x23;//cmd
cmd[2]= (byte)blockNo;
return cmd;
}
How can I change the int blockNo to its hexadecimal value , which can be cast to byte .I want the byte value and not an byte []
I have gone through the following links
Convert integer into byte array (Java)
How to autoconvert hexcode to use it as byte[] in Java?
Java integer to byte array
Thanks!
Converting an integer (in decimal) to hex can be done with the following line:
String hex = Integer.toHexString(blockNo);
Then to convert it to byte, you can use
Byte.parseByte(hex,16);
But if all you wanted to do is convert the parameter to bytes:
Byte.parseByte(blockNo);
would work too I guess. Correct me if I'm wrong.

How to create a Java Hexadecimal Array

This does not seem to be appropriate. Is there a way to create a hexadecimal array?
float[] bitBytes = {0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1};
for (int k = 0; k < alot; k++) {
BitSet.set(increment++, ((array[k] & (bitBytes[k%8]& 0xff)) != 0));
}
Hexadecimals is a representation of bytes as a String, or at least an array of characters. It is mainly used for human consumption, as it is easier to see the bit value of the bytes.
To create a byte array containing byte values, you can use the following construct:
final byte[] anArray = { (byte) 0x10, (byte) 0x80 };
The cast to byte - (byte) - is really only required for values of 0x80 or over as bytes are signed in Java and therefore only have values ranging from -0x80 to 0x7F. Normally we only deal with unsigned values though, so we need the cast.
Alternatively, for larger strings, it can be useful to simply supply a hexadecimal string to a decoder. Unfortunately the idiots that have thought out the standard API still haven't defined a standard hexadecimal codec somewhere in java.lang or java.util.
So you can use another library, such as the Apache codec library or a self written function. Stackoverflow to the rescue.
Convert a string representation of a hex dump to a byte array using Java?
If you want to have a BitSet of the values in the byte array, please use BitSet.valueOf(byte[])
byte[] biteBytes = new byte[8];
for (int j = 0; j < bitBytes.length; j++) {
bitBytes[j] = (byte) (Math.pow(2,j));
}

Convert INT(0-255) to UTF8 char in Java

since I need to control some devices, I need to send some bytes to them. I'm creating those bytes by putting some int values together (and operator), creating a byte and finally attaching it to a String to send it over the radio function to the robot.
Unfortuantely Java has some major issues doing that (unsigned int problem)
Does anybody know, how I can convert an integer e.g.
x = 223;
to an 8-bit character in Java to attach it to a String ?
char = (char)x; // does not work !! 16 bit !! I need 8 bit !
A char is 16-bit in Java. Use a byte if you need an 8-bit datatype.
See How to convert Strings to and from UTF8 byte arrays in Java on how to convert a byte[] to String with UTF-8 encoding.
Sending a java.lang.String over the wire is probably the wrong approach here, since Strings are always 16-bit (since Java was designed for globalization and stuff). If your radio library allows you to pass a byte[] instead of a String, that will allow you to send 8-bit values without needing to worry about converting to UTF8. As far as converting from an int to an unsigned byte, you'll probably want to look at this article.
int to array of bytes
public byte[] intToByteArray(int num){
byte[] intBytes = new byte[4];
intBytes[0] = (byte) (num >>> 24);
intBytes[1] = (byte) (num >>> 16);
intBytes[2] = (byte) (num >>> 8);
intBytes[3] = (byte) num;
return intBytes;
}
note endianness here is big endian.

Categories