PHP河豚CBC VS珍珠地穴

时间:2018-08-27 07:50:53

标签: php openssl crypt blowfish

我使用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对相同的数字进行编码(他使用的是Pearl库: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)时,每种语言都应获得相同的结果。

期待对此案发表意见。

最佳 Bartek。

1 个答案:

答案 0 :(得分:2)

工作脚本

以下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类是expects a passphrase by default类,它将从中派生加密密钥by doing an MD5 hash。如果要让类使用原始字节作为加密密钥,则必须将参数literal_key设置为1

完成此操作后,CBC类将期望密钥为加密方案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

输出格式

默认情况下,PHP openssl_encrypt()函数返回base64编码的字符串,CBC类返回原始字节。保持一致的一种方法是通过在PHP中设置OPENSSL_RAW_DATA选项。

检查密文

如果要检查可读格式的密文,则可以在末尾添加自己的打印例程,或者将输出通过管道传输到hexdumpxxd之类的工具中

$ 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..