4

ゲームの保存ファイルを暗号化して保存するために使用するC#の基本的な暗号化機能があります。これは、ゲームのWebサイトにユーザーのユーザー名とパスワードを使用します。最近、ユーザーがパスワードを変更すると、古いパスワードで暗号化されているため、保存にアクセスできなくなることに気付きました。そのため、パスワードを更新するときに保存を「再変換」するPHP関数を構築しようとしています。残念ながら、C# はバイト配列を使用してハッシュを実行し、PHP は文字列を使用するという問題があり、この 2 つを調整する方法がわかりません。一般的なプロセスは次のとおりです。

  • ユーザー名のハッシュ (バイト配列に)
  • ハッシュ パスワード (バイト配列に)
  • ユーザー名とパスワードのハッシュを連結します (2 倍の長さのバイト配列に)
  • キーを取得するためのハッシュ結果 (これは 256 ビット長に戻ります)
  • 暗号化されたファイルを取得するためのキーを使用してバイト単位でファイルを xor する

PHPでこれを達成する方法がわかりません。私はもともと使用しようとしてunpack('C*', hash("sha256", $thing_to_be_hashed, false))いましたが、これは正しいバイト配列を生成していないようです。それから私はこれを試しました:

$new_key = hash("sha256", hash("sha256", $username, false) . hash("sha256", $newpass, false), false);
$old_key = hash("sha256", hash("sha256", $username, false) . hash("sha256", $oldpass, false), false);

$conversion_key = array();
for($i = 0; $i < strlen($new_key); ++$i) {
    $conversion_key[] = $old_key[$i] ^ $new_key[$i]; 
    // this part with the array is a bit wonky, I know, but it didn't seem like
    // it would have worked anyway since I was xor'ing things like 'f' and '3'
    // instead of bytes like '23' and '57'.
}
$file_contents = file_get_contents("savefile.sav");
for($i = 0; $i < strlen($file_contents); ++$i) {
    $file_contents[$i] = $file_contents[$i] ^ $conversion_key[$i % count($conversion_key)]; // I read somewhere I can access $file_contents like this to get bytes
}

残念ながら、どちらの方法もどの段階でも機能しません (以前の unpack メソッドは、ハッシュの最初の段階でさえ正しいバイト配列を生成しませんでした。また、2 番目の段階で正しく文字列に戻していたと確信しています)。私が得ることができる助けをいただければ幸いです。ありがとう!

編集:unpack()文字通り文字列をデコードしているため、正しいバイト配列が得られないことがわかりました。私の主な質問は、まず「によって返された hexitshash()をバイト配列に変換するにはどうすればよいですか?」ということだと思います。次に、「これらのバイト配列をハッシュするにはどうすればよいですか?」(当然のことながら、「バイト配列を変換して hexits の文字列に戻し、それらをハッシュするだけで十分ですか?」)

4

1 に答える 1

2

文字列がエンコードされた Unicode シーケンスである .NET とは対照的に、PHP の文字列はダム シーケンスのバイトです。したがって、PHP 側では、必要なことはすべて文字列で行うことができ、配列を使用する必要はまったくありません。つまり、配列は必要unpackありません。

主に対処すべきことは、PHP ハッシュ関数がデフォルトでストレート バイナリ出力ではなく 16 進エンコードを返すことです。一方から他方への変換は非常に簡単です: usehex2binを使用しますが、3 番目の (オプションの) 引数を として指定する方がはるかに簡単ですtrue

したがって、必要なハッシュを次のように取得できます。

// for convenience
function sha256($data) {
    return hash("sha256", $data, true);
}

$new_key = sha256(sha256($username).sha256($newpass));
$old_key = sha256(sha256($username).sha256($oldpass));

この関数は、2 つのキーを XOR します。

function str_xor($str1, $str2) {
    if (strlen($str1) != strlen($str2)) {
        return false;
    }

    $len = strlen($str1);
    for($i=0; $i < $len; $i++) {
        $str1[$i] = $str1[$i] ^ $str2[$i];
    }

    return $str1;
}

したがって、既存のループを使用して、保存されたデータをあるキーから別のキーに「再暗号化」できます。

于 2013-10-08T08:47:14.750 に答える