2

在互联网上我发现这个代码生成一个 SHA1 哈希:

        public static String hash(String str) {
            try {
                    MessageDigest mg = MessageDigest.getInstance("SHA-1");
                    byte[] result = mg.digest(str.getBytes());
                    StringBuffer sb = new StringBuffer();
                    for (int i = 0; i < result.length; i++) {
                            sb.append(Integer.toString((result[i] & 0xff) + 0x100, 16).substring(1));
                    }
                    return sb.toString();
            } catch (NoSuchAlgorithmException e) {
                    System.err.println("SHA-1 not found.");
                    return "";
            }
    }

但是为什么会有(result[i] & 0xff) + 0x100呢?

4

2 回答 2

6

字节已签名:它们可能是负数。当处理负字节时,会Integer.toString()生成一个以“FFFFFF”开头的字符串,但正字节不会发生这种情况,因此生成的字符串的长度是不固定的。将& 0xff字节转换为无符号整数。然后加上0x100,保证十六进制字符串为3个字符长;这是必需的,因为我们想要一个每个字节有 2 个十六进制数字的字符串,但是 0 到 15 之间的字节只会产生 1 个字符。最后第三个数字被丢弃substring(1)

我建议用 StringBuilder 替换 StringBuffer ,因为它效率更高,并且还可以指定初始缓冲区长度:

StringBuilder sb = new StringBuilder(result.length * 2);
于 2013-04-27T16:40:09.403 回答
1

& 0xff 是为了以防字节被提升为大于 8 位的东西并进行符号扩展。

符号扩展在这里是一个非常现实的问题,因此至少出于这个原因需要 0xff。

于 2013-04-27T16:16:31.233 回答