当我使用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)
)来查看它是否与符号位有问题,但我得到了完全相同的结果。
答案 0 :(得分:7)
忽略前导零
byte[] bytes = {0x0, 0x1};
System.out.println(new BigInteger(1, bytes).bitLength());
打印
1
不像你期望的那样16岁。
我应该阅读Javadoc,因为它在BigInteger.bitLength()
中说明此BigInteger的最小二进制补码表示中的位数,不包括符号位。
答案 1 :(得分:0)
如果你要运行足够数量的随机测试,你会看到大约一半的结果是256位长,四分之一255位长,八位长254位长等等。原因是每个散列的位有效地是随机的,因此高位(或者,确切地说,您需要注意的任何其他特定位)为1和50%的概率为50%,即0%和25%两个高阶位(或您想要查看的任何其他两个特定位)的概率为00(或您需要测试的任何其他值),等等。
public static void main(final String[] args) throws Exception {
final Random random = new Random();
final int[] bits = new int[257];
for (int i = 0; i < 10000; i++) {
final MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
final BigInteger testNum = new BigInteger(100, random);
final byte[] hash = sha256.digest(testNum.toByteArray());
final BigInteger hashedInt = new BigInteger(1, hash);
bits[hashedInt.bitLength()]++;
}
for (int i = 0; i < bits.length; i++) {
if (bits[i] > 0) {
System.out.println(i + " / " + bits[i]);
}
}
}
制备:
位:244计数:2 0.02% 比特:245数:3 0.03% 位:246计数:4 0.04% 位:247计数:7 0.07% 位:248计数:20 0.2% 位:249计数:33 0.33% 比特:250总数:70 0.7% 比特:251数:168 1.68% 位:252计数:296 2.96% 比特:253人数:657 6.57% 位:254数:1238 12.38% 比特:255数:2510 25.1% 位:256计数:4992 49.92%