PHP Blowfish cbc VS Pearl Crypt

Я шифрую номера клиентов в PHP, используя openssl_encrpyt.

$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), мы должны получать одинаковые результаты на каждом языке.

Ждем мнения по этому делу.

Лучший Бартек.


person Bartłomiej Wiśniewski    schedule 27.08.2018    source источник


Ответы (1)


Рабочие скрипты

Следующие сценарии 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)

Перл:

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 по умолчанию ожидает кодовую фразу, из которого будет получен ключ шифрования выполнением хэш MD5. Если вы хотите, чтобы класс использовал ваши необработанные байты в качестве ключа шифрования, вы должны установить для параметра literal_key значение 1.

После того, как вы это сделаете, класс CBC ожидает, что ключ будет содержать точное количество байтов, необходимое для схемы шифрования, который класс CBC принимает за 56 для реализации Crypt::Blowfish. Отсюда и скорректированный ключ в скриптах. В противном случае вы получите ошибку 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 возвращает необработанные байты. Один из способов сделать это согласованным — установить параметр OPENSSL_RAW_DATA в PHP.

Проверка зашифрованного текста

Если вы хотите проверить зашифрованный текст в удобочитаемом формате, вы можете добавить свои собственные процедуры печати в конце или направить вывод в инструмент, такой как hexdump или xxd

$ 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..
person Reinier Torenbeek    schedule 27.08.2018
comment
Спасибо, это очень помогло. - person Bartłomiej Wiśniewski; 28.08.2018