0

私は現時点でActionScript 3を初めて使用し、処理のためにサーバーに送信する前に、as3cryptoライブラリを使用してblowfishアルゴリズムで一部のデータを暗号化しようとしています。https を使用できることはわかっていますが、ほとんどのブラウザーは引き続き送信データを表示するため、ユーザーは簡単にリクエストを偽装できます。そのため、ユーザーにページ要求を表示させたいのですが、復号化せずにデータを読み取ることはできません。

残念ながら、as3crypto ライブラリの decumentation は、コード内のコメント (あまり役に立ちません) を除けば、ほとんど存在しません。as3crypto フグ暗号化を「実装」するためにいくつかの静的関数を使用してフラッシュ側をセットアップしましたが、フラッシュ内でのみ暗号化/復号化に問題なく動作します。問題は、mcrypt ライブラリを使用して PHP でキーを使用して復号化しようとすると発生します。私が得た出力は元のコードではなく、なぜ役に立たないのかを理解するために数日を費やしました。

以下、コードと解説です。この例では、使用されるキーは「mykey」(引用符なし) で、エンコードされたデータは「Hello World」(引用符なし) です。

フラッシュ コード (as3crypto フグ ヘルパー):

    package lib.ef.crypto
{
    import com.hurlant.util.Base64;
    import com.hurlant.crypto.Crypto;
    import flash.utils.ByteArray;
    import com.hurlant.crypto.symmetric.IPad;
    import com.hurlant.crypto.symmetric.ICipher;
    import com.hurlant.crypto.symmetric.NullPad;

    public class Blowfish
    {
        /**
        * Encrypts a string.
        * @param text  The text string to encrypt.
        * @param key  A cipher key to encrypt the text with.
        */
        static public function encrypt($text:String, $key:String=""):String
        {
            var cryptKey:ByteArray = new ByteArray();
            cryptKey.writeUTF( $key );

            var iPad:IPad = new NullPad();

            var crypt:ICipher = Crypto.getCipher('blowfish-cfb',cryptKey,iPad);

            iPad.setBlockSize( crypt.getBlockSize() );

            var cryptText:ByteArray = new ByteArray();
            cryptText.writeUTF( $text );

            crypt.encrypt( cryptText );

            trace( Base64.encodeByteArray( cryptText ) );

            return null;
        }

        static public function decrypt($text:String, $key:String=""):String
        {
            return new String();
        }

    }
}

その出力は実行ごとに異なりますが、この実行例の目的のために、得られる base64 でエンコードされた出力は「EkKo9htSJUnzBmxc0A==」です。

そのコードを PHP に取り込むと、復号化するために以下のメソッドに渡される前に base64 でデコードされます。

public static function decrypt($crypttext,$key)
{

        if( !function_exists('mcrypt_module_open') ) trigger_error('The blowfish encryption class requires the Mcrypt library to be compiled into PHP.');
    $plaintext = '';
    $td        = mcrypt_module_open('blowfish', '', 'cfb', '');
    $blocksize    = mcrypt_enc_get_block_size($td);
    $iv        = substr($crypttext, 0, $blocksize);
    $crypttext = substr($crypttext, $blocksize);
    if (true)
    {
        mcrypt_generic_init($td, $key, $iv);
        $plaintext = mdecrypt_generic($td, $crypttext);
    }
    return $plaintext;
}

この時点で、出力は完全に読めなくなります。この問題は、blowfish の as3crypto 実装が正しくない (可能性は低い) か、使用するパディング (現在は null パディング) に関係している可能性があるか、最後に私が考えたことが原因であると思われます。エンコードされた文字列の先頭に追加されていない as3crypto でランダムに生成された初期化ベクトルと関係がありますか? as3crypto ライブラリは大規模で複雑であり、文書化されていないため、最後の 1 つを実際にテストすることはできませんでした。私はこの問題をグーグルで検索し、数日間すべてをテストしましたが、PHP で使用できないデータを見つけ続けています。Flash から PHP へのシステムを動作させることができるかどうかはわかっています。それをリバース エンジニアリングして、PHP から Flash への暗号化も実行することができます。

実際に夜の睡眠が犠牲になっているので、この件に関するすべての意見を歓迎します笑 よろしくお願いします:)


今日、さらにテストを行い、疑ったように初期化ベクトルであるかどうかを確認しようとしました。それが問題だとは思いません。エンコードされた出力を生成するために使用される IV の出力を取得できるように、フラッシュでいくつかのことを変更しました。

 package lib.ef.crypto
{
    import com.hurlant.util.Base64;
    import com.hurlant.crypto.Crypto;
    import flash.utils.ByteArray;
    import com.hurlant.crypto.symmetric.IPad;
    import com.hurlant.crypto.symmetric.ICipher;
    import com.hurlant.crypto.symmetric.NullPad;

    public class Blowfish
    {
        /**
        * Encrypts a string.
        * @param text  The text string to encrypt.
        * @param key  A cipher key to encrypt the text with.
        */
        static public function encrypt($text:String, $key:String=""):String
        {
            var cryptKey:ByteArray = new ByteArray();
            cryptKey.writeUTF( $key );

            var iPad:IPad = new NullPad();

            var crypt = Crypto.getCipher('blowfish-cfb',cryptKey,iPad);

            iPad.setBlockSize( crypt.getBlockSize() );

            var cryptText:ByteArray = new ByteArray();
            cryptText.writeUTF( $text );

            crypt.encrypt( cryptText );

            cryptText.position = 0;

            var iv:ByteArray = crypt.IV;

            iv.position = 0;

            trace( Base64.encodeByteArray( iv ) );

            trace( Base64.encodeByteArray( cryptText ) );

            return null;
        }

        static public function decrypt($text:String, $key:String=""):String
        {
            return new String();
        }

    }
}

この例では、「1bcGpqIbWRc=」のエンコードされた IV と「XpgART3hNQO10vcgLA==」のエンコードされた暗号化データを取得しました。base64_decode() でそれらを ing した後、これらを修正した PHP 関数にプラグインしました。

 public static function decrypt($crypttext,$key,$iv=NULL)
    {

        if( !function_exists('mcrypt_module_open') ) trigger_error('The blowfish encryption class requires the Mcrypt library to be compiled into PHP.');
        $plaintext = '';
        $td        = mcrypt_module_open('blowfish', '', 'cfb', '');
        if( $iv === NULL ){
            $ivsize    = mcrypt_enc_get_iv_size($td);
            echo '<pre>'.$ivsize.'</pre>';
            $iv        = substr($crypttext, 0, $ivsize);
            echo '<pre>'.strlen($iv).'</pre>';
            $crypttext = substr($crypttext, $ivsize);
        }
        if ($iv)
        {
            mcrypt_generic_init($td, $key, $iv);
            $plaintext = mdecrypt_generic($td, $crypttext);
        }
        return $plaintext;
    }

この出力でさえ正しくありません。IV が Flash と PHP の両方で正しいサイズであることを確認するためにいくつかのテストを行いましたが、何らかの理由で PHP 側では Flash からのフグでエンコードされた出力を復号化できません。as3crypto で NULL と PKCS5 の両方のパディングを使用してみましたが、どちらも PHP のシステムでは機能しません。IV 文字列が Flash と PHP の両方で同じであることを確認するためにテストしました。どちらも同じキーを使用しています。どちらもCFBモードを使用しています。理解できません。同じアルゴリズム、同じキー、同じ IV、同じモードですが、互いに復号化できません。フグの as3crypto 実装が正しくないように思えます。誰でもこれを確認できますか?

4

2 に答える 2

1

ありがとう!ここで正しい「復号化」を参照してください。

static public function decrypt(txt:String, k:String=""):String{

    var kdata:ByteArray;
    kdata = Hex.toArray(Hex.fromString(k));

    var data:ByteArray;
    data = Base64.decodeToByteArray(txt);

    var pad:IPad = new NullPad;
    var mode:ICipher = Crypto.getCipher('simple-blowfish-cbc', kdata, pad);
    pad.setBlockSize(mode.getBlockSize());
    mode.decrypt(data);
    data.position = 0;

    return data.readUTFBytes( data.bytesAvailable );

}
于 2013-03-10T15:36:48.577 に答える
1

as3Crypto ライブラリ ファイルとデモ コードを調べたところ、blowfish-cfb モードではなく simple-blowfish-cfb モードで getCipher 関数を使用する必要があることが問題であることがわかりました。crypt.encyrpt( cryptText ) の呼び出しからの暗号化された出力には、アルゴリズムの IV が既にプレフィックスとして付けられているため、Base64.encodeByteArray( cryptText ) を 1 回呼び出して、PHP に送信する出力を取得します。上記の方法で PHP を初期化すると、文字列から IV が切り離され、適切に復号化されます。うまくいけば、これはこの問題に付随する他の人の助けになります.

「正しい」フラッシュと PHP コード* は、すべての TLDR; 簡単なコピー/貼り付けソリューションが必要な人のために以下にあります :P

*注: 両方のコード サンプルでアプリケーション固有の呼び出しの一部を削除する必要があり、それらが 100% 機能することを保証するためにそれらをテストしませんでしたが、概念/構造を十分に説明して、正しく動作しない場合は「アウト」する必要があります。箱の「」を使用すると、簡単に修理できます。

PHP「ヘルパー」クラス:

class Blowfish
{

    public static function encrypt($plaintext,$key)
    {
        if( !function_exists('mcrypt_module_open') ) trigger_error('The blowfish encryption class requires the Mcrypt library to be compiled into PHP.');
        $td = mcrypt_module_open('blowfish', '', 'cbc', '');
        $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, $key, $iv);
        $crypttext = mcrypt_generic($td, $plaintext);
        mcrypt_generic_deinit($td);
        $out = $iv.$crypttext;
        return $out;
    }

    public static function decrypt($crypttext,$key)
    {
        if( !function_exists('mcrypt_module_open') ) trigger_error('The blowfish encryption class requires the Mcrypt library to be compiled into PHP.');
        $plaintext = '';
        $td        = mcrypt_module_open('blowfish', '', 'cbc', '');
        $ivsize    = mcrypt_enc_get_iv_size($td);
        $iv        = substr($crypttext, 0, $ivsize);
        $crypttext = substr($crypttext, $ivsize);
        if ($iv)
        {
            mcrypt_generic_init($td, $key, $iv);
            $plaintext = mdecrypt_generic($td, $crypttext);
        }
        return $plaintext;
    }

}

Flash「ヘルパー」クラス:

package [your package name]
{
    import com.hurlant.util.Base64;
    import com.hurlant.util.Hex;
    import com.hurlant.crypto.Crypto;
    import flash.utils.ByteArray;
    import com.hurlant.crypto.symmetric.IPad;
    import com.hurlant.crypto.symmetric.ICipher;
    import com.hurlant.crypto.symmetric.IVMode;
    import com.hurlant.crypto.symmetric.NullPad;

    public class Blowfish
    {
        /**
        * Encrypts a string.
        * @param txt  The text string to encrypt.
        * @param k  A cipher key to encrypt the text with.
        */

        static public function encrypt(txt:String, k:String=""):String
        {
            var kdata:ByteArray;
            kdata = Hex.toArray(Hex.fromString(k));

            var data:ByteArray;
            data = Hex.toArray(Hex.fromString(txt));

            var pad:IPad = new NullPad;
            var mode:ICipher = Crypto.getCipher('simple-blowfish-cbc', kdata, pad);
            pad.setBlockSize(mode.getBlockSize());
            mode.encrypt(data);

            return Base64.encodeByteArray( data );
        }

        /**
        * Decrypts a string.
        * @param txt  The text string to decrypt.
        * @param k  A cipher key to decrypt the text with.
        */

        static public function decrypt(txt:String, k:String=""):String
        {
            var kdata:ByteArray;
            kdata = Hex.toArray(Hex.fromString( Base64.decode( k ) ));

            var data:ByteArray;
            data = Hex.toArray(Hex.fromString(txt));

            var pad:IPad = new NullPad;
            var mode:ICipher = Crypto.getCipher('simple-blowfish-cbc', kdata, pad);
            pad.setBlockSize(mode.getBlockSize());
            mode.decrypt(data);
            data.position = 0;
            return data.readUTFBytes( data.bytesAvailable );
        }

    }
}
于 2011-08-10T13:35:29.170 に答える