【问题标题】:Java SHA512 digest output differs from PHP scriptJava SHA512 摘要输出与 PHP 脚本不同
【发布时间】:2014-03-20 05:04:22
【问题描述】:

有人能弄清楚为什么这些(php 和 java)sn-ps 代码的输出不会为相同的输入返回相同的 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 代码的任何答案。

【问题讨论】:

标签: java php sha512


【解决方案1】:

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

【讨论】:

  • 是的,你是对的。我根据您的建议更改了代码,但没有生成相同的输出。但是,第一个哈希应该是相同的。
  • @Joscandreu 第一个哈希已经不同还是相同?
  • 第一个哈希值不同。我的猜测是必须对字符串的二进制解释做一些事情,但更改字符集不会影响 java 输出。我在 java 中强制使用 ISO-8859-1,因为这似乎是我安装中 php 的默认字符集。
  • @Joscandreu 是的,这可能是编码问题(我没有看到其他原因)。但根据这个问题stackoverflow.com/questions/4680661/…,它似乎适用于 ISO-8859-1 或 UTF-8(对于 ASCII 输入,两种编码一致)。
  • 读完后:daniweb.com/web-development/php/threads/319067/… 我怀疑 encodebase64 函数,可能有问题。 php 中的 encode 函数接受一个字符串作为输入,它实际上是原始二进制文件。所以可能是 php 正在管理一些静默的内部转换。如果可以的话,我会深入研究。
【解决方案2】:

对于懒惰的人来说,一个例子胜过一千个单词;)。我终于明白发生了什么。方法 update 将字节附加到摘要中,因此当您附加 $password.{$salt} 时,与执行 mda.update(password bytes) 和 mda.digest("{$salt}" bytes 相同。我会回答因为我正在疯狂地寻找它为什么不起作用,而这一切都在这个答案中。

谢谢各位。 这是适用于 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;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-27
    • 2019-01-21
    • 2012-11-16
    • 1970-01-01
    • 2015-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多