Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 将带有Blowfish和ECB的mcrypt迁移到OpenSSL_Php_Encryption_Openssl_Mcrypt - Fatal编程技术网

Php 将带有Blowfish和ECB的mcrypt迁移到OpenSSL

Php 将带有Blowfish和ECB的mcrypt迁移到OpenSSL,php,encryption,openssl,mcrypt,Php,Encryption,Openssl,Mcrypt,我一辈子都不知道如何将遗留的mcrypt代码迁移到OpenSSL。我让它为CBC的河豚和CBC的Rijndael工作,但ECB的河豚一直在逃避我 是的,我读了,我尝试了零填充数据,而不是零填充数据,零填充键,循环键和它们的任何组合,但似乎没有任何效果 这是我的代码: <?php function encrypt_with_mcrypt($data, $key) { return mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data, MCR

我一辈子都不知道如何将遗留的mcrypt代码迁移到OpenSSL。我让它为CBC的河豚和CBC的Rijndael工作,但ECB的河豚一直在逃避我

是的,我读了,我尝试了零填充数据,而不是零填充数据,零填充键,循环键和它们的任何组合,但似乎没有任何效果

这是我的代码:

<?php
function encrypt_with_mcrypt($data, $key) {
        return mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data, MCRYPT_MODE_ECB);
}

function encrypt_with_openssl($data, $key) {
        return openssl_encrypt($data, 'BF-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY);
}

$data = 'foobar';
$key = 'supersecretkey';

var_dump(base64_encode(encrypt_with_mcrypt($data, $key)));
var_dump(base64_encode(encrypt_with_openssl($data, $key)));

mcrypt库/包装器默认为零字节填充(仅在需要时),而OpenSSL库/包装器默认为PKCS#5填充。这意味着单个块的填充方式不同,因此将显示不同的密文块


一个常见的技巧是在不进行任何解密的情况下解密生成的密文,然后通过查看明文+十六进制填充来检查填充字节

这将向您展示:

5z0q3xNnokw=
666f6f6261720000
对于mcrypt和

1zyqavq7sCk=
666f6f6261720202
对于OpenSSL

使用需要加密多个块的更大的明文消息也会向您表明,除了最后一个块之外,加密工作进展顺利


当且仅当mcrypt输入不是8字节的倍数(Blowfish的块大小)时,首先对数据进行零填充,然后使用
OPENSSL\u zero\u PADDING
作为填充模式

请注意,查看源代码显示,出于某些未指定的原因,
OPENSSL\u ZERO\u PADDING
似乎表示“无填充”对于包装器和
OPENSSL\u NO\u PADDING
似乎与其他设置冲突-我认为这是PHP OPENSSL包装器API开发人员的一个相当糟糕的设计和实现错误


更多信息可以在下面找到,显示API如何填充/取消填充(或忘记填充/取消填充,具体取决于您所处的位置)。

我没有太多要补充的内容,只是我认为最好能显示一些说明其文字的代码

mcrypt
添加零以将明文填充到8字节BF blocksize的倍数,可通过打印明文和解密密文的十六进制转储来显示:

$key = "supersecretkey";
$data = "foobar";
$ctxt = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data, MCRYPT_MODE_ECB);
$ptxt = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $ctxt, MCRYPT_MODE_ECB);
echo bin2hex($data).PHP_EOL;
echo bin2hex($ptxt).PHP_EOL;
提供以下十六进制转储:

666f6f626172
666f6f6261720000
openssl
默认情况下使用PKCS#5填充,在这种情况下,在块的末尾添加2个字节,值为2:

$key = "supersecretkey";
$data = "foobar";
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY;
$ctxt = openssl_encrypt($data, 'BF-ECB', $key, $opts);
$ptxt = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $ctxt, MCRYPT_MODE_ECB);
echo bin2hex($data).PHP_EOL;
echo bin2hex($ptxt).PHP_EOL;
给予

通过手动添加填充字节,可以使
mcrypt
openssl
的密文保持一致。注意
OPENSSL\u ZERO\u PADDING
选项和添加的
“\0\0”

给出:

e73d2adf1367a24c
e73d2adf1367a24c
或者,在使用
mcrypt
时,在末尾手动插入PKCS#5个填充字节:

$key = "supersecretkey";
$data = "foobar";
$ctxt_mc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data."\2\2", MCRYPT_MODE_ECB);
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY;
$ctxt_os = openssl_encrypt($data, 'BF-ECB', $key, $opts);
echo bin2hex($ctxt_mc).PHP_EOL;
echo bin2hex($ctxt_os).PHP_EOL;
给予

最后,尝试在禁用填充且长度不是块大小倍数的情况下调用
openssl\u encrypt()

$key = "supersecretkey";
$data = "foobar";
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY | OPENSSL_ZERO_PADDING;
$ctxt = openssl_encrypt($data, 'BF-ECB', $key, $opts);
echo(openssl_error_string().PHP_EOL)
给予


备注:名称
OPENSSL\u ZERO\u PADDING
令人困惑,但它的意思是“无填充”。您可能想使用该标志,但该标志不适用于
openssl\u encrypt()
。其值为,与
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
相同。相反,.

学习一个男人如何钓鱼,你的卡加克会一直被鱼线困住,这个男人会对你大喊大叫:p“使用OPENSSL\u ZERO\u填充可能会导致麻烦,因为OPENSSL总是填充”:我相信这是不正确的。在这种情况下,PHP到OpenSSL的粘合层显式禁用填充,在这种情况下,如果明文长度不是8字节的倍数,
OpenSSL\u encrypt()
调用将失败。是的,我同意你所说的一切,除了那一句话。出于教育目的,我还写了一个补充答案,简要地介绍了这个问题,但在其他方面支持你的答案。谢谢:-)。支持PHP OpenSSL包装器API的一点是:函数的文档中提到了
OpenSSL\u ZERO\u PADDING
而不是
OpenSSL\u NO\u PADDING
。同样,
openssl\u public\u encrypt()
提到了
openssl\u NO\u PADDING
而不是
openssl\u ZERO\u PADDING
。但这仍然让所有人感到困惑。
e73d2adf1367a24c
e73d2adf1367a24c
$key = "supersecretkey";
$data = "foobar";
$ctxt_mc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data."\2\2", MCRYPT_MODE_ECB);
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY;
$ctxt_os = openssl_encrypt($data, 'BF-ECB', $key, $opts);
echo bin2hex($ctxt_mc).PHP_EOL;
echo bin2hex($ctxt_os).PHP_EOL;
d73caa6afabbb029
d73caa6afabbb029
$key = "supersecretkey";
$data = "foobar";
$opts = OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY | OPENSSL_ZERO_PADDING;
$ctxt = openssl_encrypt($data, 'BF-ECB', $key, $opts);
echo(openssl_error_string().PHP_EOL)
error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data not multiple of block length