package im.actor.runtime.crypto.primitives.util;
// Disabling Bounds checks for speeding up calculations
/*-[
#define J2OBJC_DISABLE_ARRAY_BOUND_CHECKS 1
]-*/
/**
* Various binary operation on binary strings
*
* @author Steve Kite (steve@actor.im)
*/
public class ByteStrings {
public static byte[] longToBytes(long v) {
byte[] data = new byte[8];
int offset = 0;
data[offset++] = (byte) ((v >> 56) & 0xFF);
data[offset++] = (byte) ((v >> 48) & 0xFF);
data[offset++] = (byte) ((v >> 40) & 0xFF);
data[offset++] = (byte) ((v >> 32) & 0xFF);
data[offset++] = (byte) ((v >> 24) & 0xFF);
data[offset++] = (byte) ((v >> 16) & 0xFF);
data[offset++] = (byte) ((v >> 8) & 0xFF);
data[offset++] = (byte) (v & 0xFF);
return data;
}
public static byte[] intToBytes(int v) {
byte[] data = new byte[4];
int offset = 0;
data[offset++] = (byte) ((v >> 24) & 0xFF);
data[offset++] = (byte) ((v >> 16) & 0xFF);
data[offset++] = (byte) ((v >> 8) & 0xFF);
data[offset++] = (byte) (v & 0xFF);
return data;
}
public static long bytesToLong(byte[] data) {
return bytesToLong(data, 0);
}
public static long bytesToLong(byte[] data, int offset) {
long a1 = data[offset + 3] & 0xFF;
long a2 = data[offset + 2] & 0xFF;
long a3 = data[offset + 1] & 0xFF;
long a4 = data[offset + 0] & 0xFF;
long res1 = (a1) + (a2 << 8) + (a3 << 16) + (a4 << 24);
offset += 4;
long b1 = data[offset + 3] & 0xFF;
long b2 = data[offset + 2] & 0xFF;
long b3 = data[offset + 1] & 0xFF;
long b4 = data[offset + 0] & 0xFF;
long res2 = (b1) + (b2 << 8) + (b3 << 16) + (b4 << 24);
offset += 4;
return (res2 + (res1 << 32)) & 0xFFFFFFFFFFFFFFFFL;
}
public static int bytesToInt(byte[] data) {
return bytesToInt(data, 0);
}
public static int bytesToInt(byte[] data, int offset) {
int a1 = data[offset + 3] & 0xFF;
int a2 = data[offset + 2] & 0xFF;
int a3 = data[offset + 1] & 0xFF;
int a4 = data[offset + 0] & 0xFF;
return ((a1) + (a2 << 8) + (a3 << 16) + (a4 << 24)) & 0xFFFFFFFF;
}
public static byte[] substring(byte[] data, int offset, int size) {
byte[] res = new byte[size];
for (int i = 0; i < size; i++) {
res[i] = data[i + offset];
}
return res;
}
public static byte[] merge(byte[]... data) {
int size = 0;
for (byte[] d : data) {
size += d.length;
}
byte[] res = new byte[size];
int offset = 0;
for (byte[] d : data) {
for (int i = 0; i < d.length; i++) {
res[offset++] = d[i];
}
}
return res;
}
public static void write(byte[] dest, int destOffset, byte[] src, int srcOffset, int length) {
for (int i = 0; i < length; i++) {
dest[destOffset + i] = src[srcOffset + i];
}
}
public static boolean isEquals(byte[] a, byte[] b) {
if (a.length != b.length) {
return false;
}
// To avoid timing attacks
int result = 0;
for (int i = 0; i < a.length; i++) {
result |= a[i] ^ b[i];
}
return result == 0;
}
public static int compare(byte[] a, byte[] b) {
if (a == null || b == null) {
throw new IllegalArgumentException("Arguments can't be null");
}
if (a.length > b.length) {
return 1;
}
for (int i = 0; i < a.length; i++) {
int ai = a[i] & 0xFF;
int bi = b[i] & 0xFF;
if (ai > bi) {
return 1;
} else if (ai < bi) {
return -1;
}
}
return 0;
}
}