php openssl_decrypt() 参数(之前由 perl Crypt::CBC 加密)

php openssl_decrypt() parameters (encrypted previously by perl Crypt::CBC)

我的 encryption/decryption 环境在 Perl 中运行良好。从 php 读取该信息是我正在寻求答案的问题。下面是我的测试用例,我希望 php 正确打印 $decryption。目前我得到一个空白。

#(perl 5)  the encryption method
use Crypt::Blowfish;
use Crypt::CBC;
$cipher = Crypt::CBC->new( -key    => "example",
                           -cipher => 'Blowfish',
                           -iv     =>  '12345678',
                           -header      => 'none'
                          );

$pj="Testing encryption";
$pje = $cipher->encrypt("$pj");##
$pjf = unpack("H*", $pje), "\n";

open (FILE2,">data.txt");
print FILE2 "$pjf";
close (FILE2);

#(php 7.3)
<?php 

$data = file_get_contents("data.txt");
$encryption = pack("H*", $data);
$ciphering = "blowfish";
$options = 0; 

// Display the encrypted string 
echo "Encrypted String: " . $encryption . "\n"; 

// Non-NULL Initialization Vector for decryption 
$decryption_iv = '12345678'; 

// Store the decryption key 
$decryption_key = "example"; 

// Use openssl_decrypt() function to decrypt the data 
$decryption=openssl_decrypt ($encryption, $ciphering,  
        $decryption_key, $options, $decryption_iv); 

// Display the decrypted string 
echo "Decrypted String: " . $decryption; 
echo""
?> 

(谢谢)

在Perl代码中创建Crypt::CBC对象时,下面是关于key的定义,见here:

  • 因为未指定 -keysize 参数,密钥的最大大小为 56 字节。
  • 由于未指定 -literal_key 参数,该值被解释为密码短语,实际密钥是从中派生的(通常与盐组合)。
  • 由于未指定 -salt 参数,因此未使用盐,因此密钥仅从密码派生。

对于发布的 Perl 代码中的示例,作为十六进制字符串 ($pjf) 的密文是:

ecc9d0b2449ef433285ade2d02ac19184866f5f9b814bde2 

要使用发布的 PHP 代码成功解密此密文,需要进行以下更改:

  • 密钥必须从密码导出。这是在 expandKey 函数中完成的。密钥是通过创建密码的 MD5 哈希生成的。如果密钥没有所需的长度,它会再次散列并附加到前一个散列。这种情况会发生,直到生成具有所需长度的密钥。

  • 必须设置 OPENSSL_RAW_DATA 标志,因为加密数据作为原始数据传递给 openssl_decrypt 而不是 Base64 编码。或者,加密数据必须通过 Base64 编码为 openssl_decrypt.

PHP 代码包括更改:

$encryptedDataHex = 'ecc9d0b2449ef433285ade2d02ac19184866f5f9b814bde2';
$encryptedData = hex2bin($encryptedDataHex);

$key = expandKey('example'); 
$iv = '12345678'; 
$cipher = 'bf-cbc'; // 'blowfish' also works
$options = OPENSSL_RAW_DATA; 

$decryptedData = openssl_decrypt($encryptedData, $cipher, $key, $options, $iv); 

echo 'Decrypted data: ' . $decryptedData; 

function expandKey($key){
    $key = md5($key, true);
    while(strlen($key) < 56){
        $key .= md5($key, true);
    }
    return substr($key, 0, 56);
}