Шифроване с Perl CBC и дешифриране с PHP mcrypt

Имам шифрован низ, който беше шифрован с Perl Crypt::CBC (Rijndael,cbc). Оригиналният обикновен текст беше шифрован с метода encrypt_hex() на Crypt::CBC.

$encrypted_string = '52616e646f6d49567b2c89810ceddbe8d182c23ba5f6562a418e318b803a370ea25a6a8cbfe82bc6362f790821dce8441a790a7d25d3d9ea29f86e6685d0796d';

Имам използвания ключ от 32 знака.

mcrypt е успешно компилиран в PHP, но ми е много трудно да се опитвам да дешифрирам низа в PHP. Продължавам да получавам безсмислици.

Ако разопаковам ('H*', $encrypted_string), виждам 'RandomIV', последвано от нещо, което изглежда като двоично.

Изглежда не мога да извлека правилно IV и да отделя действителното криптирано съобщение. Знам, че не предоставям информацията си, но не съм сигурен откъде другаде да започна.

$cipher = 'rijndael-256';
$cipher_mode = 'cbc';

$td = mcrypt_module_open($cipher, '', $cipher_mode, '');

$key = '32 characters'; // Does this need to converted to something else before being passed?
$iv = ??  // Not sure how to extract this from $encrypted_string.
$token = ?? // Should be a sub-string of $encrypted_string, correct?

mcrypt_generic_init($td, $key, $iv);
$clear = rtrim(mdecrypt_generic($td, $token), '');
mcrypt_generic_deinit($td); 
mcrypt_module_close($td);

echo $clear;

Всяка помощ, насоки в правилната посока, ще бъдат високо оценени. Кажете ми, ако трябва да предоставя повече информация.


person Ed.    schedule 09.04.2010    source източник


Отговори (3)


Мисля, че IV за използване се генерира на случаен принцип от CBC::Crypt. Ако съм прав и чета документа правилно, това са първите 32 байта от разопакования низ.

Опитайте това с добрия ключ:

$cipher = 'rijndael-256';
$cipher_mode = 'cbc';

$td = mcrypt_module_open($cipher, '', $cipher_mode, '');

$key = '32 characters'; // Does this need to converted to something else before being passed?

$unpacked = pack('H*', '52616e646f6d49567b2c89810ceddbe8d182c23ba5f6562a418e318b803a370ea25a6a8cbfe82bc6362f790821dce8441a790a7d25d3d9ea29f86e6685d0796d');


$iv = substr($unpacked, 0, 32);
$token = substr($unpacked, 32);

mcrypt_generic_init($td, $key, $iv);
$clear = rtrim(mdecrypt_generic($td, $token), '');
mcrypt_generic_deinit($td); 
mcrypt_module_close($td);

echo $clear;
person Arkh    schedule 09.04.2010

Този отговор е за осоления режим на Crypt::CBC, а не за режима randomIV, но това е страницата, на която се озовах, когато търся решение, така че други може също.

Когато използвате този perl код:

  my $cipher = Crypt::CBC->new(
                -key    =>  $password,
                -cipher => 'Rijndael',
                -salt => 1,
                -header => 'salt',
              ) || die "Couldn't create CBC object";
  $string = $cipher->encrypt_hex($input);

(или дори без сол и заглавка, които имат тези стойности по подразбиране) Perl ще създаде хеш, който е предназначен да бъде съвместим с OpenSSL. Не намерих PHP метод, който знае как да разчете това, така че ето моята собствена PHP версия на декодирането, намерена в CBC.pm. Извличам ключ и iv и след това оставям mcrypt да свърши работата.

function cred_decrypt($input, $password)
{
  /************************* Inspired by Crypt/CBC.pm *******************************/
  $input = pack('H*', $input);
  if (substr($input, 0, 8) != 'Salted__') {
    die("Invalid hash header, expected 'Salted__', found '".substr($input, 0, 8)."'");
  }
  $salt   = substr($input, 8, 8);
  $input  = substr($input, 16);

  $key_len  = 32;
  $iv_len   = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);

  $data = '';
  $d    = '';
  while (strlen($data) < $key_len+$iv_len) {
    $d = md5($d . $password . $salt, TRUE);
    $data .= $d;
  }
  $key  = substr($data, 0, $key_len);
  $iv   = substr($data, $key_len, $iv_len);
  /**********************************************************************************/

  return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $input, MCRYPT_MODE_CBC, $iv), "\0\n\3");
}

Забележка: rtrim беше необходим в моя случай, може да изяде края на новия ред, ако има такъв.

person Côme BERNIGAUD    schedule 03.07.2013

Това също не проработи. Имам чувството, че CBC::Crypt на Perl прави нещата много по-различно от функциите mcrypt на PHP. Опитвам се да намеря изходния код за функциите mcrypt в моята PHP директория, за да ги сравня, но все още нямам успех.

person Ed.    schedule 13.04.2010