2

以前、C++ CryptoPP Rijndael_128 CBC コードを MCrypt PHP に移植することができましたが、現在、CFB モードで問題が発生しています。C++ と PHP の結果は一致しません (最初のバイトは一致しますが、これは偶然かもしれませんが、他のすべては一致しません)。いくつかの診断では、PHP の mcrypt がキーの長さを正しく設定していないように見えますか?

これがC++です(簡単にするために診断と雑用は削除されています):

CFB_Mode<AES>::Encryption encryptor(g_encrypt_key, AES::DEFAULT_KEYLENGTH, g_encrypt_iv);

StringSource ss( sInput.c_str(), true, 
        new StreamTransformationFilter( encryptor, 
            new HexEncoder( new StringSink( sEncryptedOut ) )
        ));

そして、ここにPHPがあります:

$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CFB, '')
mcrypt_generic_init($cipher, $g_encrypt_key, $g_encrypt_iv);

$sEncryptedOutput = mcrypt_generic( $cipher, $sInput);
mcrypt_generic_deinit($cipher);
mcrypt_module_close($cipher);

g_encrypt_keyg_encrypt_ivはどちらも 16 バイトの長さで、バイトは C++ と PHP のバージョンで一致します。PHP バージョンの場合、バイトから構築されたバイナリ文字列です (はい、これらが同一であることを確認しました)。

$cipherのブロック サイズ、キー サイズなどを確認するために、PHP バージョンへの呼び出しを追加しました。ブロック サイズと iv サイズは両方とも 16 です。サポートされている鍵のサイズは、16、24、および 32 と報告されており、すべて予想どおりです。

私が問題だと思うのは、キーサイズが 32 バイトと報告されていることです。mcrypt docs を見ると、キーサイズを設定する唯一の方法は、必要なサイズのキーを提供することです。しかし、私は 16 バイトの鍵を渡しています! では、なぜ 32 バイトのキーの存在を報告しているのでしょうか? CFB モードで 32 バイトのキーを使用する必要がある場合、CryptoPP はなぜそれを問題なく受け入れるのですか? 解決策は何ですか?提供された 16 バイトの鍵を PHP に強制的に使用させることはできますか? または、CryptoPP で MCrypt とは異なる設定にデフォルト設定されている、欠落しているパラメーターがありますか?

結果の暗号化データの長さを最小限に抑えたいので、CFB モードを使用しています。パディングによって導入される数バイトは、このアプリケーションでは重要です。

C ++で暗号化/復号化できる必要がありますが、PHPでのみ暗号化できます。AES は間違いなく、私のアプリケーションにとってやり過ぎです。データ内の個々のバイトの機能が明確にならないように、最低限必要なのは「バイトの適切なスクランブル」です。

4

3 に答える 3

4

しばらく経ちましたが、数年前にCFBを使用してmcryptとopenSSLで同様の問題が発生しました。最終的に、mcrypt が CFB モードの openssl とは異なるデフォルトのフィードバック チェーン サイズを使用していることを発見しました。つまり、CFB の openSSL AES128 は 128 ビットのブロック サイズとフィードバック サイズを使用し、mcrypt は 128 ビットのブロック サイズと 8 ビットのフィードバック サイズを使用したと思います。これを確認する方法はありません。それは当時、いくつかの古いフォーラムの投稿を読んだことに基づく憶測に過ぎませんでした。その理論が真実であるかどうかにかかわらず、この特定の問題を抱えたのは私だけではなく、最初でもありませんでした。

私にとっての解決策は、自分自身として nOFB を使用することでした。PHP mcrypt ライブラリ リファレンス によるとMCRYPT_MODE_NOFB、フィードバック チェーンはアルゴリズムのブロック サイズと等しくなります。この場合、AES128 (Rijndael) の 128 ビット ブロック/フィードバックであり、mcrypt モジュールのマンページで nOFB について述べられている内容と一致します。nOFBフィードバックはブロックサイズに同期していることがわかったので、これは良いことです。したがって、nOFB の mcrypt と OpenSSL の両方が、AES128 の 128 ビット キー/iv/ブロック/フィードバック サイズになり、すべてが正常に機能しました。

PHP が 256 ビットのキーサイズ (32 バイト) を報告している限り、現在の暗号アルゴリズムのキー サイズを返す関数は実際には最大のキー サイズを返しますが、これはドキュメントには明確に記載されていません。私がこれを知っているのは、現在さまざまなプロジェクトで常に使用している私の小さなクラスが、openSSL や CBC または nOFB の他の AES ライブラリで完全に正常に動作するためです。これは、mcrypt が 128 ビット (16 文字) のキーに追加の 128 ビットの null 文字列などを埋め込んでいる場合には当てはまりません。また、技術的には正しくありません。

本当に良い答えではありませんが、数年前に非常にアマチュアな暗号への進出に基づいて得た最高の答えです。

于 2010-10-29T16:42:57.200 に答える
2

phpseclib をチェックしてください:

http://phpseclib.sourceforge.net/

キーサイズとブロックサイズを自由に設定できます。

例えば。$aes->setKeyLength(128) または $aes->setKeyLength(256);

于 2010-11-04T14:02:24.743 に答える
1

私はこの問題を抱えていました-いくつかのポイント。デフォルトでは、PHP Rijndael モードはフィードバック ループを 8 ビットに設定します。これには、AES が IV/Key と同じ長さである必要があります。

これを行うには、「cfb」または MCRYPT_MODE_CFB の代わりにモード「ncfb」を使用します。

aes_cfb_128 互換の PHP の作成に関する完全な詳細は、Security Stackexchange question: aes cfb 128 decryption /encryption problem between Erlang and PHP にあります。それの短いは(Tom Leekから)です:

... CFB と OFB (互いに異なり、同じ意味で使用することはできません) の両方について、さまざまな暗号化ライブラリで明確に文書化されているとは限らない「フィードバックの長さ」について心配する必要があります。相互運用するには、暗号化と復号化の両方で同じフィードバック長を使用する必要があります。

于 2013-02-03T10:07:47.117 に答える