当我使用 Java 的 MessageDigest
计算 BigInteger
的 SHA-256 散列时,我遇到了一些奇怪的行为。看起来哈希值有时有 256 位,但有时只有 255 位。这是我用来测试 BigInteger 哈希的代码:
@Test
public void testSHA256LengthConsistent() {
MessageDigest sha256 = null;
try {
sha256 = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
Assert.fail("NoSuchAlgorithmException. Can't construct the MessageDigest.");
}
BigInteger[] tests = {new BigInteger("15902493"), new BigInteger("5189087324092341824"), new BigInteger("7153293421609183203421127438153268")};
for(BigInteger testNum : tests) {
byte[] hash = sha256.digest(testNum.toByteArray());
Assert.assertEquals(32, hash.length); //256 bits is 32 bytes
BigInteger hashedInt = new BigInteger(1, hash);
Assert.assertEquals(256, hashedInt.bitLength());
}
}
(是的,我正在使用 JUnit 4)。此测试在第三个测试编号上失败,其中第二个断言失败并显示“预期 256 但实际为 255”。
我将 BigIntegers 与字节数组相互转换的方式有问题吗?我能找到的关于 Java 的 MessageDigest 的所有示例都使用它来散列字符串,而不是 BigIntegers,所以我不知道是否有将 BigIntegers 与 MessageDigest 一起使用的“标准”方法。或者,这是 Java 执行 SHA-256 的方式中的错误或边缘情况,并且 7153293421609183203421127438153268(我随机生成的数字)中的某些东西导致散列中的差一错误?
顺便说一句,我已经尝试将哈希值转换为负数 BigInteger(使用 new BigInteger(-1, hash)
)以查看符号位是否有问题,但是我得到完全相同的结果。
最佳答案
忽略前导零
byte[] bytes = {0x0, 0x1};
System.out.println(new BigInteger(1, bytes).bitLength());
打印
1
不是您预期的 16。
我应该阅读 Javadoc,因为它在 BigInteger.bitLength() 中说明了
number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit.
关于Java 的 SHA-256 有时会返回 255 位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12924185/