php 和 perl 3DES CBC 中的相同 return 值

Same return value in php and perl 3DES CBC

我想知道如何 return 在 perl 和 php 中为 3DES 加密设置相同的值。 PHP 代码如下:

$bytes = array(0,0,0,0,0,0,0,0);
$iv = implode(array_map("chr", $bytes)); 
$ciphertext = mcrypt_encrypt(MCRYPT_3DES, base64_decode('Mk9m98IfEblmPfrpsawt7BmxObt98Jev'), '0000001920', MCRYPT_MODE_CBC, $iv);
echo base64_encode($ciphertext);

结果是:"A/VCTXA6q/x/emW0zzlSDg=="

Perl 代码是:

use Crypt::CBC;
$cipher = Crypt::CBC->new(  -key    => decode_base64('Mk9m98IfEblmPfrpsawt7BmxObt98Jev'),
                                -cipher => 'DES_EDE3',
                                -iv     => pack("H*","0000000000000000"),
                                -literal_key => 1,
                                -header      => 'none'
                            );

$ciphertext = $cipher->encrypt("0000001920");
print encode_base64($ciphertext, '');

结果是:"A/VCTXA6q/y9g7ypgqlWIg=="

结果非常相似,我的 perl 代码哪里做错了?

您没有使用相同的填充机制。

如果您仔细阅读 PHP's mcrypt_encrypt 的参考页,您会在数据参数旁边看到以下注释:

If the size of the data is not n * blocksize, the data will be padded with '[=14=]'.

现在,如果您还阅读了 Perls Crypt::CBC 的参考页,您会注意到它们有几种填充方法(由 -padding 参数定义)。默认值是 PKCS#5,这与仅用 0x00.

填充不同

现在,如果您将填充更改为 "null",Perl 打印结果与 PHP 相同。所以你的代码应该是这样的:

use MIME::Base64;
use Crypt::CBC;
$cipher = Crypt::CBC->new(  -key    => decode_base64('Mk9m98IfEblmPfrpsawt7BmxObt98Jev'),
                                -cipher => 'DES_EDE3',
                                -iv     => pack("H*","0000000000000000"),
                                -padding     => "null",
                                -literal_key => 1,
                                -header      => 'none'
                            );

$ciphertext = $cipher->encrypt("0000001920");
print encode_base64($ciphertext, '');

或者你可以在 PHP 中实现 PKCS#5,你必须自己做,因为 PHP 默认不包含它(搜索 PHP PKCS#5你可能会找到一些你可以使用的代码片段,在 PHP-doc 评论之一中甚至有一个 simple PKCS#5 function