PHP 河豚 cbc VS 珍珠地穴

PHP blowfish cbc VS Pearl Crypt

我正在使用 openssl_encrpyt 加密 PHP 中的客户号码。

$value = '01715034842';
$key = 'pi3kn3W@k@cj3';                
$iv = 'Toy@dtv!';
$cipher = 'bf-cbc';

$crypted = openssl_encrypt($value, $cipher, $key, true, $iv);
$hashValue = unpack('H*',$crypted);

最终结果是: 0b6b81176ac7c298ebcb294f0a581539

我的朋友也在 Pearl 编程其他部分。他还使用相同的密钥并使用 Blowfish 对相同的数字进行编码(他使用的是珍珠库:https://metacpan.org/pod/release/LDS/Crypt-CBC-2.30/CBC.pm):

use Crypt::CBC;
use Crypt::Blowfish;


## szyfrowanie
my $key = 'pi3kn3W@k@cj3';
my $iv = 'Toy@dtv!';

my $cipher = Crypt::CBC->new(   -key    => $key,
                                -iv => $iv,
                                -header => 'none',
                                -cipher => 'Blowfish'
                            );
sub mkHash {
        my  $crypt = $cipher->encrypt_hex($_[0]);
#        print 'Hash: '.$crypt."\n";
        return $crypt;
}


sub deHash {
        my $crypt = $cipher->decrypt_hex($_[0]);
       # print 'string: '.$crypt."\n";
        return $crypt;
}

my $clientHash = mkHash($smc);

他对同一组数据得到不同的结果: c5377bcf0f55af641709c35928350576

所以我们不能广泛使用这种语言。 这取决于编程语言的差异?或者这是我的代码或语言中的错误? 我认为当我们使用相同的数据集和相同的加密(BlowFish CBC)时,我们应该在每种语言中得到相同的结果。

期待对此案的意见。

最佳 巴尔泰克

工作脚本

以下 PHP 和 Perl 脚本显示了如何为两种语言实现相同的输出。我将在下面解释一些细节。

PHP:

$value = '01715034842';
$cipher = 'bf-cbc';
$key = '12345678901234567890123456789012345678901234567890123456';
$option = OPENSSL_RAW_DATA;
$iv = 'Toy@dtv!';

$crypted = openssl_encrypt($value, $cipher, $key, $option, $iv);
echo($crypted)

Perl:

use Crypt::CBC;
use Crypt::Blowfish;

my $value = '01715034842';
my $key = '12345678901234567890123456789012345678901234567890123456';
my $iv = 'Toy@dtv!';

my $cipher = Crypt::CBC->new(   -literal_key => 1,
                                -key         => $key,
                                -iv          => $iv,
                                -header      => 'none',
                                -cipher      => 'Blowfish'
                            );

my $crypted = $cipher->encrypt($value);
print $crypted;

在两个输出上使用diff结果没有区别,表明它们是相同的:

$ diff <(php encrypt.php) <(perl encrypt.pl)
$

解释所需更改的详细信息

以下部分说明了与原始代码相比所需的更改。

加密密钥

PHP openssl_encrypt() 函数总是需要原始密钥。您给它的字节是用作加密密钥的字节。另一方面,Perl CBC class expects a passphrase by default, from which it will derive the encryption key by doing an MD5 hash。如果您希望 class 使用您的原始字节作为加密密钥,您必须将参数 literal_key 设置为 1

完成后,CBC class 期望密钥是加密方案 which the CBC class assumes to be 56 for the Crypt::Blowfish implementation 所需的确切字节数。因此,脚本中的调整键。否则你会得到的错误是 If specified by -literal_key, then the key length must be equal to the chosen cipher's key length of 56 bytes

输出格式

PHPopenssl_encrypt()函数默认returns一个base64编码的字符串,CBCclassreturns原始字节。使此一致的一种方法是在 PHP.

中设置 OPENSSL_RAW_DATA 选项

正在查看密文

如果您想以可读格式检查密文,您可以在末尾添加自己的打印例程或将输出通过管道传输到 hexdumpxxd[=31= 等工具中]

$ php encrypt.php | xxd
00000000: 5f35 3205 74e8 dcaa 2f05 9aa4 366e ef8b  _52.t.../...6n..
$ perl encrypt.pl | xxd
00000000: 5f35 3205 74e8 dcaa 2f05 9aa4 366e ef8b  _52.t.../...6n..