1

I'm trying to validate sha256 hashes generated via Java Guava Hashing class using PHP, but can't seem to do it. I can't touch Java files, so fix has to be done on PHP side. Both PHP and Java use UTF-8 encoding. What am I missing?

Java:

package org.test.hash;

import com.google.common.hash.Hashing;

public class Main {
    public static void main(String[] args) throws Exception
    {
        String salt = "0123456789012345";
        String password = "password";

        System.out.println(
            Hashing.sha256().hashUnencodedChars(salt + "|" + password).toString()
        );
    }
}

Output:

818112d34d341ace8b9325fce61e676a125f733e25c28c9ed172c1f7d2c3aa6c

PHP:

$salt = "0123456789012345";
$password = "password";
print_r(hash("sha256", $salt . "|" . $password));

Output:

1f0a70940ae365e930c51e3de4c0a82f853f7663fc17acd36406982666685703
2
  • A quick look at the javadoc suggests that you should use hashString instead of hashUnencodedChars (which basically encodes the low byte and high byte of a Java char, that is as if UTF-16 is used to convert the string to bytes. Commented Aug 20, 2022 at 16:23
  • Can't touch the java part, but I'll try to convert my string to UTF-16 in PHP code once I get home. Commented Aug 20, 2022 at 16:36

2 Answers 2

1

It's a string encoding difference, check the following with Python:

>>> from hashlib import sha256
>>> string = "0123456789012345|password"

>>> sha256(string.encode("utf-8")).hexdigest()
'1f0a70940ae365e930c51e3de4c0a82f853f7663fc17acd36406982666685703'

>>> sha256(string.encode("utf-16-le")).hexdigest()
'818112d34d341ace8b9325fce61e676a125f733e25c28c9ed172c1f7d2c3aa6c'

>>> string.encode("utf-8").hex()
'303132333435363738393031323334357c70617373776f7264'

>>> string.encode("utf-16-le").hex()
'30003100320033003400350036003700380039003000310032003300340035007c00700061007300730077006f0072006400'
Sign up to request clarification or add additional context in comments.

1 Comment

That's a good hint, thanks! I didn't think that Java converts string to utf-16-le before hashing. I'll try to reproduce that in PHP once I get home and update this post
0

I figured it out thanks to suggestions from comments. It seems that bad implementation on Java end (using hashUnencodedChars instead of hashString) is causing conversion from source encoding (UTF-8 in my case) to UTF-16LE. Here's a way to fix that on PHP side:

$salt = "0123456789012345";
$password = "password";
$salted = mb_convert_encoding($salt . "|" . $password, "UTF-16LE", "UTF-8")
print_r(hash("sha256", $salted));

Output:

818112d34d341ace8b9325fce61e676a125f733e25c28c9ed172c1f7d2c3aa6c

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.