حجم المفتاح غير الصحيح عند تنفيذ تشفير Crypto ++ AES إلى Mcrypt's PHP

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

سؤال

في وقت سابق تمكنت من تنفيذ بعض C ++ Cryptopp Rijndael_128 CBC Code إلى Mcrypt PHP ، لكنني الآن أواجه مشاكل في وضع CFB. لا تتطابق نتائج C ++ و PHP (حسنًا ، تتطابق البايت الأول ، لكن هذا قد يكون مصادفة ، كل شيء آخر لا). مع بعض التشخيصات ، يبدو أن Mcrypt من PHP لا يضع طول المفتاح بشكل صحيح؟

إليكم C ++ (تشخيصات وسطاقات الشمس التي تمت إزالتها من أجل البساطة):

CFB_Mode<AES>::Encryption encryptor(g_encrypt_key, AES::DEFAULT_KEYLENGTH, g_encrypt_iv);

StringSource ss( sInput.c_str(), true, 
        new StreamTransformationFilter( encryptor, 
            new HexEncoder( new StringSink( sEncryptedOut ) )
        ));

وهنا PHP:

$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CFB, '')
mcrypt_generic_init($cipher, $g_encrypt_key, $g_encrypt_iv);

$sEncryptedOutput = mcrypt_generic( $cipher, $sInput);
mcrypt_generic_deinit($cipher);
mcrypt_module_close($cipher);

g_encrypt_key و g_encrypt_iv يبلغ طول كلاهما 16 بايت ، وتطابق البايتات لإصدارات C ++ و PHP. بالنسبة لإصدار PHP ، فهي سلسلة ثنائية تم إنشاؤها من البايتات (نعم لقد راجعت هذه المتطابقة).

لقد أضفت مكالمات إلى إصدار PHP للتحقق $cipherحجم الكتلة ، وحجم المفتاح ، وما إلى ذلك. حجم الكتلة وحجم الرابع كلاهما 16 ؛ يتم الإبلاغ عن أحجام المفاتيح المدعومة على أنها 16 و 24 و 32 - كلها كما هو متوقع.

حيث أعتقد أن المشكلة هي أن المفاتيح يتم الإبلاغ عنها على أنها 32 بايت. بالنظر إلى مستندات MCRYPT ، فإن الطريقة الوحيدة لتحديد المفاتيح هي توفير مفتاح الحجم المطلوب. لكنني أمر مفتاح بايت 16! فلماذا تقوم بالإبلاغ عن وجود مفتاح 32 بايت؟ إذا كان وضع CFB يجب أن يستخدم مفتاح 32 بايت ، فلماذا يقبل Cryptopp أنه بخير؟ ماهو الحل؟ هل يمكنني إجبار PHP على استخدام مفتاح البايت الـ 16 الذي تم توفيره؟ أم أن هناك معلمة أفتقدها والتي تتخلف عن إعداد مختلف في Cryptopp عن Mcrypt؟

أنا أستخدم وضع CFB لأنني أريد تقليل طول البيانات المشفرة الناتجة. البايتات القليلة التي ستقدمها الحشو ، لا تهم في هذا التطبيق.

يجب أن أكون قادرًا على تشفير/فك التشفير في C ++ ولكن فقط تشفير في PHP. يمكن القول أن AES مبالغة في طلبي - الحد الأدنى الذي أحتاجه هو "التدافع الجيد للبايت" بحيث تكون وظيفة البايتات الفردية في البيانات غير واضحة.

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

المحلول

لقد كان الوقت لحظة ، لكن كان لدي بعض المشكلات المماثلة مع Mcrypt و Openssl باستخدام CFB قبل عامين. في النهاية ، اكتشفت أن Mcrypt استخدمت حجم سلسلة التغذية المرتدة الافتراضية المختلفة عن OpenSSL في وضع CFB. وهذا يعني ، أعتقد أن OpenSSL AES128 في CFB استخدم حجم الكتلة وحجم ردود الفعل 128 بت ، في حين استخدم Mcrypt حجم كتلة 128Bits وحجم ردود الفعل 8 بت. ليس لدي أي وسيلة لتأكيد ذلك ، لقد كانت مجرد تكهنات في ذلك الوقت بناءً على قراءة بعض منشورات المنتدى القديمة. بغض النظر عن حقيقة هذه النظرية ، لم أكن الشخص الوحيد أو أولاً لدي هذه القضية بالذات.

كان الحل بالنسبة لي هو استخدام NOFB بنفسك. بحسب ال مرجع مكتبة PHP Mcrypt MCRYPT_MODE_NOFB يفرض سلسلة التعليقات على مساواة حجم كتلة الخوارزمية ، وفي هذه الحالة كتلة/ردود فعل 128 بت لـ AES128 (Rijndael) ، والتي تتطابق مع ما manpage للوحدة MCRYPT ينص على NOFB. هذا جيد لأن كل ما وجدته قال إن ملاحظات NOFB متزامنة مع حجم الكتلة. وبالتالي ، أصبح كل من McRypt و OpenSSL في NOFB الآن أحجام مفتاح/IV/Block/Block/Block/Block لـ AES128 ، وكل شيء على ما يرام.

بقدر PHP الإبلاغ عن مفاتيح 256bit (32 بايت) ، فإن الوظيفة التي تُرجع حجم مفتاح المشفر الحالي ، تُرجع حجم المفتاح القصوى إلى الحد الأقصى للحجم ، والذي لم يتم ذكره بوضوح في الوثائق. أعرف ذلك لأن صفي الصغير الذي أستخدمه طوال الوقت الآن لمشاريع مختلفة يعمل بشكل جيد تمامًا مع OpenSSL وأي مكتبات AES أخرى في CBC أو NOFB. لن يكون هذا هو الحال إذا كان Mcrypt يحشّن مفتاح 128bit (16 char) مع 128bits إضافية من سلسلة فارغة ، أو أي شيء آخر ، ولن يكون صحيحًا من الناحية الفنية على أي حال.

ليست حقًا إجابة جيدة ، ولكن أفضل ما حصلت عليه استنادًا إلى غزوة للهواة للغاية في التشفير قبل عدة سنوات.

نصائح أخرى

تحقق من phpseclib:

http://phpseclib.sourceforge.net/

يمكنك ضبط حجم المفتاح وحجم كتلة على كل ما تريد.

على سبيل المثال. $ aes-> setKeyLength (128) أو $ aes-> setKeyLength (256) ؛

واجهت هذه المشكلة - بضع نقاط. بشكل افتراضي ، يقوم وضع PHP Rijndael بتعيين حلقة التغذية المرتدة إلى 8Bits - أن تكون AES هي بنفس طول المفتاح IV/المفتاح.

يمكنك القيام بذلك باستخدام وضع "NCFB" بدلاً من "CFB" أو MCRYPT_MODE_CFB.

التفاصيل الكاملة لكتابة AES_CFB_128 PHP متوافقة مع هذا الأمن stackexchange سؤال: AES CFB 128 مشكلة فك التشفير /التشفير بين Erlang و PHP. أقل منه (من توم ليك):

... بالنسبة لكل من CFB و OFB (والتي تختلف عن بعضها البعض ولا يمكن استخدامها بالتبادل) ، عليك أن تقلق بشأن "طول التعليقات" الذي لا يتم توثيقه بالضرورة بوضوح كبير في مكتبات التشفير المختلفة. يجب أن يستخدم كل من التشفير وفك التشفير نفس طول التغذية المرتدة للتفاعل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top