我已经在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: ‘53616c7465645f5fc36630f5364619c31ac26e44809c81bf84ae995c22be45ce’
我正在尝试在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;
输出量
2bab1b8874692176d213e4c23565b304
解决方法:
Crypt :: CBC和mcrypt_encrypt使用不同的默认值,这导致此不匹配.
对于mcrypt_encrypt
,文档提供以下信息:
string mcrypt_encrypt ( string $cipher , string $key , string $data , string $mode [, string $iv ] )
$cipher
is the algorithm name.$key
is the encryption key, if it is too short it will be padded with NUL bytes.$data
is the data to be encrypted, if it is too short it will be padded with NUL bytes.$mode
is the mode of operation, here"cbc"
is correct.$iv
is the initialization vector, if not provided it will be initialized as NUL bytes.
对于Crypt::CBC
,我们改为使用以下行为:
Crypt::CBC->new(KEYWORD_OPTIONS)
-key => STRING
is the passphrase from which the encryption key is generated by some hashing operations.-literal_key => BOOL
If set, this skips the hashing for the-key
and uses it as a literal key.-cipher => CIPHER
the name of a cipher, or a pre-initialized cipher object.-salt => 1 | STRING
If set to"1"
, this will produce a random salt. Any other values are taken as the literal salt. This defaults to-salt => 1
if a salt is needed. Or something like that, the docs are a bit confusing here. The salt is not needed if both the-iv
andliteral_key
options are set.-iv => STRING
is the initialization vector, which is usually generated from the salt.-header => STRING
controls what kind of header is prepended to the output. This defaults to"salt"
, but can also be set to"none"
.
还要注意,RIJNDAEL_128的密钥长度为16,而Crypt :: CBC的密钥长度为32.
最好使用不带Crypt :: CBC包装器的Crypt::Rijndael
,因为这使我们可以轻松地将必需的选项设置为与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.