مولد السلاسل العشوائية في PHP: نظرة تحت الغطاء

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

كيف يعمل مولد السلاسل العشوائية في PHP حقًا؟ نلقي نظرة تحت الغطاء



هل تساءلت يومًا عما يحدث عندما تضغط على "إنشاء كلمة مرور" في موقع ما؟ أو عندما يقوم النظام بإنشاء معرف فريد لجلسة العمل الخاصة بك؟ في تسع حالات من أصل عشرة، يكون وراء ذلك مولد سلاسل عشوائية في PHP. قد يبدو الأمر بسيطًا: خذ مصفوفة من الرموز، اخلطها، وأخرج النتيجة. لكن الشيطان، كما هو الحال دائمًا، يكمن في التفاصيل.



على Stack Overflow، حصد سؤال "PHP random string generator" آلاف المشاهدات. وهذا ليس من قبيل الصدفة. المبتدئون يكتبون حلولاً بدائية باستخدام rand()، وذوو الخبرة يستخدمون random_int()، والخبراء يتجادلون حول الإنتروبيا. دعنا نفهم كيف يعمل كل شيء حقًا، ونكتب المولد المثالي الخاص بنا.



لماذا rand() هو الشر؟ (تنبيه: قابلية التوقع)



الطريقة "الطفولية" الأكثر شيوعًا هي استخدام rand() في حلقة:



<?phpfunction generateRandomString($length = 10) {    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';    $charactersLength = strlen($characters);    $randomString = '';    for ($i = 0; $i < $length; $i++) {        $randomString .= $characters[rand(0, $charactersLength - 1)];    }    return $randomString;}echo generateRandomString(); // الإخراج: "aB3kL9xQ2m"?>


الكود يعمل. ولكن فقط إذا كنت لا تهتم بالأمان. تستخدم الدالة rand() مولدًا خطيًا متطابقًا (LCG). هذه خوارزمية حتمية: بمعرفة الحالة الحالية، يمكن توقع جميع الأرقام التالية. علاوة على ذلك، يتم تهيئة rand() افتراضيًا بالقيمة 1 إذا لم تستدعِ srand(). وإذا استدعيتها، فغالبًا ما يتم أخذ البذرة (seed) من time()، مما يعطي 2-3 ملايين احتمال فقط. يستغرق التعداد (الاختراق بالتجربة) ثوانٍ.



الخلاصة: rand() مناسبة للألعاب والاختيار العشوائي للصور الرمزية، ولكنها غير مناسبة تمامًا لتوليد الرموز المميزة (tokens) أو كلمات المرور أو مفاتيح API.



تعرف على mt_rand() — أسرع، لكن ليس أكثر أمانًا



في PHP 4، ظهرت الدالة mt_rand()، المستندة إلى عجلة ميرسين (Mersenne Twister). إنها أسرع ولها دورة أفضل (2^19937 مقابل 2^31 لـ rand). لا يزال الكثيرون يستخدمونها كنسخة "متقدمة":



<?phpfunction generateTokenMtRand($length = 32) {    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';    $token = '';    for ($i = 0; $i < $length; $i++) {        $token .= $chars[mt_rand(0, strlen($chars) - 1)];    }    return $token;}?>


ولكن هناك خدعة هنا أيضًا. عجلة ميرسين غير آمنة تشفيريًا. من خلال سلسلة من 624 رقمًا تم إنشاؤها، يمكن استعادة الحالة الداخلية للمولد والتنبؤ بجميع القيم المستقبلية. وهذا أكثر من كافٍ لمهاجمة رمز إعادة تعيين كلمة المرور.



الخلاصة الأخلاقية: mt_rand() هو اختيار ممتاز للمحاكاة والاختبارات، ولكن ليس للأمان.



الثلاثي المقدس: random_int() و CSPRNG والإنتروبيا



بدءًا من PHP 7.0، لدينا random_int() و random_bytes(). هذه هي مولدات الأرقام العشوائية الزائفة الآمنة تشفيريًا (CSPRNG). ماذا يعني هذا عمليًا؟



  • الإنتروبيا: تجمع PHP "الضوضاء" من النظام: الوقت بين ضغطات المفاتيح، حركات الماوس، حزم الشبكة، مقاطعات الأقراص. في Linux يُستخدم /dev/urandom، وفي Windows يُستخدم CryptGenRandom.
  • عدم القدرة على التوقع: حتى بمعرفة الخوارزمية، لا يمكن استعادة البذرة (seed) أو توقع الرقم التالي.
  • التوزيع المنتظم: كل بايت يظهر باحتمال 1/256 بالضبط.


هذا هو شكل مولد السلاسل العشوائية الصحيح في PHP

المدونات

توصيات الكتب