3

これらの (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コードの変更方法に関する回答をいただければ幸いです。

4

2 に答える 2

2

最初のハッシュは、サーバーとJavaで同じである必要があります。しかし、ループ内でダイジェストに追加されるのpassword{salt}はPHPコードですが{salt}、Javaコードのみです。

于 2013-02-08T12:52:35.097 に答える
0

怠惰な人にとっては、千の言葉よりも優れた 1 つの例 ;)。何が起こっているのか、やっと理解できました。メソッド update はダイジェストにバイトを追加するため、 $password.{$salt} を追加すると、 mda.update(password bytes) および 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;
    }
于 2014-03-19T21:04:22.470 に答える