Java's MessageDigest SHA1-algorithm returns di

2019-01-14 17:33发布

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?..

标签: java php sha1
4条回答
霸刀☆藐视天下
2楼-- · 2019-01-14 17:49

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);.

查看更多
做自己的国王
3楼-- · 2019-01-14 17:52

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楼-- · 2019-01-14 18:08

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

查看更多
闹够了就滚
5楼-- · 2019-01-14 18:12

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.

查看更多
登录 后发表回答