当我使用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 html" target="_blank">hashedInt = new BigInteger(1, hash);
Assert.assertEquals(256, hashedInt.bitLength());
}
}
(是的,我正在使用JUnit 4)。此测试在第三个测试编号上失败,其中第二个断言失败,出现“预期256,但为255”
我在字节数组之间转换大整数的方式有什么问题吗?我能找到的所有Java的MessageDigest示例都使用它来散列字符串,而不是BigInteger,所以我不知道是否有“标准”方法可以将BigInteger与MessageDigest一起使用。或者,这是Java执行SHA-256的方式中的一个bug还是边缘情况,并且7153293421609183203421127438153268(我随机生成的一个数字)会导致哈希中的一个off-by-one错误?
顺便说一句,我已经尝试将哈希转换为负的BigInteger(使用新的BigInteger(-1,hash)),以查看符号位是否有问题,但我得到了完全相同的结果。
如果要运行足够数量的随机测试,您会看到大约一半的结果是256位长,四分之一是255位长,八分之一是254位长,等等。原因是哈希的每个位实际上都是随机的,所以高阶位(或准确地说,您要查看的任何其他特定位)有50%的概率为1,50%的概率为0,两个高阶位(或您想要查看的任何其他两个特定位)为00(或您想要测试的任何其他值)的25%概率,依此类推。
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%
忽略前导零
byte[] bytes = {0x0, 0x1};
System.out.println(new BigInteger(1, bytes).bitLength());
印刷品
1
不像你想象的那样16岁。
我应该读一下Javadoc,因为它是用biginger表示的。bitLength()
此BigInteger的最小补码表示中的位数,不包括符号位。
为什么他们不一样?我需要如何更改java版本以使其与Go版本完全相同?
问题内容: 我正在使用该程序包从数据库查询文本列。该数据库基于Microsoft SQL Server 2008 R2构建。SQL中列的数据类型为。 但是,当我运行时: 在SQL中,我期望(对于第一行): 但是,当我这样做时: 它返回: 255 。 所以我的问题是,是什么导致了这种截断,我该如何避免呢?谢谢!! 问题答案: 好的,看来我已经找到了解决方法。经过更多Google搜寻后,我发现: SQ
我正在尝试使用亚马逊的弹性代码转换器。这里我需要sha-256散列一个字符串;http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html 我已经尝试了我在网上找到的任何方法,但我找不到与页面和一些在线哈希网站提供的相同的结果。 下面是要散列的字符串,您可以从上面的链接中找到; 以下是预期结果: 3
问题内容: 我需要计算大文件(或其一部分)的SHA-256哈希。我的实现工作正常,但比C 的CryptoPP计算要慢得多(25分钟vs. 30 GB文件的10分钟)。我需要的是在C 和Java中执行时间相似,因此散列几乎可以同时准备好。我也尝试了Bouncy Castle的实现,但是它给了我相同的结果。这是我如何计算哈希值: 问题答案: 我的解释可能无法解决您的问题,因为它很大程度上取决于您的实际
我已经在诺基亚开发者论坛上发布了这个问题,所以请原谅我。 我正在编写一个应用程序,它需要查找一个URL的SHA-256哈希,该URL以唯一的值键控,即。在Java ME/J2ME中最好的方法是什么?
我在这里漏掉了什么?我试过上/下现金,每个字节之间的空格。我不确定还能试什么。 这个问题开始是因为我在Python中实现了这个,但在我担心代码之前,我试图理解为什么这是不同的。