I have the following c code which id like to port to Java
unsigned long long* data=(unsigned long long*)pBuffer; // file data
unsigned long long crypt = 0x0000;
unsigned long long next_crypt;
unsigned int len = size >> 3;
for(unsigned int i=0; i<len;i++) {
next_crypt = crypt+data[i]-0xCAFEBABE;
data[i] = ((data[i]<<0x1d)|(data[i]>>0x23))+0xCAFEBABE;
data[i] = (data[i]<<0x0e)|(data[i]>>0x32);
data[i] = data[i] - crypt;
crypt = next_crypt;
}
I tried to port this to java using long, however this would result in negative values. Therefor i switched to biginteger since i have to do arithmetics (bit shifting etc).
I got the desired 64bit unsigned long value using BigInteger, however when i wanted to convert it to byte (BigInteger.toByteArray) it was 14 bytes long and no longer 8 bytes - so i cannot modify my array/file anymore. I tried using toLongValue() but the data was incorrect.
Thanks
Your C code is relying on bits being shifted off the high-order end of the unsigned long long
. (These are rotated around to the other end by the other shift.) BigInteger is arbitrary precision and hence has no end, so left-shifted bits are never shifted off.
You could construct a 64-bit BigInteger bitwise AND mask and AND it after the left shifts. This is an intuitive solution.
You could also just simply ignore the high-order bytes.
byte[] bar = foo.toByteArray();
if (bar.length > 8) {
bar = System.arrayCopy(bar, bar.length - 8, new byte[8], 0, 8);
}
If len
is large, then this simple solution would be wasteful of memory.
In any case there is a saner and higher-performing solution. Java's signed integer types are all guaranteed to have two's complement semantics. The bit semantics for arithmetic with two's complement integers and unsigned integers are identical--the difference is only in the interpretation of the value! So just use the original C code (substituting in Java's long
) and at the end, interpret them your way.
byte[] longToByteArray(long x) {
byte[] array = new byte[8];
for (int i = 7; i >= 0; i--) {
array[i] = (byte)x;
x >>>= 8;
}
}
By the way, be sure you replace the >>
operator in the C code with Java's >>>
operator.