سؤال

لا أعرف الكثير عن التشفير ، لكنني تمكنت من تشغيل AES في PHP ... إلى حد ما. فيما يلي وظائف زوجين أستخدمها:

function aes_decrypt($val,$ky) 
{ 
    $key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 
    for($a=0;$a<strlen($ky);$a++) 
      $key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a])); 
    $mode = MCRYPT_MODE_ECB; 
    $enc = MCRYPT_RIJNDAEL_128; 
    $dec = @mcrypt_decrypt($enc, $key, $val, $mode, @mcrypt_create_iv( @mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND) ); 
    return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null)); 
} 

function aes_encrypt($val,$ky) 
{ 
    $key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 
    for($a=0;$a<strlen($ky);$a++) 
      $key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a])); 
    $mode=MCRYPT_MODE_ECB; 
    $enc=MCRYPT_RIJNDAEL_128; 
    $val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16))); 
    return mcrypt_encrypt($enc, $key, $val, $mode, mcrypt_create_iv( mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND)); 
} 

يتم تعديل هذه قليلاً من أ التعليق على صفحة وثائق PHP لـ Mcrypt. (لقد تغيرت من Dev_urandom إلى Rand ، لأنني على مربع Windows ، حيث لا يتوفر Dev_urandom.)

على أي حال ، يتم تعريف المفتاح الذي أستخدمه في هذه الوظائف على هذا النحو:

define("PSK", pack("H*", "abcd7b5ca46e12345678a8161fdacee9"));

أسمي وظيفتي مثل هذه:

echo bin2hex(aes_encrypt("wootwootwootwootwootwootwoo", PSK));

الآن ، أول 16 بايت (32 رقمًا) من سلسلة السداسي الناتجة على ما يرام. لا تتطابق البايتات الـ 16 التالية مع ما هو متوقع.

انظر ، أنا أقوم بنشر هذه البيانات إلى خدمة ويب خارجية تقوم بعد ذلك بفك تشفيرها. (لسوء الحظ) لا يمكنني إعطاء حالة اختبار واحدة لدي دون توزيع مفتاح التشفير والبيانات. أنا آسف للغاية على ذلك ، لكنني آمل أن يتمكن شخص مطلع على Mcrypt من النظر إلى هذا ويخبرني بما أفعله خطأ.

مرة أخرى ، آسف على عدم وجود حالة اختبار صلبة ، لكنني أقدر كثيرًا أي مساعدة يمكنك تقديمها!

تعديل: يبدو أن مزودتي التي أقوم بنشرها هي استخدام Null IV. بعد نصيحة Rook ، قمت بالتبديل إلى وضع CBC ، وأزلت الرمز غير الضروري المتعلق بالمفتاح. ها هي وظيفاتي الجديدة:

function aes_decrypt($val,$key)
{
    $mode = MCRYPT_MODE_CBC;
    $enc = MCRYPT_RIJNDAEL_128; 
    $dec = @mcrypt_decrypt($enc, $key, $val, $mode, null); 
    return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null)); 
}

function aes_encrypt($val,$key) 
{
    $mode = MCRYPT_MODE_CBC;
    $enc=MCRYPT_RIJNDAEL_128; 
    $val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16))); 
    return mcrypt_encrypt($enc, $key, $val, $mode, null); 
}
هل كانت مفيدة؟

المحلول

من المحتمل أن تستخدم خدمة التشفير هذه وضعًا مختلفًا للتشفير مثل CBC. إذا تم استخدام NULL IV مع وضع CBC ، فإن الكتلة الأولى (في هذه الحالة 16 بايت) من ECB و CBC ستنتج نفس نص المشفر. يجب ألا يستخدم أي شخص وضع البنك المركزي الأوروبي لأي سبب من الأسباب.

فيما يلي مثال على الوضع المشفر في وضع الأوراق الأوروبي: رسالة مشفرة:

alt text

نصائح أخرى

أنا وكلية لي حيث ترميز تطبيق iPhone وحيث استخدام الطرق المذكورة أعلاه لتشفير البيانات وفك تشفيرها. لكننا وجدنا مشكلة عندما كنت أقوم بتشفير البيانات التي سيتم قراءتها من جهاز iPhone الخاص به. يستخدم iPhone حشو PKCS7. كان الرمز أعلاه يضيف حشوة إضافية ، وهذا من شأنه أن يتسبب في فشل طريقة فك تشفير iPhone. قمنا بتعديل الرمز لإصلاح المشكلة الحالية:

public static function  aes128Encrypt($key,$val) 
{
    $mode = MCRYPT_MODE_CBC;
    $enc=MCRYPT_RIJNDAEL_128; 
    $blocksize= mcrypt_get_block_size($enc,$mode);
    $stringLength = strlen($val);
    $paddingLength =$blocksize-($stringLength%$blocksize);
    $val=str_pad($val,$paddingLength+$stringLength,chr($paddingLength));
    return base64_encode(mcrypt_encrypt($enc, $key, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")); 
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top