加密地窖-尝试在PHP中以与Perl相同的方式工作


Encryption Crypt - Trying to get to work in PHP same way as Perl

我已经在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::CBCmcrypt_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。或者类似的东西,这里的文档有点令人困惑。如果同时设置了-ivliteral_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