Java SHA512摘要输出与PHP脚本不同

时间:2013-02-08 12:42:14

标签: java php sha512

有人可以弄清楚为什么这些(php和java)代码片段的输出不会为同一输入返回相同的SHA512吗?

$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;

这是android应用程序上的代码:

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);
}

base64编码的库是:base64lib

这个java代码实际上是我在StackOverflow中的另一个问题中找到的一些修改过的代码。 虽然Android代码运行正常,但它与php脚本的输出不匹配。它甚至不匹配第一个哈希!

注1:在php hash('sha512',$input, $raw_output)上返回原始二进制输出

注意2:在java上我试图更改字符集(UTF-8,ASCII),但它也没有用。

注3:服务器的代码无法更改,所以我很感激有关如何更改我的Android代码的任何答案。

2 个答案:

答案 0 :(得分:2)

第一个哈希在服务器和Java中应该是相同的。但是在循环中,附加到摘要的内容是PHP代码中的password{salt},但Java代码中只有{salt}

答案 1 :(得分:0)

对于懒惰的人来说,一个例子胜过千言万语;)。我终于明白了发生了什么。方法更新将字节附加到摘要,因此当您附加$ password时,{$ salt}与执行mda.update(密码字节)和mda.digest(“{$ salt}”字节相同。我做的回答因为我疯狂地发现它为什么不起作用而且这一切都在这个答案中。

谢谢你们。 这是在Java服务器中运行的示例:

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;
    }