首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在PHP中解密as3crypto河豚数据的错误

在PHP中解密as3crypto河豚数据的错误
EN

Stack Overflow用户
提问于 2011-08-08 03:56:37
回答 2查看 2K关注 0票数 0

目前,我对ActionScript 3还比较陌生,在将其提交给服务器进行处理之前,我一直试图使用as3crypto库对一些数据进行河豚算法加密。我知道您可以使用https,但是大多数浏览器仍然显示出站数据,使得用户很容易伪造请求。这就是为什么我想让用户看到页面请求,但不能在不解密的情况下读取数据。

不幸的是,对于我来说,除了代码中的注释之外,as3crypto库上的去中心功能几乎是不存在的(这并没有太大帮助)。我用一些静态函数设置了闪存端,以“实现”as3crypto河豚加密,它们只适用于flash中的加密/解密。当我试图使用mcrypt库在PHP中使用密钥解密时,问题就出现了。我得到的输出不是原始代码,我花了几天时间试图找出为什么没有效果。

下面是代码和解释。在这个例子中,使用的键是'mykey‘(没有引号),编码的数据是'Hello’(同样没有引号)。

Flash代码(as3crypto河豚助手):

代码语言:javascript
复制
    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解码:

代码语言:javascript
复制
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;
}

此时,输出完全不可读。我怀疑这个问题可能与以下事实有关:河豚的as3crypto实现不正确(不太可能),或者可能与它使用的填充(当前为空填充)有关,或者最后,我认为它可能与as3crypto中随机生成的初始化向量有关,而不是被加到编码字符串的前面?最后一次我还不能真正测试,因为as3crypto库很大,很复杂,而且文档也不多。我已经在谷歌上搜索了这个问题,并测试了几天的所有内容,我只是不断地想出PHP中无法使用的数据。我知道如果我能让Flash到PHP系统工作,我可以反向工程它,让PHP的Flash加密也运行。

我欢迎所有关于这件事的意见,因为它实际上已经让我在晚上睡不着觉了,谢谢:)

我今天做了一些进一步的测试,并试图看看它是否像我所怀疑的那样是初始化向量。我不相信这就是问题所在。我在闪存中修改了一些内容,以便获得用于生成编码输出的IV的输出:

代码语言:javascript
复制
 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();
        }

    }
}

在这个例子中,我得到了一个编码的IV '1bcGpqIbWRc=‘和加密的'XpgART3hNQO10vcgLA==’数据--在对它们进行base64_decode()处理之后,我将它们插入一个修改后的PHP函数中:

代码语言:javascript
复制
 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和as3crypto填充,但两者都不适用于PHP的系统。我已经进行了测试,以确保在Flash和PHP中IV字符串是相同的。他们都用同样的钥匙。两者都在使用循环流化床模式。我还是不明白。相同的算法、相同的密钥、相同的IV、相同的模式,但它们不能相互解密。在我看来,河豚的as3crypto实现可能是错误的。有人能证实这一点吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-10 13:35:29

在对as3Crypto库文件和演示代码进行了一些深入研究之后,我发现问题在于,我需要使用简单的getCipher函数,而不是blowfish cfb模式。然后调用crypt.encyrpt( cryptText )的加密输出将是以算法IV为前缀的,因此您只需对Base64.encodeByteArray( cryptText )进行一次调用,就可以获得要发送给PHP的输出。当您以上面的方式初始化PHP时,它将从字符串中分割出IV并正确地解密。希望这能帮助其他人解决这个问题。

以下是“正确的”闪存和PHP代码*,适用于所有只需要快速复制/粘贴解决方案的用户:P

*注意:我必须在两个代码示例中删除一些特定于我的应用程序的调用,并且没有对它们进行测试以确保它们是100%的功能,但是它们应该足够地说明概念/结构,如果它们不能正确地“开箱即用”,您可以很容易地修复它们供您使用。

PHP“助手”类:

代码语言:javascript
复制
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“助手”类:

代码语言:javascript
复制
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 );
        }

    }
}
票数 1
EN

Stack Overflow用户

发布于 2013-03-10 15:36:48

谢谢!请参见此处正确的“解密”:

代码语言:javascript
复制
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 );

}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6977595

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档