当前位置: 首页 > 知识库问答 >
问题:

Java的SHA-256有时返回255位

公冶谦
2023-03-14

当我使用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)),以查看符号位是否有问题,但我得到了完全相同的结果。

共有2个答案

马安邦
2023-03-14

如果要运行足够数量的随机测试,您会看到大约一半的结果是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%

仲鸿风
2023-03-14

忽略前导零

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中实现了这个,但在我担心代码之前,我试图理解为什么这是不同的。