通过 mcrypt 加密并通过 openssl 使用模式 CBC 和密码 BLOWFISH 解密

Encrypt by mcrypt and decrypt by openssl with mode CBC and cipher BLOWFISH

我们已经用 mcrypt 密码 BLOWFISH 加密了一些数据,模式是 CBC 字符串在 php5.5 中加密,需要在 php7.1 中解密(php 版本升级)

以下是我们尝试使用 openssl

解密 mcrypt 字符串的代码
$data = "Lorem ipsum";
$key = "12345678";
$iv = "12345678";

$encrypted = mcrypt_encrypt(
    MCRYPT_BLOWFISH, $key, $data, MCRYPT_MODE_CBC, $iv);
echo $encrypted . PHP_EOL;

$decrypted = openssl_decrypt(
    $encrypted, "BF-CBC", $key,
    OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);

echo $decrypted;

以上代码不是解密字符串。 请建议我任何解密字符串的方法

您在 openssl 一侧遗漏了一个选项:OPENSSL_DONT_ZERO_PAD_KEY

如果给 openssl_decrypt() 的密钥长度短于密码的默认密钥长度(在本例中为 Blowfish),PHP openssl 胶水代码会扩展密钥通过添加额外的零来达到该长度。你可以看到它发生 heremcrypt 实现不执行该键填充。 Blowfish 的 openssl 默认密钥长度为 16 字节,因此如果您的密钥短于 16 字节,则 mcryptopenssl 的密钥将不同——除非您使用 openssl 不对键进行填充的选项。

验证确实如此:

# bf.php
$data = "Lorem ipsum";
$key = "12345678";
$iv = "12345678";

$encrypted = mcrypt_encrypt(
    MCRYPT_BLOWFISH, $key, $data, MCRYPT_MODE_CBC, $iv);
#echo $encrypted . PHP_EOL;

$decrypted = openssl_decrypt(
    $encrypted, "BF-CBC", $key,
    OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING | OPENSSL_DONT_ZERO_PAD_KEY, $iv);

echo $decrypted . PHP_EOL;

$ php bf.php
Lorem ipsum

也与末尾的零有关。扩展该建议:

var_dump($decrypted);
var_dump(rtrim($decrypted));

给予

string(16) "Lorem ipsum"
string(11) "Lorem ipsum"

你当然不能对二进制数据做rtrim,在那种情况下你必须记住或存储原始明文的大小,或者根据一些有用的填充模式手动填充数据与零填充相反。 mcrypt_encrypt() 似乎做不到。