【问题标题】:Implementation of SHA-1 yields different hashes than the `java.security` implementationSHA-1 的实现产生的散列值与 `java.security` 实现不同
【发布时间】:2019-10-05 06:51:31
【问题描述】:

我正在尝试在 Java 11 中实现 SHA-1 算法,在测试散列算法时,我得到的散列值与使用 SHA-1 的 java.security 实现散列时不同。

我试图遵循的伪代码可以在on Wikipedia找到。

public static byte[] hash(byte[] message) {
    int h0 = 0x67452301;
    int h1 = 0xEFCDAB89;
    int h2 = 0x98BADCFE;
    int h3 = 0x10325476;
    int h4 = 0xC3D2E1F0;

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    out.writeBytes(message);
    out.write(0x00000080);
    while (out.size() % 64 != 56) out.write(0x00000000);
    out.writeBytes(ByteBuffer.allocate(8).putLong(message.length).array());
    byte[] data = out.toByteArray();

    for (int j = 0; j < data.length / 64; ++j) {
        int[] w = new int[80];
        for (int i = 0; i < 16; ++i) {
            w[i] = ByteBuffer.wrap(data, j * 64 + i * 4, 4).getInt();
        }

        for (int i = 16; i < 80; ++i) {
            w[i] = leftrotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
        }

        int a = h0;
        int b = h1;
        int c = h2;
        int d = h3;
        int e = h4;

        for (int i = 0; i < 80; ++i) {
            final int f, k;
            if (i < 20) {
                f = (b & c) | ((~b) & d);
                k = 0x5A827999;
            } else if (i < 40) {
                f = b ^ c ^ d;
                k = 0x6ED9EBA1;
            } else if (i < 60) {
                f = (b & c) | (b & d) | (c & d);
                k = 0x8F1BBCDC;
            } else {
                f = b ^ c ^ d;
                k = 0xCA62C1D6;
            }

            int t = leftrotate(a, 5) + f + e + k + w[i];
            e = d;
            d = c;
            c = leftrotate(b, 30);
            b = a;
            a = t;
        }

        h0 += a;
        h1 += b;
        h2 += c;
        h3 += d;
        h4 += e;
    }

    ByteBuffer buffer = ByteBuffer.allocate(20);
    buffer.putInt(h0);
    buffer.putInt(h1);
    buffer.putInt(h2);
    buffer.putInt(h3);
    buffer.putInt(h4);

    return buffer.array();
}

public static int leftrotate(int x, int c) {
    return (x << c) | (x >> (32 - c));
}

为了测试这一点,我尝试对一个 n 字节的随机数组进行散列,并将散列与通过得到的散列进行比较

MessageDigest.getInstance("SHA-1").digest(message)

我得到不同的哈希值。 我上面的实现有什么错误吗?错误可能来自其他地方吗?

【问题讨论】:

  • 我得到不同的哈希值。我在上面的实现中是否有任何错误? 如果您得到不同的哈希值,那么您的实现中一定有错误。 或者,以您比较哈希的方式。
  • @ElliottFrisch 这不是我比较哈希的方式。那么你知道差异来自哪里吗?我遵循了伪代码,我假设 Java 的实现也在遵循。那为什么这里会出错呢?
  • 嗯...您不会得到相同的结果,因为您完全忽略了消息输入,除了使用它的长度。此外,ByteArrayOutputStream 没有名为writeBytes() 的方法,即使其他所有内容都正确,您也没有显示leftrotate() 的代码,因此我们永远无法回答您的问题。请在提问时更加小心。
  • @JamesKPolk 抱歉,错误地复制和粘贴了我没有解决此问题的先前版本。已编辑。问题依然存在。考虑到writeBytes(),确实如此。见here。使用这个而不是write 可以不必处理无论如何都不会被抛出的IOException
  • 您的代码仍然无法编译。只需尝试编译您在此处发布的内容。

标签: java algorithm hash sha


【解决方案1】:

实施有两个问题。首先,我以字节而不是位为单位写入初始消息的大小。其次,leftrotate 方法在本应使用逻辑右移时使用了算术右移。

【讨论】:

    猜你喜欢
    • 2012-04-10
    • 2018-07-22
    • 2012-02-21
    • 2013-03-19
    • 2018-07-12
    • 2014-09-03
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    相关资源
    最近更新 更多