アプレットとしてパッケージ化される Java でゲームを開発しており、ネットワークの側面に取り組んでいます。SSL の使用を必要とせずに、要求の頻度とセキュリティのニーズに合わせて機能するセッション フローを設計しました。データ送信プロセスは、Facebook が OAuth プロセスで使用される signed_token に署名する方法に大まかに基づいています。簡略化されたコンテキストは次のとおりです。
- 私の php/java 実装は、hash_hmac/javax.crypto.Mac を使用して、共有された秘密の一意のトークンとさまざまな JSON ペイロードに基づいて、ペイロードに署名するためのあいまいな署名を生成します
- 両方の出力は、より大きなエンコード/デコード圧縮スキームの一部であるため、正確に一致する必要があります
- この署名はペイロードとともに URL を介して渡され、ペイロードの有効性と整合性を検証するために使用されます。
お察しのとおり、それらが一致しない場合は、データのパケットがドロップされ、無効なデータが送信されたためエラーが発生しました。私の問題は、結果の 16 進エンコーディングが完全に一致する一方で、生のバイナリが一致しないように見えることです。以下は、私が設定した抽出された php および Java テスト ケースです。
注: PHP と Java が PHP 連想配列 / Java ハッシュマップの JSON 構造を生成する方法が異なるため、両方のフィールドがプラットフォーム間で一貫するように、文字列ペイロードの代わりにシークレットの値を使用しています。
Php:
$secret = "922ec205d8e4d0ea06079d60a5336fffd9cf0aea";
$json = $secret; //json_encode($test_array);
$hmac_a = hash_hmac('sha256',$json,$secret);
$hmac_b = hash_hmac('sha256',$json,$secret,$raw=true);
echo(htmlentities($hmac_a)."<br/>\n");
echo(htmlentities($hmac_b)."<br/>\n");
ブラウザ内出力:
ff21a9e468ac49863e5e992324ac8bc92f239a08100b0f329b087be16f5ad382
ÿ!©äh¬I†>^™#$¬‹É/#š2›{áoZÓ‚</p>
ジャワ:
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(Charset.forName("UTF-8").encode(this.secret).array(), "HmacSHA256");
hmac.init(secret_key);
byte[] digest = hmac.doFinal(this.secret.getBytes("UTF-8"));
System.out.println(hexify(digest));
System.out.println(new String(digest,"UTF-8"));
コンソール出力:
ff21a9e468ac49863e5e992324ac8bc92f239a08100b0f329b087be16f5ad382
�!��h�I�>^�#$���/#� 2� {�oZӂ
php にコピーしてエコーするように指示すると、2 番目の文字列は次のようになります。
:�!��h�I�>^�#$���/#���2{�oZӂ</p>
16 進数は同じですが、2 進数は異なりますが、同じソースから表示すると同じ末尾 ( oZÓ‚ ) が含まれていることに注意してください。実際には、より一般的な文字 (!hI>^#$/#2{oZÓ,) がすべて順番に含まれています。コンソール出力を php にコピーしてから、バイナリ文字列、通常の文字列、utf8_encode されたバイナリ/通常の文字列、および utf8_encode された $hmac_b として表示してみました。生のバージョンを一致させるものはないようです。
PHP の hmac で mb_detect_encoding を実行したところ、UTF-8 と表示されました。また、javax.crypto.Mac のすべてを UTF-8 に設定し、UTF-8 として表示しましたが、ダイスはありません。Java の UTF-8 が php の UTF-8 と変わらないことは知っています。これは、標準の文字セットを持つという概念に反するからです。何が起きてる?
注: URL エンコーディングには 16 進数バージョンを使用することを好み、使用できるようになりましたが、このナンセンスな文字セットで何が起こっているのか、およびおそらくそれを修正する方法を知りたいと思っています。