我已经在Perl中编写了加密功能,我正试图在PHP中以同样的方式工作。
在PERL中:
#!/usr/bin/perl
use strict;
use warnings;
use Crypt::CBC;
use Crypt::Rijndael;
my $cryptkey = '_PRIVATE_';
my $cipher = Crypt::CBC->new( -key => $cryptkey,
-salt => 1,
-cipher => 'Rijndael',
);
my $data = "hello";
my $ciphertext = $cipher->encrypt_hex($data);
print "HEX_KEY: '$ciphertext' 'n";
输出:HEX_KEY:"53616 c7465645f5fc36630f5364619c31ac26e44809c81bf84ae995c22be45ce"
我正试图在PHP和输出相同的HEX工作,但它是不一样的,出了什么问题?
class Test {
public function Encypt($data, $cryptkey) {
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $cryptkey, $data, MCRYPT_MODE_CBC);
return bin2hex($encrypted);
}
}
$data = "hello";
$test = new Test();
$cryptkey = "_PRIVATE_";
$hex = $test->Encypt($data, $cryptkey);
echo $hex;
2 bab1b8874692176d213e4c23565b304
Crypt::CBC
和mcrypt_encrypt
使用不同的默认值,从而导致这种不匹配。
对于mcrypt_encrypt
,文档提供了以下信息:
string mcrypt_encrypt ( string $cipher , string $key , string $data , string $mode [, string $iv ] )
$cipher
为算法名。$key
是加密密钥,如果太短,将被NUL字节填充。$data
是要加密的数据,如果太短,它将被填充NUL字节。$mode
为操作模式,此处"cbc"
为正确模式。$iv
是初始化向量,如果没有提供它将被初始化为NUL字节。
对于Crypt::CBC
,我们得到这样的行为:
Crypt::CBC->new(KEYWORD_OPTIONS)
-key => STRING
是一些散列操作从中生成加密密钥的密码短语。-literal_key => BOOL
如果设置,则跳过-key
的哈希,并将其用作文字键。-cipher => CIPHER
密码或预初始化密码对象的名称。-salt => 1 | STRING
如果设置为"1"
,这将产生一个随机盐。任何其他值都被视为字面上的盐。如果需要添加盐,默认为-salt => 1
。或者类似的东西,这里的文档有点令人困惑。如果同时设置了-iv
和literal_key
选项,则不需要添加盐。-iv => STRING
为初始化向量,通常由盐生成。-header => STRING
控制输出的报头类型。默认为"salt"
,也可以设置为"none"
。
进一步注意,RIJNDAEL_128
意味着密钥长度为16,而Crypt::CBC
假设密钥长度为32
。
Crypt::Rijndael
而不使用Crypt::CBC
包装器可能更可取,因为这允许我们轻松地将所需选项设置为PHP使用的相同默认值:
use Crypt::Rijndael;
my $key = "_PRIVATE_";
my $data = "hello";
# pad the $key to 16 bytes
$key .= "'0" x (16 - length $key);
# pad the $data to a multiple of 16 bytes:
if (my $distance = length($data) % 16) {
$data .= "'0" x (16 - $distance);
}
my $crypt = Crypt::Rijndael->new($key, Crypt::Rijndael::MODE_CBC);
$crypt->set_iv("'0" x 16);
my $binary = $crypt->encrypt($data);
print unpack("H*", $binary), "'n";
输出2bab1b8874692176d213e4c23565b304
。