2

My application uses salted hash in Java. First a random salt is generated. Then this salt is prefixed to the SHA-512 of the input password and the combined string is SHA-512 again.It is implemented as follows:-

String password = testpwd.getText().toString();
SecureRandom rand = new SecureRandom();
byte[] randbytes = new byte[16];
rand.nextBytes(randbytes);
String encodedSalt = Base64.encodeToString(randbytes, Base64.DEFAULT);

MessageDigest digest = MessageDigest.getInstance("SHA-512");
digest.reset();
digest.update(password.getBytes("utf-8"));
byte[] pwdhash = digest.digest();
String encodedPwd = Base64.encodeToString(pwdhash, Base64.DEFAULT);

String saltedPassword = encodedSalt+encodedPwd ;

digest.reset();
digest.update(saltedPassword.getBytes("utf-8"));
byte[] pwdhash1 = digest.digest();
String encodedPwdSalt = Base64.encodeToString(pwdhash1, Base64.DEFAULT);

Then the strings encodedSalt and encodedPwdSalt are sent to web server for authentication. The PHP encryption is as follows:

$postpassword = $_POST['password'];
$postsalt = $_POST['salt'];
$salt = base64_decode($postsalt);
$password = base64_decode('postpassword');

The SHA-512 hashs of the password "Ditglt@785" is stored in the database. It is retrieved and processed as follows:-

$getsaltpwd = $salt.$dbpassword ;
$dbsaltpwd = hash('sha512', $getsaltpwd);
if($dbpassword == $postpassword) {}

The condition always fails and so does the authentication. What should I do ?

9
  • 2
    When comparing to $postpassword, shouldn't you be using $dbsaltpwd instead of $dbpassword? Commented Jun 21, 2018 at 9:13
  • What is base64_decode('postpassword'); doing in your first PHP block? (Why decode a constant?) Commented Jun 21, 2018 at 9:24
  • You shouldn't be base64-decoding your salt in PHP either because you're hashing a base64- encoded salt in Java. Commented Jun 21, 2018 at 9:28
  • @John You should be more specific about what process of encode/concat/hash steps you want. There's clearly a mismatch between Java and PHP, and we're left guessing which process is the intended one. Commented Jun 21, 2018 at 9:29
  • @RobbyCornelissen you are right about "using $dbsaltpwd instead of $dbpassword". But it was a typo while posting the question here. In code it is as you mentioned. Commented Jun 21, 2018 at 9:29

3 Answers 3

2

The PHP version hashes raw bytes while the Java version hashes base64-encoded strings.

Here's a Java version that matches what your PHP code does:

digest.reset();
digest.update(randbytes);
digest.update(pwdhash);
byte[] pwdhash1 = digest.digest();
String encodedPwdSalt = Base64.encodeToString(pwdhash1, Base64.DEFAULT);

Having said that, it would be more secure to store the salt and the salted password in the database, and to use at least some key derivation function (iterate the hash function many times) in order to counteract any potential brute-forcing of the stored hashes.

Sign up to request clarification or add additional context in comments.

3 Comments

Ohh! I used the line String saltedPassword = encodedSalt+encodedPwd ; to achieve this
The Java version is hashing saltedPassword which is encode(salt) + encode(hash(password)), roughly speaking (that isn't Java syntax). Perhaps $salt shouldn't be passed through base64_decode, since they seem to want to hash the encoded salt.
saltedPassword = encodedSalt+encodedPwd; is incorrect.
1

Since your Java code correctly follows what you describe in your specification, the problem lies on the PHP side.

With your Java code as-is, it generates the following values when encoding the string "password" with a random salt:

encodedSalt: ww0g+f77ygKD7Iww1GTYtg==
encodedPwd: sQnzu7wkTrgkQZF+0G1hi5AI3Qmzvv0bXgc5THBqi7mAsdd4Xll27ASbRt9fEyavWi6m0QP9B8lThf+rDKy8hg==
encodedPwdSalt: YAGG7GcpUxIZzBnHuaezPf5BWFhFalBPgvue/0wFoRLu+JsKslG8wPCv6dPubIBk1aFIJ8spK8S17347aDBAYA==

In PHP, what you would need to do is the following:

$postpassword = 'YAGG7GcpUxIZzBnHuaezPf5BWFhFalBPgvue/0wFoRLu+JsKslG8wPCv6dPubIBk1aFIJ8spK8S17347aDBAYA==';
$postsalt = 'ww0g+f77ygKD7Iww1GTYtg==';
$dbpassword = 'sQnzu7wkTrgkQZF+0G1hi5AI3Qmzvv0bXgc5THBqi7mAsdd4Xll27ASbRt9fEyavWi6m0QP9B8lThf+rDKy8hg==';

if($postpassword == base64_encode(hash('sha512', $postsalt.$dbpassword, true))) {
    echo 'OK';
}  

2 Comments

you have said my Java code as-is, but according to rustyx, saltedPassword = encodedSalt+encodedPwd part is incorrect.
There's nothing incorrect about it. You make a choice to concatenate two base64-encoded strings and hash that, while he chooses to concatenate two byte arrays and hash that. The results will obviously be different, but one is not more correct than the other.
0

Check if the padding matches. I experienced the same problem with encryption where the padding in PHP was different from the padding in JAVA. Luckily I was able to set the padding in JAVA to the one that PHP uses. But I had to look at PHP source code to figure out how. As far as I remember it was not possible to change the padding in PHP back then.

Here is the question I posted back then: decrypting php encrypted data on android

[...] you need to set Base64.decode with the parameter Base64.NO_WRAPas PHP will just put out the base64 delimited by \0.

2 Comments

SHA-512? Padding?
@RobbyCornelissen I looked at my question from back then again and the problem with Base64 was delimiting character.

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.