I have some byte-int operations. But I cant figure out the problem.
First of all I have a hex data and I am holding it as an integer
public static final int hexData = 0xDFC10A;
And I am converting it to byte array with this function:
public static byte[] hexToByteArray(int hexNum)
{
ArrayList<Byte> byteBuffer = new ArrayList<>();
while (true)
{
byteBuffer.add(0, (byte) (hexNum % 256));
hexNum = hexNum / 256;
if (hexNum == 0) break;
}
byte[] data = new byte[byteBuffer.size()];
for (int i=0;i<byteBuffer.size();i++){
data[i] = byteBuffer.get(i).byteValue();
}
return data;
}
And I want to convert 3 byte array to integer back again how can I do that?
Or you can also suggest other converting functions like hex-to-3-bytes-array and 3-bytes-to-int thank you again.
UPDATE
In c# someone use below function but not working in java
public static int byte3ToInt(byte[] byte3){
int res = 0;
for (int i = 0; i < 3; i++)
{
res += res * 0xFF + byte3[i];
if (byte3[i] < 0x7F)
{
break;
}
}
return res;
}
This will give you the value:
(byte3[0] & 0xff) << 16 | (byte3[1] & 0xff) << 8 | (byte3[2] & 0xff)
This assumes, the byte array is 3 bytes long. If you need to convert also shorter arrays you can use a loop.
The conversion in the other direction (int to bytes) can be written with logical operations like this:
byte3[0] = (byte)(hexData >> 16);
byte3[1] = (byte)(hexData >> 8);
byte3[2] = (byte)(hexData);
You could use Java NIO's ByteBuffer:
byte[] bytes = ByteBuffer.allocate(4).putInt(hexNum).array();
And the other way round is possible too. Have a look at this.
As an example:
final byte[] array = new byte[] { 0x00, (byte) 0xdf, (byte) 0xc1, 0x0a };//you need 4 bytes to get an integer (padding with a 0 byte)
final int x = ByteBuffer.wrap(array).getInt();
// x contains the int 0x00dfc10a
If you want to do it similar to the C# code:
public static int byte3ToInt(final byte[] byte3) {
int res = 0;
for (int i = 0; i < 3; i++)
{
res *= 256;
if (byte3[i] < 0)
{
res += 256 + byte3[i]; //signed to unsigned conversion
} else
{
res += byte3[i];
}
}
return res;
}
to convert Integer to hex: integer.toHexString()
to convert hexString to Integer: Integer.parseInt("FF", 16);
I'm attempting to create a check sum by calculating the two's complement of the least significant byte of the sum of all the data bytes in an array.
So given an array:
byte[] bytes = new byte[] { 0x01, 0x02 };
would something like this work...
public static void main(String []args)
{
byte[] bytes = new byte[] { 0x01, 0x02 };
BigInteger bi = new BigInteger(bytes);
BigInteger biRes = bi.not().add(BigInteger.ONE);
byte[] result = biRes.toByteArray();
System.out.println("a: " + result);
System.out.println("b: " + javax.xml.bind.DatatypeConverter.printHexBinary(result));
}
Produces...
a: [B#34bdb859
b: FEFE
Is this correct?
I have another solution :
private static byte calculateChecksum8(byte[] bytes){
byte result = 0;
for(int i = 0; i < bytes.length; i++){
result += bytes[i];
}
result = (byte) (~ result & 0xFF);
result = (byte) (result +1 & 0xFF);
String str = String.format("%02x", result);
System.out.println(result+" = "+str.toUpperCase());
return result;
}
Someone to confirm ?
Just add up all the bytes, negate the resuit, cast or truncate it to a byte, and you're done.
I am suffering of a massive lack of speed when it comes to mutual authenticate with the card. This takes about 13 to 20 seconds which seems at least 10 times to much.
The slowest part is the "Get-Challenge" and I think it might be because of my construction of a non-leaking map and the seperate "rotate-left"
public static byte[] NLM (byte[] x, byte[] y) {
final byte[] f1 = new byte[] {(byte) 0x35, (byte) 0xB0,(byte) 0x88,(byte) 0xCC,(byte) 0xE1,(byte) 0x73}; //48-bit unsigned integer
final byte[] constant = new byte[] {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01}; //constant
byte[] Y = new byte[6]; //48-bit unsigned integer
byte[] Y1 = new byte[6]; //48-bit unsigned integer
byte[] R = new byte[6]; //48-bit unsigned integer
byte[] R1 = new byte[6]; //48-bit unsigned integer
short size = 6;
JCArrayInt[] Red = new JCArrayInt[2]; // array of 48-bit unsigned integers
JCArrayInt[] Mul = new JCArrayInt[2]; // array of 48-bit unsigned integers
byte k = 48;
Red[0] = new JCArrayInt(size);
Mul[0] = new JCArrayInt(size);
Red[1] = new JCArrayInt(size);
Mul[1] = new JCArrayInt(size);
Red[1].jcint = Utils.XOR(f1, constant);
Mul[1].jcint = x;
Y = y;
for (short i = 0; i < 48; i++) {
R = rotateLeft48(R);
R1 = Utils.AND(R, constant);
R = Utils.XOR(R, Red[R1[5]].jcint);
Y = rotateLeft48(Y);
Y1 = Utils.AND(Y, constant);
R = Utils.XOR(R, Mul[Y1[5]].jcint);
}
return R;
}
public static byte[] rotateLeft48 (byte[] data) {
byte t = (byte)((data[0] >>> 7) & 0x001);
short l = (short) (data.length - 1);
for (short i = 0; i < l; ++i) {
data[i] = (byte)(((data[i] << 1) & 0x0FE) | ((data[i + 1] >>> 7) & 0x001));
}
data[l] = (byte)(((data[l] << 1) & 0x0FE) | t);
return data;
}
I can live with it taking a little longer due to this overhead besides doing some XOR, AND, rotation and all they key generation and actual encrypting (done with AES-128).
should I use transient arrays (would that make that big of a difference)?
Using JCOP for all that!
I have to store some constant values (UUIDs) in byte array form in java, and I'm wondering what the best way to initialize those static arrays would be. This is how I'm currently doing it, but I feel like there must be a better way.
private static final byte[] CDRIVES = new byte[] { (byte)0xe0, 0x4f, (byte)0xd0,
0x20, (byte)0xea, 0x3a, 0x69, 0x10, (byte)0xa2, (byte)0xd8, 0x08, 0x00, 0x2b,
0x30, 0x30, (byte)0x9d };
private static final byte[] CMYDOCS = new byte[] { (byte)0xba, (byte)0x8a, 0x0d,
0x45, 0x25, (byte)0xad, (byte)0xd0, 0x11, (byte)0x98, (byte)0xa8, 0x08, 0x00,
0x36, 0x1b, 0x11, 0x03 };
private static final byte[] IEFRAME = new byte[] { (byte)0x80, 0x53, 0x1c,
(byte)0x87, (byte)0xa0, 0x42, 0x69, 0x10, (byte)0xa2, (byte)0xea, 0x08,
0x00, 0x2b, 0x30, 0x30, (byte)0x9d };
...
and so on
Is there anything I could use that may be less efficient, but would look cleaner?
for example:
private static final byte[] CDRIVES =
new byte[] { "0xe04fd020ea3a6910a2d808002b30309d" };
You can use an utility function to convert from the familiar hexa string to a byte[].
When used to define a final static constant, the performance cost is irrelevant.
Since Java 17
There's now java.util.HexFormat which lets you do
byte[] CDRIVES = HexFormat.of().parseHex("e04fd020ea3a6910a2d808002b30309d");
This utility class lets you specify a format which is handy if you find other formats easier to read or when you're copy-pasting from a reference source:
byte[] CDRIVES = HexFormat.ofDelimiter(":")
.parseHex("e0:4f:d0:20:ea:3a:69:10:a2:d8:08:00:2b:30:30:9d");
Before Java 17
I'd suggest you use the function defined by Dave L in Convert a string representation of a hex dump to a byte array using Java?
byte[] CDRIVES = hexStringToByteArray("e04fd020ea3a6910a2d808002b30309d");
I insert it here for maximum readability :
public static 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;
}
byte[] myvar = "Any String you want".getBytes();
String literals can be escaped to provide any character:
byte[] CDRIVES = "\u00e0\u004f\u00d0\u0020\u00ea\u003a\u0069\u0010\u00a2\u00d8\u0008\u0000\u002b\u0030\u0030\u009d".getBytes();
In Java 6, there is a method doing exactly what you want:
private static final byte[] CDRIVES = javax.xml.bind.DatatypeConverter.parseHexBinary("e04fd020ea3a6910a2d808002b30309d")
Alternatively you could use Google Guava:
import com.google.common.io.BaseEncoding;
private static final byte[] CDRIVES = BaseEncoding.base16().lowerCase().decode("E04FD020ea3a6910a2d808002b30309d".toLowerCase());
The Guava method is overkill, when you are using small arrays. But Guava has also versions that can parse input streams. This is a nice feature when dealing with big hexadecimal inputs.
You can use the Java UUID class to store these values, instead of byte arrays:
UUID
public UUID(long mostSigBits,
long leastSigBits)
Constructs a new UUID using the specified data. mostSigBits is used for the most significant 64 bits of the UUID and leastSigBits becomes the least significant 64 bits of the UUID.
Smallest internal type, which at compile time can be assigned by unsigned hex numbers is char, as
private static final char[] CDRIVES_char = new char[] {0xe0, 0xf4, ...};
In order to have an equivalent byte array one might deploy conversions as
public static byte[] charToByteArray(char[] x)
{
final byte[] res = new byte[x.length];
for (int i = 0; i < x.length; i++)
{
res[i] = (byte) x[i];
}
return res;
}
public static byte[][] charToByteArray(char[][] x)
{
final byte[][] res = new byte[x.length][];
for (int i = 0; i < x.length; i++)
{
res[i] = charToByteArray(x[i]);
}
return res;
}
A solution with no libraries, dynamic length returned, unsigned integer interpretation (not two's complement)
public static byte[] numToBytes(int num){
if(num == 0){
return new byte[]{};
}else if(num < 256){
return new byte[]{ (byte)(num) };
}else if(num < 65536){
return new byte[]{ (byte)(num >>> 8),(byte)num };
}else if(num < 16777216){
return new byte[]{ (byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
}else{ // up to 2,147,483,647
return new byte[]{ (byte)(num >>> 24),(byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
}
}
You can use this utility function:
public static byte[] fromHexString(String src) {
byte[] biBytes = new BigInteger("10" + src.replaceAll("\\s", ""), 16).toByteArray();
return Arrays.copyOfRange(biBytes, 1, biBytes.length);
}
Unlike variants of Denys Séguret and stefan.schwetschke, it allows inserting separator symbols (spaces, tabs, etc.) into the input string, making it more readable.
Example of usage:
private static final byte[] CDRIVES
= fromHexString("e0 4f d0 20 ea 3a 69 10 a2 d8 08 00 2b 30 30 9d");
private static final byte[] CMYDOCS
= fromHexString("BA8A0D4525ADD01198A80800361B1103");
private static final byte[] IEFRAME
= fromHexString("80531c87 a0426910 a2ea0800 2b30309d");
As far as a clean process is concerned you can use ByteArrayOutputStream object...
ByteArrayOutputStream bObj = new ByteArrayOutputStream();
bObj.reset();
//write all the values to bObj one by one using
bObj.write(byte value)
// when done you can get the byte[] using
CDRIVES = bObj.toByteArray();
//than you can repeat the similar process for CMYDOCS and IEFRAME as well,
NOTE This is not an efficient solution if you really have small array.
My preferred option in this circumstance is to use org.apache.commons.codec.binary.Hex which has useful APIs for converting between Stringy hex and binary. For example:
Hex.decodeHex(char[] data) which throws a DecoderException if there are non-hex characters in the array, or if there are an odd number of characters.
Hex.encodeHex(byte[] data) is the counterpart to the decode method above, and spits out the char[].
Hex.encodeHexString(byte[] data) which converts back from a byte array to a String.
Usage: Hex.decodeHex("dd645a2564cbe648c8336d2be5eafaa6".toCharArray())
You can use the bouncy castle package,
Maven import,
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
Java code,
byte[] CDRIVES = Hex.decode("e04fd020ea3a6910a2d808002b30309d");
private static final int[] CDRIVES = new int[] {0xe0, 0xf4, ...};
and after access convert to byte.
I'm trying to send a Java UUID to C++, where it will be used as a GUID, then send it back and see it as a UUID, and I'm hoping to send it across as just 16 bytes.
Any suggestions on an easy way to do this?
I've got a complicated way of doing it, sending from Java to C++, where I ask the UUID for its least and most significant bits, write this into a ByteBuffer, and then read it out as bytes.
Here is my silly-complicated way of getting 2 longs out of a UUID, sending them to C++:
Java
public static byte[] asByteArray(UUID uuid)
{
long msb = uuid.getMostSignificantBits();
long lsb = uuid.getLeastSignificantBits();
byte[] buffer = new byte[16];
for (int i = 0; i < 8; i++) {
buffer[i] = (byte) (msb >>> 8 * (7 - i));
}
for (int i = 8; i < 16; i++) {
buffer[i] = (byte) (lsb >>> 8 * (7 - i));
}
return buffer;
}
byte[] bytesOriginal = asByteArray(uuid);
byte[] bytes = new byte[16];
// Reverse the first 4 bytes
bytes[0] = bytesOriginal[3];
bytes[1] = bytesOriginal[2];
bytes[2] = bytesOriginal[1];
bytes[3] = bytesOriginal[0];
// Reverse 6th and 7th
bytes[4] = bytesOriginal[5];
bytes[5] = bytesOriginal[4];
// Reverse 8th and 9th
bytes[6] = bytesOriginal[7];
bytes[7] = bytesOriginal[6];
// Copy the rest straight up
for ( int i = 8; i < 16; i++ )
{
bytes[i] = bytesOriginal[i];
}
// Use a ByteBuffer to switch our ENDIAN-ness
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(16);
buffer.order(java.nio.ByteOrder.BIG_ENDIAN);
buffer.put(bytes);
buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN);
buffer.position(0);
UUIDComponents x = new UUIDComponents();
x.id1 = buffer.getLong();
x.id2 = buffer.getLong();
C++
google::protobuf::int64 id1 = id.id1();
google::protobuf::int64 id2 = id.id2();
char* pGuid = (char*) &guid;
char* pGuidLast8Bytes = pGuid + 8;
memcpy(pGuid, &id1, 8);
memcpy(pGuidLast8Bytes, &id2, 8);
This works, but seems way too complex, and I can't yet get it working in the other direction.
(I'm using google protocol buffers to send the two longs back and forth)
Alex
I got something working.
Instead of sending it across as two longs, I send it across as bytes, here is the Java code:
public static UUID fromBytes( ByteString byteString)
{
byte[] bytesOriginal = byteString.toByteArray();
byte[] bytes = new byte[16];
// Reverse the first 4 bytes
bytes[0] = bytesOriginal[3];
bytes[1] = bytesOriginal[2];
bytes[2] = bytesOriginal[1];
bytes[3] = bytesOriginal[0];
// Reverse 6th and 7th
bytes[4] = bytesOriginal[5];
bytes[5] = bytesOriginal[4];
// Reverse 8th and 9th
bytes[6] = bytesOriginal[7];
bytes[7] = bytesOriginal[6];
// Copy the rest straight up
for ( int i = 8; i < 16; i++ )
{
bytes[i] = bytesOriginal[i];
}
return toUUID(bytes);
}
public static ByteString toBytes( UUID uuid )
{
byte[] bytesOriginal = asByteArray(uuid);
byte[] bytes = new byte[16];
// Reverse the first 4 bytes
bytes[0] = bytesOriginal[3];
bytes[1] = bytesOriginal[2];
bytes[2] = bytesOriginal[1];
bytes[3] = bytesOriginal[0];
// Reverse 6th and 7th
bytes[4] = bytesOriginal[5];
bytes[5] = bytesOriginal[4];
// Reverse 8th and 9th
bytes[6] = bytesOriginal[7];
bytes[7] = bytesOriginal[6];
// Copy the rest straight up
for ( int i = 8; i < 16; i++ )
{
bytes[i] = bytesOriginal[i];
}
return ByteString.copyFrom(bytes);
}
private static byte[] asByteArray(UUID uuid)
{
long msb = uuid.getMostSignificantBits();
long lsb = uuid.getLeastSignificantBits();
byte[] buffer = new byte[16];
for (int i = 0; i < 8; i++) {
buffer[i] = (byte) (msb >>> 8 * (7 - i));
}
for (int i = 8; i < 16; i++) {
buffer[i] = (byte) (lsb >>> 8 * (7 - i));
}
return buffer;
}
private static UUID toUUID(byte[] byteArray) {
long msb = 0;
long lsb = 0;
for (int i = 0; i < 8; i++)
msb = (msb << 8) | (byteArray[i] & 0xff);
for (int i = 8; i < 16; i++)
lsb = (lsb << 8) | (byteArray[i] & 0xff);
UUID result = new UUID(msb, lsb);
return result;
}
Doing it this way, the bytes can be used straight up on the C++ side. I suppose the switching around of the order of the bytes could be done on either end.
C++
memcpy(&guid, data, 16);
It's possibly easiest to use getMostSignificantBits and getLeastSignificant bits to get long values, and send those. Likewise you can reconstruct the UUID from those two longs using the appropriate constructor.
It's a shame there isn't a toByteArray/fromByteArray pair of methods :(
Your current way is fine, nothing wrong about doing it that way.
Another approace is yo just communicate with the string representation of the uuid, send the string, parse it in c++.
Btw, bytes do not have endianess, Unless you're casting a byte/char array or similar to an integer type, you just determine the endianess by assigning the bytes back in the approprate order.
Here is what I do to convert a C++ GUID to a Java UUID. On the C++ side, the GUID struct is just converted to bytes. The conversion to C++ can then just go along the same lines.
public static UUID cppGuidBytesToUuid(byte[] cppGuid) {
ByteBuffer b = ByteBuffer.wrap(cppGuid);
b.order(ByteOrder.LITTLE_ENDIAN);
java.nio.ByteBuffer out = java.nio.ByteBuffer.allocate(16);
out.order(ByteOrder.BIG_ENDIAN);
out.putInt(b.getInt());
out.putShort(b.getShort());
out.putShort(b.getShort());
out.put(b);
out.position(0);
return new UUID(out.getLong(), out.getLong());
}
// Here is the JNI code ;-)
jbyteArray GUID2ByteArray(JNIEnv *env,GUID* guid)
{
if (guid == NULL)
return NULL;
jbyteArray jGUID = env->NewByteArray(sizeof(GUID));
if (jGUID == NULL)
return NULL;
env->SetByteArrayRegion(jGUID,0,sizeof(GUID),(signed char*)(guid));
if (env->ExceptionOccurred() != NULL)
return NULL;
return jGUID;
}
Perhaps you could explain why you are not just doing.
UUID uuid =
x.id1 = uuid.getMostSignificantBits();
x.id2 = uuid.getLeastSignificantBits();
P.S. As I read #Jon Skeet's post again, I think this is much the same advice. ;)