Implementation of SHA-1 yields different hashes than the `java.security` implementation

-2

I am trying to implement the SHA-1 algorithm in Java 11, and while testing the hashing algorithm I get different hashes than when hashing with the java.security implementation of SHA-1.

The pseudocode I attempted to follow can be found 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));
}

To test this out, I attempt to hash a random array of n bytes, and compare the hash to the one obtained by

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

I get different hashes. Is there any mistake in my implementation above? Could the error come from somewhere else?

java
algorithm
hash
sha
asked on Stack Overflow May 18, 2019 by oranji • edited Apr 2, 2020 by oranji

1 Answer

0

There were two problems with the implementation. First, I was writing the size of the initial message in bytes and not in bits. Second, the leftrotate method was using the arithmetic right shift when it should have been using the logical right shift.

answered on Stack Overflow May 18, 2019 by oranji

User contributions licensed under CC BY-SA 3.0