简体   繁体   English

Java:将“unsigned”字节转换为int的正确方法

[英]Java: correct way to cast “unsigned” byte to int

I have spent several hours on looking for bug in third-party implementation of stream cipher Rabbit . 我花了几个小时寻找流密码Rabbit的第三方实现中的 bug。 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. 这里的问题是字节IV[i << 1]被转换为int ,但由于Java没有无符号类型,所以任何值>= 0x80都是错误的。 Say, byte 0xff becomes 0xffffffff , not 0x000000ff how author of the code above expected. 比方说,字节0xff变为0xffffffff ,而不是0x000000ff上面代码的作者如何预期。

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. 这个解决方案似乎有些愚蠢

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 . 我不确定这会有多大帮助,但是你可以通过运行带有0xFF的二进制AND操作将有符号字节转换为无符号值。

Taking this logic further, you could check for overflows after the cast by running a similar AND on the int, with the appropriate operand. 进一步采用这种逻辑,你可以通过在int上使用相应的操作数运行类似的AND来检查转换后的溢出。 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 . Radiodef礼貌地将上述内容融合在一起。

Use library functions for this operation (in ByteBuffer class). 使用库函数进行此操作(在ByteBuffer类中)。 You will be able to control endianness as a bonus. 您将能够控制字节序作为奖励。 This will rely on efficiency of Java creators. 这将依赖于Java创建者的效率。

package tests.StackOverflow.q20776371;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;

public class q20776371 {


    public static void main(String[] args) {

        byte[] bb = { (byte)0xFF, (byte)0x01, (byte)0x02, (byte)0x03 };

        ByteBuffer buffer1 = ByteBuffer.wrap(bb);

        // set endianness
        // buffer1.order(ByteOrder.BIG_ENDIAN);
        // buffer1.order(ByteOrder.LITTLE_ENDIAN);

        ShortBuffer buffer2 = buffer1.asShortBuffer();

        short[] ss = new short[bb.length>>1];
        buffer2.get(ss);

        for(int i=0; i<ss.length; ++i) {
            System.out.println(String.format("%04x", ss[i]));
        }
    }


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM