问题描述
目前,我们的系统上有一个 mcrypt 实现,用于对 PHP 应用程序中的一些敏感数据进行加密.现在我们有一个新要求,我们必须将 crypt 模块更改为 openssl.另一件重要的事情是我们正在使用密码河豚和模式 ecb.所以我开始测试有什么区别,以及如何使用 openssl 解密 mcrypt 加密的字符串.
currently we have a mcrypt implentation on our systems to crypt some sensible data in our PHP application. Now we have a new requirement that we have to change the crypt module to openssl. Another thing which is important know is that we are using the cipher blowfish and the mode ecb. So I began to test what are differences and how I can decrypt mcrypt encrypted strings with openssl.
我使用了标准的 PHP 函数:
I used the standard PHP function:
- mcrypt_encrypt 与 openssl_encrypt
- mcrypt_decrypt 与 openssl_decrypt 对比
两种方法都产生不同的结果.第二件事是,在给定的密码 (blowfish) 和模式 (ecb) 中,两种类型都需要不同的 IV 长度(openssl=0 和 mcrypt=56).
Both methods are delivering different results. Second thing is that in the given cipher (blowfish) and mode (ecb) in both types different IV lengthes are required (openssl=0 and mcrypt=56).
有谁知道我如何在不进行大量迁移工作的情况下轻松更改模块?
Does anybody know how I can easily change the modules without having a big migration effort?
提前致谢!
更新:
这是我测试过的代码:
<?php
function say($message){
if(!is_string($message)){
if(!isset($_SERVER["HTTP_USER_AGENT"])) echo "<pre>";
echo var_export($message, true) . ((!isset($_SERVER["HTTP_USER_AGENT"]) ? "
" : "<br />"));
if(!isset($_SERVER["HTTP_USER_AGENT"])) echo "</pre>";
}else{
echo $message . ((!isset($_SERVER["HTTP_USER_AGENT"]) ? "
" : "<br />"));
}
}
say("= Begin raw encryption");
$key = "anotherpass";
$str = "does it work";
say(" Params:");
say(" - String to encrypt '".$str."'");
say(" - Key: ".$key);
say("");
$params = array(
"openssl" => array(
"cipher" => "BF",
"mode" => "ECB",
),
"mcrypt" => array(
"cipher" => "blowfish",
"mode" => "ecb",
),
);
say("= Mcrypt");
$handler = mcrypt_module_open($params['mcrypt']['cipher'], '', $params['mcrypt']['mode'], '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($handler), MCRYPT_RAND);
$keysize = mcrypt_enc_get_key_size($handler);
mcrypt_generic_init($handler,$key," ");
say(" Params:");
say(" - InitVector ".bin2hex($iv)." (bin2hex)");
say(" - Max keysize ".$keysize);
say(" - Cipher ".$params['mcrypt']['cipher']);
say(" - Mode ".$params['mcrypt']['mode']);
say("");
say(" Encryption:");
$m_encrypted = mcrypt_generic($handler, $str);
$m_decrypted = mdecrypt_generic($handler, $m_encrypted);
say(" - Encrypted ".bin2hex($m_encrypted)." (bin2hex)");
say(" - Descrypted ".$m_decrypted);
say("");
say("= Openssl");
say(" Params:");
say(" - InitVector not needed");
say(" - Max keysize ".openssl_cipher_iv_length($params['openssl']['cipher']."-".$params['openssl']['mode']));
say(" - Cipher ".$params['openssl']['cipher']);
say(" - Mode ".$params['openssl']['mode']);
say("");
say(" Encryption:");
$o_encrypted = openssl_encrypt($str,$params['openssl']['cipher']."-".$params['openssl']['mode'],$key,true);
$o_decrypted = openssl_decrypt($o_encrypted,$params['openssl']['cipher']."-".$params['openssl']['mode'],$key,true);
say(" - Encrypted ".bin2hex($o_encrypted)." (bin2hex)");
say(" - Descrypted ".$o_decrypted);
And this is my result:
这是我的结果:
Maybe any ideas now?
现在可能有什么想法了吗?
Thanks!
谢谢!
推荐答案
Blowfish 是分组密码.它要求在加密之前填充数据.OpenSSL 使用 PKCS#7,mcrypt 使用 PKCS#5.数据的不同填充算法.最小 PKCS#5 填充长度为 0,对于 PKCS#7,它为 1(维基百科).看看这个例子(我已经手动填充了 PKCS#7 风格的 mcrypt_encrypt()
输入数据):
<?php
$key = "anotherpassword1";
$str = "does it work 12";
$enc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $str."1", MCRYPT_MODE_ECB);
$dec = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $enc, MCRYPT_MODE_ECB);
echo(bin2hex($enc).PHP_EOL);
var_dump($dec);
$enc = openssl_encrypt($str, 'bf-ecb', $key, true);
$dec = openssl_decrypt($enc, 'bf-ecb', $key, true);
echo(bin2hex($enc).PHP_EOL);
var_dump($dec);
?>
It's impossible to openssl_decrypt() data encrypted with mcrypt_encrypt(), unless manual data padding was made with PKCS#7 before mcrypt_encrypt()
was called.
不可能打开用 mcrypt_encrypt() 加密的 openssl_decrypt() 数据,除非在调用 mcrypt_encrypt()
之前用 PKCS#7 手动填充数据.
There is only one way in your case - recrypt the data.
在您的情况下只有一种方法 - 重新加密数据.
PS: There is an error in your source - ECB mode does not uses IV at all (wikipedia)
这篇关于用 OpenSSL 替换 Mcrypt的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!