javaarrayscomparemessage-digest

Java byte array comparison of MessageDigest SHA1 result and original hash value?


I would like to compare two byte arrays. One is calculated from plaintext with MessageDigest SHA1, the other is the hex itself in byte array, without calculation.

MessageDigest returns 20 byte long result, String.getBytes() returns 40 byte long array. bytesToHex() function is the same that was provided in this answer, used only for printing.

The question:

How can I convert a string to byte array (and then compare with one calculated with MessageDigest) without the additional overhead? String comparison with bytesToHex() and .toUppercase() is working, but not an option, since speed is cruital in the application.

The code:

 MessageDigest md;

    try {
        md = MessageDigest.getInstance("SHA-1");

        byte[] toEncode = "test".getBytes();
        byte[] encoded = md.digest(toEncode);

        System.out.println("String to encode:\t\t" + new String(toEncode));
        System.out.println("Encoded in hex:\t\t\t" + bytesToHex(encoded));
        System.out.println("Encoded length:\t\t\t" + encoded.length);


        byte[] hash = new String("a94a8fe5ccb19ba61c4c0873d391e987982fbbd3").getBytes(); // "test" representation in SHA1

        System.out.println("\nHash to compare with:\t\t" + new String(hash));
        System.out.println("Hash length:\t\t\t" + hash.length);
        System.out.println("Two byte array equals:\t\t" + Arrays.equals(hash, encoded));
        System.out.println("Two equals in string:\t\t" + new String(hash).equals(bytesToHex(encoded).toLowerCase()));

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

The result:

String to encode:           test
Encoded in hex:             A94A8FE5CCB19BA61C4C0873D391E987982FBBD3
Encoded length:             20

Hash to compare with:       a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
Hash length:                40
Two byte array equals:      false
Two equals in string:       true

Solution

  • You're not decoding your hex representation to bytes. If you would, for example using the solution from this answer, the two arrays would match:

    try {
        byte[] encoded = MessageDigest.getInstance("SHA-1").digest("test".getBytes());
        byte[] hash = DatatypeConverter.parseHexBinary("a94a8fe5ccb19ba61c4c0873d391e987982fbbd3");
    
        System.out.println("Two byte array equals:\t\t" + Arrays.equals(hash, encoded));
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }