SHA1 in Java and PHP with different results

2020-06-23 06:03发布

问题:

I know there are several questions like this around, but I tried every single solution I found on stackoverflow and I still haven't got the expected result.

I'm trying to convert a string to sha1 in Java and PHP, but I'm getting different results. The string is generated randomly. I checked the string on both ends and they are the same (even trying a online comparison tool).

This is the same code I use in another app and it's working there, but not in this case.

One string I tried to hash with sha1 is: UgJaDVYEClRUD1cAAVUBVwRTB1MDAA9SBgcDBwNXAwNZBQdUAAACBA==

Java result: 72c9bbe7eed0efe5e82ea9568136d8f52347259e

PHP result: f720d73d18a7bb9cf36808af17ce40621ebfb405

Java Code

public static String sha1(String toHash)
{
    String hash = null;
    try
    {
        MessageDigest digest = MessageDigest.getInstance("SHA-1");
        byte[] bytes = toHash.getBytes("ASCII"); //I tried UTF-8, ISO-8859-1...
        digest.update(bytes, 0, bytes.length);
        bytes = digest.digest();
        StringBuilder sb = new StringBuilder();
        for(byte b : bytes)
        {
            sb.append(String.format("%02X", b));
        }
        hash = sb.toString();
    }
    catch(NoSuchAlgorithmException e)
    {
        e.printStackTrace();
    }
    catch(UnsupportedEncodingException e)
    {
        e.printStackTrace();
    }
    return hash.toLowerCase(Locale.ENGLISH);
}

PHP code

sha1("UgJaDVYEClRUD1cAAVUBVwRTB1MDAA9SBgcDBwNXAwNZBQdUAAACBA==");

Any help would be appreciated

Update

In Java & PHP I was doing the following:

Java

String toHash = "qwerty";
String hash = sha1(toHash); //Prints: b1b3773a05c0ed0176787a4f1574ff0075f7521e

toHash = Base64.encodeToString(toHash.getBytes("ASCII"), Base64.DEFAULT);
hash = sha1(toHash); //Prints: 88bfb2d77c3b42823bab820c1737f03c97d87c1b

PHP

$toHash = "qwerty";
sha1($toHash); //Prints: b1b3773a05c0ed0176787a4f1574ff0075f7521e

sha1(base64_encode($toHash)); //Prints: 278aa0e8dde2af58a4eed613467da219a35c5278

I guess that the Base64 encoding is doing something to the string that is different on PHP and Java, any thoughts on why?

UPDATE 2

I should have been more clearer, sorry for that, what I mean is:

The output of Java

sha1(Base64.encodeToString("qwerty".getBytes("ASCII"), Base64.DEFAULT));

is different that the output of PHP

sha1(base64_encode("qwerty"));

UPDATE 3

although both base64 encoded string are equal cXdlcnR5.

Basically:

- sha1("qwerty") == sha1("qwerty")
- Base64.encodeToString("qwerty".getBytes(), Base64.DEFAULT) == base64_encode("qwerty")
- sha1(Base64.encodeToString("qwerty".getBytes(), Base64.DEFAULT)) != sha1(base64_encode("qwerty"))

I already dropped the base64 encoding on the strings that I hash, but I still would like to know what I could have done to make it work.

回答1:

Edit

you are using the toHash variable twice in the encodeToString method making your second line of code redundant.

this code

String toHash = "qwerty";
String hash = sha1(toHash); //Prints: b1b3773a05c0ed0176787a4f1574ff0075f7521e

toHash = Base64.encodeToString(toHash.getBytes("ASCII"), Base64.DEFAULT);
hash = sha1(toHash); //Prints: 88bfb2d77c3b42823bab820c1737f03c97d87c1b

is equivalent to this code

String toHash = "qwerty";
toHash = Base64.encodeToString(toHash.getBytes("ASCII"), Base64.DEFAULT);
hash = sha1(toHash); //Prints: 88bfb2d77c3b42823bab820c1737f03c97d87c1b

So essentially in java you are

  • getting Base64 for "qwerty"
  • getting the sha1 on that result

While using PHP your are

  • getting the sha1 for "qwerty"
  • getting the Base64 on that result

I assume you've mistyped



回答2:

Over 3 years later I ran into the same issue, but this time I figured out the problem. Here is the solution to anyone that stumbles upon this question:

I was using:

sha1("qwerty") == sha1("qwerty")
Base64.encodeToString("qwerty".getBytes(), Base64.DEFAULT) == base64_encode("qwerty")
sha1(Base64.encodeToString("qwerty".getBytes(), Base64.DEFAULT)) != sha1(base64_encode("qwerty"))

The problem with this is the Base64.DEFAULT, the default behavior of Base64 wraps the string (adds \n to string). In order to get the same result as the PHP method you should use Base64.NO_WRAP:

sha1("qwerty") == sha1("qwerty")
Base64.encodeToString("qwerty".getBytes(), Base64.NO_WRAP) == base64_encode("qwerty")
sha1(Base64.encodeToString("qwerty".getBytes(), Base64.NO_WRAP)) == sha1(base64_encode("qwerty"))

After I made this change it started to work