为什么& 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
。
答案 0 :(得分:1)
根据JLS,文字0xff
的类型为int
同样根据JLS,当在byte
和int
之间执行操作时,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。