我目前对 ActionScript 3 有点陌生,并且一直在尝试使用 as3crypto 库使用河豚算法加密一些数据,然后再将其提交给服务器进行处理。我知道您可以使用 https,但大多数浏览器仍会显示出站数据,这使得用户很容易伪造请求。这就是为什么我想让用户看到页面请求,但不解密就无法读取数据。
对我来说不幸的是,除了代码中的注释(没有太大帮助)之外,as3crypto 库上的 deocumentation 几乎不存在。我已经用几个静态函数设置了闪存方面的东西来“实现”as3crypto河豚加密,它们仅适用于在闪存中加密/解密。当我尝试使用密钥在 PHP 中使用 mcrypt 库进行解密时,问题就出现了。我得到的输出不是原始代码,我花了几天时间试图弄清楚为什么无济于事。
下面是代码和解释。出于本示例的目的,使用的密钥是“mykey”(不带引号),编码数据是“Hello World”(同样不带引号)。
Flash 代码(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;
}
此时输出完全不可读。我怀疑这个问题可能与河豚的 as3crypto 实现不正确(不太可能)或者它可能与它使用的填充(当前为空填充)有关,或者最后我认为它可能有与 as3crypto 中随机生成的初始化向量没有被添加到编码字符串的前面有关吗?最后一个我无法真正测试,因为 as3crypto 库很大、很复杂,而且根本没有太多文档记录。我已经用谷歌搜索了这个问题并测试了几天所有的东西,我只是不断地想出 PHP 中不可用的数据。我知道如果我可以让 Flash 到 PHP 系统正常工作,我可以对其进行逆向工程以使 PHP 到 Flash 加密也运行。
我欢迎所有关于这件事的意见,因为它实际上让我在晚上睡觉,哈哈提前谢谢你:)
我今天做了一些进一步的测试,并试图看看它是否是我怀疑的初始化向量。我不相信这是问题所在。我在 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() 之后将它们插入到修改后的 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 实现可能不正确。谁能证实这一点?