Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: correct way to cast "unsigned" byte to int

Tags:

java

int

byte

I have spent several hours on looking for bug in third-party implementation of stream cipher Rabbit. There are several bugs, but one of them:

/**
 * @param IV An array of 8 bytes
 */
public void setupIV(final byte[] IV) {
    short[] sIV = new short[IV.length>>1];
    for(int i=0;i<sIV.length;++i) {
        sIV[i] = (short)((IV[i << 1] << 8) | IV[(2 << 1) + 1]);
    }
    setupIV(sIV);
}

The problem here is that byte IV[i << 1] is casted to int, but since Java doesn't have unsigned types, any value >= 0x80 is casted wrong. Say, byte 0xff becomes 0xffffffff, not 0x000000ff how author of the code above expected.

So I have added simple function:

   private int byte2int(byte b){
      int ret = b;
      if (ret < 0){
         ret += 256;
      }
      return ret;
   }

It works, but I'm wondering if this is correct way to do what I need? This solution seems dumb somewhat.

like image 490
Dmitry Frank Avatar asked Dec 25 '13 20:12

Dmitry Frank


People also ask

Can we convert byte to int in Java?

The intValue() method of Byte class is a built in method in Java which is used to return the value of this Byte object as int.

Can we assign byte to int?

We can directly assign the byte to the int data type. Secondly, we have a Wrapper class method intValue() that returns the value of byte as an int after widening the primitive conversion as we're storing a smaller data type into a larger one. If we take the byte as unsigned, then we have the Byte.

Can we type cast byte to char?

Two bytes for char vs one for byte is a problem in the general case, but here, on its own, that wouldn't matter as 'È' is a codepoint below 256, so could be stored in one byte. Problem here is that char is unsigned while byte isn't. Casting char to byte only works for ASCII, so not for codepoints above 127, like here.


1 Answers

I'm not sure how much this will help, but you may convert a signed byte to its unsigned value by running a binary AND operation with 0xFF.

Taking this logic further, you could check for overflows after the cast by running a similar AND on the int, with the appropriate operand. This of course assumes that you're always expecting positive or zero valued numbers, or in other words unsigned numbers.

(short)(((IV[i << 1] & 0xFF) << 8) | (IV[(2 << 1) + 1] & 0xFF))

The above is the result of putting it all together, courtesy of Radiodef.

like image 51
Siddharth Avatar answered Oct 03 '22 22:10

Siddharth