Frage

Can someone figure out why the output of these (php and java) snippets of code don't return the same SHA512 for the same input?

$password = 'whateverpassword';
$salt = 'ieerskzcjy20ec8wkgsk4cc8kuwgs8g';
$salted = $password.'{'.$salt.'}';
$digest = hash('sha512', $salted, true);
echo "digest: ".base64_encode($digest);
for ($i = 1; $i < 5000; $i++) {
  $digest = hash('sha512', $digest.$salted, true);
}
$encoded_pass = base64_encode($digest);
echo $encoded_pass;

This is the code on the android application:

public String processSHA512(String pw, String salt, int rounds)
{
    try {
        md = MessageDigest.getInstance("SHA-512");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        throw new RuntimeException("No Such Algorithm");
    }

    String result = hashPw(pw, salt, rounds);
    System.out.println(result);
    return result;
}

private static String hashPw(String pw, String salt, int rounds) {
    byte[] bSalt;
    byte[] bPw;

    String appendedSalt = new StringBuilder().append('{').append(salt).append('}').toString();

    try {
        bSalt = appendedSalt.getBytes("ISO-8859-1");
        bPw = pw.getBytes("ISO-8859-1");
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException("Unsupported Encoding", e);
    }

    byte[] digest = run(bPw, bSalt);
    Log.d(LCAT, "first hash: " + Base64.encodeBytes(digest));
    for (int i = 1; i < rounds; i++) {
        digest = run(digest, bSalt);
    }

    return Base64.encodeBytes(digest);
}

private static byte[] run(byte[] input, byte[] salt) {
    md.update(input);
    return md.digest(salt);
}

The library for base64 encoding is this: base64lib

This java code is actually some modified code I found around another question in StackOverflow. Although the Android code is running fine it doesn't match with the output from the php script. It doesn't even match the first hash!

Note 1: On php hash('sha512',$input, $raw_output) returns raw binary output

Note 2: On java I tried to change the charset (UTF-8, ASCII) but it also didn't work.

Note 3: The code from the server can not be changed, so I would appreciate any answer regarding how to change my android code.

War es hilfreich?

Lösung

The first hash should be the same on the server and in Java. But then in the loop what gets appended to the digest is password{salt} in the PHP code, but only {salt} in the Java code.

Andere Tipps

For the lazy ones, one example better than a thousand words ;). I finally understood what was happening. The method update appends bytes to the digest, so when you append $password.{$salt} is the same as doing mda.update(password bytes) and the mda.digest("{$salt}" bytes. I do that answer because I was going crazy finding why it was not working and it was all in this answer.

Thanks guys. This is the example that works in a Java Server:

public static String hashPassword(String password, String salt) throws Exception {
        String result = password;
        String appendedSalt = new StringBuilder().append('{').append(salt).append('}').toString();
        String appendedSalt2 = new StringBuilder().append(password).append('{').append(salt).append('}').toString();

        if(password != null) {
            //Security.addProvider(new BouncyCastleProvider());

            MessageDigest mda = MessageDigest.getInstance("SHA-512");
            byte[] pwdBytes = password.getBytes("UTF-8");
            byte[] saltBytes = appendedSalt.getBytes("UTF-8");
            byte[] saltBytes2 = appendedSalt2.getBytes("UTF-8");
            byte[] digesta = encode(mda, pwdBytes, saltBytes);

            //result = new String(digesta);
           System.out.println("first hash: " + new String(Base64.encode(digesta),"UTF-8"));
                for (int i = 1; i < ROUNDS; i++) {

                    digesta = encode(mda, digesta, saltBytes2);
                }
                System.out.println("last hash: " + new String(Base64.encode(digesta),"UTF-8"));

                result = new String(Base64.encode(digesta));
        }
        return result;
    }

private static byte[] encode(MessageDigest mda, byte[] pwdBytes,
            byte[] saltBytes) {
        mda.update(pwdBytes);
        byte [] digesta = mda.digest(saltBytes);
        return digesta;
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top