الجزء الثاني: كيفية جعل روبي AES-256-CBC و PHP MCRET_RIJNDAEL_128 تلعب جيدا معا

StackOverflow https://stackoverflow.com/questions/1864700

سؤال

هذا السؤال هو استمرار لآخر واحد، فيما يتعلق كيفية جعل Ruby AES-256-CBC و PHP Mcrypt_rijndael_128 تلعب جيدا معا. وبعد لقد عملت الآن، لكنني ما زلت أكافح من أجل الذهاب إلى الاتجاه الآخر. يبدو أن PHP تم إنشاؤه Cryptogram لديه جميع المعلومات التي تم توفيرها، لكنني لا أستطيع الحصول على رمز روبي لفك تشفيرها دون خطأ.

إليك رمز PHP الذي أستخدمه لإنشاء Cryptogram:

$cleartext = "Who's the clever boy?";
$key = base64_decode("6sEwMG/aKdBk5Fa2rR6vVw==\n");
$iv = base64_decode("vCkaypm5tPmtP3TF7aWrug==");
$cryptogram = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $cleartext, MCRYPT_MODE_CBC, $iv);
$result = base64_encode($cryptogram);
print "\n'$result'\n";

RESULT
'JM0OxMINPTnF1vwXdI3XdKI0KlVx210CvpJllFja+GM='

ثم ها هي محاولة فك تشفيرها في Ruby:

>> cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
>> cipher.key = Base64.decode64("6sEwMG/aKdBk5Fa2rR6vVw==\n")
>> cipher.iv = Base64.decode64("vCkaypm5tPmtP3TF7aWrug==")
>> cryptogram = Base64.decode64('JM0OxMINPTnF1vwXdI3XdKI0KlVx210CvpJllFja+GM=')
>> cleartext = cipher.update(cryptogram)
=> "Who's the clever"
>> cleartext << cipher.final
OpenSSL::Cipher::CipherError: bad decrypt
 from (irb):100:in `final'
 from (irb):100

ما هو محبط حقا حول هذا هو أنه من الممكن الحصول على ClearText بالكامل من تلك السلسلة المشفرة. تكرار ما سبق، ولكن إضافة لوحة هرائية إلى التشفير:

  >> cleartext = cipher.update(cryptogram + 'pad')
  => "Who's the clever boy?\000\000\000\000\000\000\000\000\000\000\000"
  >> cleartext << cipher.final
  OpenSSL::Cipher::CipherError: bad decrypt
   from (irb):119:in `final'
   from (irb):119

في حالة الاستخدام الفعلي، تم تنظيم ClearText (سلسلة JSON، لأنني أسأل)، لذلك أشعر بالراحة هذه النقطة التي يمكنني إخبارها باستخدام هذا المخطط والكشف عن المدخلات المشفرة بشكل سيء دون أداء cipher.final. وبعد ومع ذلك، لا أستطيع أن أتسامح مع هذا النوع من Kludge في التعليمات البرمجية الخاصة بي، لذلك أود أن أفهم كيفية جعل رمز Ruby يتعامل مع الكتلة النهائية بأمان.

هل كانت مفيدة؟

المحلول

المشكلة هي mcrypt لا حشد الكتلة الأخيرة، في حين أن ربط Openssl في روبي يستخدم طريقة الحشو الافتراضية Openssl، وهي حشوة PKCS. لا أستطيع تحسين الوصف من وثائق Openssl:

يعمل حشوة PKCS عن طريق إضافة بايت محشوة N من القيمة N لجعل الطول الكلي للبيانات مضاعف من حجم الكتلة. يضاف الحشو دائما حتى إذا كانت البيانات بالفعل مضاعفة من حجم الكتلة N سوف تساوي حجم الكتلة. على سبيل المثال، إذا كان حجم الكتلة 8 و 11 بايت يتم تشفيره، فسيتم إضافة 5 بايت الحشو من القيمة 5.

ستحتاج إلى إضافة الحشو السليم يدويا إلى نهاية ClearText في PHP قبل التشفير. للقيام بذلك، تمر $cleartext من خلال هذا pkcs5_pad وظيفة على الجانب php قبل تشفيرها (تمر 16 كما الحظر).

function pkcs5_pad ($text, $blocksize)
{
    $pad = $blocksize - (strlen($text) % $blocksize);
    return $text . str_repeat(chr($pad), $pad);
}

إذا ذهبت أيضا في الاتجاه الآخر (تشفير في Ruby و Decrypt مع Mcrypt)، فسيتعين عليك تجريد البايتات الحشو بعد فك تشفيرها.

ملاحظة جانبية: السبب في إضافته إلى إضافة الحشو حتى إذا كان ClearText هو بالفعل مضاعف من الحظر (كتلة كاملة من الحشو)، فذلك عندما تقوم بفك تشفيرك أن البايت الأخير من الكتلة الأخيرة هو دائما كمية الحشو المضافة. خلاف ذلك، لا يمكنك معرفة الفرق بين ClearText مع بايت الحشو واحة واحدة واضحة مع عدم وجود بايت الحشو التي حدثت للتو في القيمة 0x01.

نصائح أخرى

يبدو PHP. \0 منصات ClearText قبل تشفيرها. يمكنك تعيين روبي لتعطيل الحشو.

http://www.ruby-doc.org/stdlib-9.3/libdoc/openssl/rdoc/openssl/cipher.html#m#met-i-padding-3d.

سيعمل ذلك، ولكن بعد ذلك يجب أن تجرى الحشو يدويا.

1.9.3p125 :008 > cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
 => #<OpenSSL::Cipher::Cipher:0x0000000561ee78>
1.9.3p125 :009 > cipher.decrypt
 => #<OpenSSL::Cipher::Cipher:0x0000000561ee78>
1.9.3p125 :010 > cipher.padding = 0
 => 0
1.9.3p125 :011 > cipher.key = Base64.decode64("6sEwMG/aKdBk5Fa2rR6vVw==\n")
 => "\xEA\xC100o\xDA)\xD0d\xE4V\xB6\xAD\x1E\xAFW"
1.9.3p125 :012 > cipher.iv = Base64.decode64("vCkaypm5tPmtP3TF7aWrug==")
 => "\xBC)\x1A\xCA\x99\xB9\xB4\xF9\xAD?t\xC5\xED\xA5\xAB\xBA"
1.9.3p125 :013 > cryptogram =  Base64.decode64('JM0OxMINPTnF1vwXdI3XdI2j8NJ8kr+Du0fnkxorNl0=')
 => "$\xCD\x0E\xC4\xC2\r=9\xC5\xD6\xFC\x17t\x8D\xD7t\x8D\xA3\xF0\xD2|\x92\xBF\x83\xBBG\xE7\x93\x1A+6]"
1.9.3p125 :014 > cleartext = cipher.update(cryptogram)
 => "Who's the clever girl?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
1.9.3p125 :015 > cleartext << cipher.final
 => "Who's the clever girl?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"



1.9.3p125 :042 > cleartext.strip
 => "Who's the clever girl?"
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top