为什么& 0xff应用于字节变量

时间:2018-01-26 18:56:47

标签: java byte logical-operators one-time-password

为什么& 0xff应用于基于时间的OTP(TOTP,RFC 6238)的参考实现中的字节变量?在我看来,这不会改变值,因为字节数据类型的长度为8位。

byte[] hash = hmac_sha(crypto, k, msg);
int offset = hash[hash.length - 1] & 0xf;

int binary =
  ((hash[offset] & 0x7f) << 24) |
  ((hash[offset + 1] & 0xff) << 16) |
  ((hash[offset + 2] & 0xff) << 8) |
  (hash[offset + 3] & 0xff);

int otp = binary % DIGITS_POWER[codeDigits];

此外,将XAND运算符应用于0x7f的第一个元素的原因是什么?它仍然可以生成一个10位数的数字,该数字大于DIGITS_POWER中的最大条目,即100 000 000

https://tools.ietf.org/html/rfc6238,第13页)

3 个答案:

答案 0 :(得分:1)

根据JLS,文字0xff的类型为int 同样根据JLS,当在byteint之间执行操作时,byte安全地加宽int并且结果是int

这意味着表达式:

hash[offset + 1] & 0xff

或多或少与:

相同
(int)(hash[offset + 1]) & 0xff

实际上,需要int作为后续位移操作的结果类型才有意义。

(hash[offset + 1] & 0xff) << 16

如果在byte上完成了位移,则位将旋转回原始位置(16是8的精确倍数)。

整个代码正在从int构建byte[]

使用高字节上使用的奇数掩码0x7f代替0xff来屏蔽最​​左边(或最高有效)位,即符号位,确保最终结果不是负面的。

答案 1 :(得分:1)

byte b = -5;
System.out.println(b);
System.out.println(b & 0xFF);

这会产生以下输出:

-5
251

执行&时,两个操作数首先被提升为32位。 -5表示为11111111111111111111111111111011,而0xFF仅为“24”零,最后为“8”,因此(-5) & 0xFF给出了11111011 (省略前导零)。

答案 2 :(得分:0)

操作确实会更改值。 byte & 0xff将带符号的字节转换为表示与字节位模式对应的无符号值的int。