Java's MessageDigest SHA1-algorithm returns di

2019-01-14 17:19发布

问题:

I have a SQL table with usernames and passwords. The passwords are encoded using MessageDigest's digest() method. If I encode a password - let's say "abcdef12" - with MessageDigest's digest() method and then convert it to hexadecimal values, the String is different than if I do the same using PHP's SHA1-method. I'd expect these values to be exactly the same though.

Code that is used to encode the passwords:

MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] passbyte;
passbyte = "abcdef12".getBytes("UTF-8");
passbyte = md.digest(passbyte);

The conversion of the String to hexadecimal is done using this method:

public static String convertStringToHex(String str) {

    char[] chars = str.toCharArray();

    StringBuffer hex = new StringBuffer();
    for (int i = 0; i < chars.length; i++) {
        hex.append(Integer.toHexString((int) chars[i]));
    }

    return hex.toString();
}

Password: abcdef12

Here's the password as returned by a lot of SHA1-hash online generators and PHP SHA1()-function: d253e3bd69ce1e7ce6074345fd5faa1a3c2e89ef

Here's the password as encoded by MessageDigest: d253e3bd69ce1e7ce674345fd5faa1a3c2e2030ef

Am I forgetting something?

Igor.

Edit: I've found someone with a similar problem: C# SHA-1 vs. PHP SHA-1...Different Results? . The solution was to change encodings.. but I can't change encodings on the server-side since the passwords in that SQL-table are not created by my application. I use client-side SHA1-encoding using a JavaScript SHA1-class (more precisely: a Google Web Toolkit-class). It works and encodes the string as expected, but apparently using ASCII characters?..

回答1:

It has nothing to do with the encodings. The output would be entirely different.

For starters, your function convertStringToHex() doesn't output leading zeros, that is, 07 becomes just 7.

The rest (changing 89 to 2030) is also likely to have something to do with that function. Try looking at the value of passbyte after passbyte = md.digest(passbyte);.



回答2:

I have the same digest as PHP with my Java SHA-1 hashing function:

public static String computeSha1OfString(final String message) 
    throws UnsupportedOperationException, NullPointerException {
        try {
               return computeSha1OfByteArray(message.getBytes(("UTF-8")));
        } catch (UnsupportedEncodingException ex) {
                throw new UnsupportedOperationException(ex);
        }
}

private static String computeSha1OfByteArray(final byte[] message)
    throws UnsupportedOperationException {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(message);
            byte[] res = md.digest();
            return toHexString(res);
        } catch (NoSuchAlgorithmException ex) {
            throw new UnsupportedOperationException(ex);
        }
}

I've added to my unit tests:

String sha1Hash = StringHelper.computeSha1OfString("abcdef12");
assertEquals("d253e3bd69ce1e7ce6074345fd5faa1a3c2e89ef", sha1Hash);

Full source code for the class is on github.



回答3:

Try this - it is working for me:

MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(original.getBytes());
byte[] digest = md.digest();
StringBuffer sb = new StringBuffer();
for (byte b : digest) {
    sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();

Regards, Konki



回答4:

Or try this:

MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(clearPassword.getBytes("UTF-8"));
return new BigInteger(1 ,md.digest()).toString(16));

Cheers Roy



标签: java php sha1