php和perl 3DES CBC中的返回值相同


Same return value in php and perl 3DES CBC

我想知道如何在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的mcrypt_encrypt的参考页面,你会在数据参数旁边看到以下注释:

如果数据的大小不是n*块大小,则数据将填充"''0"。

现在,如果您还阅读了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文档注释中有一个简单的PKCS#55函数)。