3

I'm having some difficulty producing the same encrypted password using the PBKDF2 algorithm on both Java and PHP.

I'm using the following Java implementation to generate the hash with a random byte array which is 16 bytes in size. I'm then storing the hash and salt separately in a MySQL database, however when I go to do the same operation in PHP using the salt retrieved from the database, I get almost the exact same encryption except the hash has a leading 0 and I cannot for the life of me figure out why.

Java:

public String hashPassword(String password, byte[] salt){

 char[] passwordChars = password.toCharArray();

     PBEKeySpec spec = new PBEKeySpec(
         passwordChars,
         salt,
         ITERATIONS,
         KEY_LENGTH
     );
     SecretKeyFactory key = null;
    try {
        key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    byte[] hashedPassword = null;

    try {
        hashedPassword = key.generateSecret(spec).getEncoded();
    } catch (InvalidKeySpecException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
     return String.format("%x", new BigInteger(hashedPassword));

}

I found the above code at https://adambard.com/blog/3-wrong-ways-to-store-a-password/

PHP:

$query = $database->query('SELECT * FROM USERS');

$password = 'hello';
$iterations = 1000;

foreach($query as $user){
    $hash = hash_pbkdf2("sha1", $password, $user['salt'], $iterations, 40, false);

}
echo $hash;

Note: There is only one user stored in the database, I know the above code isn't great, I created it quickly for testing purposes.

For both implementations I'm using an iteration count of 1000, a key length of 160 in Java and a key length of 40 in PHP (to compensate for setting raw-output to false)

Java Output - 971f0dddc1bc2e899f2bca178f16ea79bfbbb13
PHP Output - 0971f0dddc1bc2e899f2bca178f16ea79bfbbb13

Any help is much appreciated, thank you.

Astronought
  • 405
  • 5
  • 24
  • Possible duplicate of [How to convert a byte array to a hex string in Java?](http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to-a-hex-string-in-java) – Artjom B. Mar 16 '16 at 07:59
  • @artjom B. It was the conversion from the byte array to hex string that was causing the problem, I used a String Builder to do the conversion process instead and it worked as intended. – Astronought Mar 20 '16 at 08:58

1 Answers1

6

It is the BigInteger that is killing the leading 0.

Hashes are not integers, they are an array of 8-bit bytes. Do not try to convert to a BigInteger.

Either use it as a byte[] or encode as a hexadecimal or Base64 string. To match PHP hexadecimal encode hashedPassword.

PHP is returning a hexadecimal string encoded hash because raw_output is set to FALSE.

zaph
  • 111,848
  • 21
  • 189
  • 228
  • 1
    Thank you, it the BigInteger conversion was the culprit, I used a String Builder to create the hex string instead and it worked correctly. – Astronought Mar 20 '16 at 08:57