以下代码片段源自Core Java Vol 2(第7版),展示了如何使用Java创建SHA1和MD5指纹。
事实证明,唯一有效的功能是从文本文件中加载明文。
MessageDigestFrame.computeDigest()如何计算指纹,特别是使用位移模式(第171-172行)?
public void computeDigest(byte[] b)
{
currentAlgorithm.reset();
currentAlgorithm.update(b);
byte[] hash = currentAlgorithm.digest();
String d = "";
for (int i = 0; i < hash.length; i++)
{
int v = hash[i] & 0xFF;
if (v < 16) d += "0";
d += Integer.toString(v, 16).toUpperCase() + " ";
}
digest.setText(d);
}
答案 0 :(得分:2)
无论你给它什么方法都应该正常工作 - 如果你得到错误的结果,我怀疑你正在加载错误的文件。请显示该代码,我们可以帮助您解决出错的问题。
就代码而言,这一行:
int v = hash[i] & 0xFF;
基本上用于将字节视为无符号。字节用Java签名 - 这是语言中公认的设计错误 - 但我们希望打印出十六进制值,就好像它是无符号整数一样。只有最后8位的按位AND有效地将其转换为被视为无符号的字节的整数值。
(有更好的方法将字节数组转换为十六进制字符串,但这是另一回事。)
答案 1 :(得分:1)
它不是位移位,而是位屏蔽。 hash[i]
是一个字节。当它被加宽到整数时,你需要屏蔽掉更高的整数位,因为可能有符号扩展。
byte b = (byte)0xEF;
System.out.println("No masking: " + (int)b);
System.out.println("Masking: " + (int)(b & 0xFF));
答案 2 :(得分:0)
这剪了一下:
int v = hash[i] & 0xFF;
if (v < 16) d += "0";
d += Integer.toString(v, 16).toUpperCase() + " ";
首先将v的最低8位设置为0(因为0xFF是二进制的11111111)。 然后,如果结果数字只是十六进制的一位数(<16),则添加前导“0”。 最后将结果转换为十六进制并将其添加到字符串中。