Perl CBC ile şifreleyerek ve PHP mcrypt ile deşifre

3 Cevap php

Perl Crypt :: CBC (Rijndael, CBC) ile şifrelenmiş şifreli bir dize var. Orijinal şifresiz Crypt :: CBC encrypt_hex () yöntemi ile şifrelenmiş.

$encrypted_string = '52616e646f6d49567b2c89810ceddbe8d182c23ba5f6562a418e318b803a370ea25a6a8cbfe82bc6362f790821dce8441a790a7d25d3d9ea29f86e6685d0796d';

Ben kullanılan 32 karakter tuşuna sahip.

mcrypt başarıyla PHP içinde derlenmiş, ama ben PHP dize şifresini çalışıyorum çok zorlanıyorum. Ben geri anlamsız alıyorum.

Ben ('H *', $ encrypted_string) açmak, ben ikili benzediğini ardından 'RandomIV' bkz.

Ben doğru IV ayıklamak ve gerçek şifreli mesajı ayırmak için görünmüyor olabilir. Benim bilgi veren değilim biliyorum, ama ben nereden başlayacağınızı başka emin değilim.

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

Herhangi bir yardım, doğru yönde göstericiler, büyük mutluluk duyacağız. Ben daha fazla bilgi sağlamak için gereken varsa bana bildirin.

3 Cevap

Ben kullanmak için IV sadece CBC :: Crypt tarafından rasgele oluşturulur düşünüyorum. Ben doğru ve düzgün doc okuma olsam, bu paketten dizenin ilk 32 byte bulunuyor.

Iyi tuşu ile bu deneyin:

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

Bu da işe yaramadı. Ben Perl'ın CBC :: Crypt bir çok farklı PHP'nin mcrypt fonksiyonları daha şeyler yapan bir his var. Ben bunları karşılaştırmak benim PHP dizininde mcrypt işlevleri için kaynak kodunu bulmak için çalışıyorum, ama hayır şans henüz oldum.

Bu cevap Crypt tuzlu modu :: CBC, değil randomIV modu için, ama bu ben de bir çözüm için çok başka olabilir ararken sona erdi sayfasıdır.

Bu perl kodunu kullanırken:

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

(or even without salt and header which have these values by default) Perl will create a hash that is meant to be OpenSSL compliant. I did not find any PHP method that knows how to read this, so here is my own PHP version of the decoding found in CBC.pm. I extract key and iv, and then I let mcrypt finish the job.

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");
}

Not: rtrim benim durumumda gerekli, eğer varsa satırsonlarını biten yemek olabilir.