الطريقة الصحيحة لتشفير الرقم السري في php

img

من هو المسؤول عن حماية الرقم السري؟

يعتبر الرقم السري من أثمن المعلومات بالنسبة للمستخدمين، فهو المفتاح الذي يسمح لهم بالولوج لحساباتهم، لذلك تجدهم حريصين على عدم مشاركة هذه البيانات الحساسة، ولكن هذا لا يقل أهمية عن حماية الرقم السري من طرف البرنامج، فأنت كمبرمج عليك الحرص دائمًا أن يكون برنامجك آمنًا، وأن تضع في الحسبان تأمين هذه البيانات بأفضل شكل ممكن.

فك تشفير الرقم السري خطيئة لا يمكن غفرانها!

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

تشفير الرقم السري يجب أن يكون ذو اتجاه واحد فقط!

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

تشفير باتجاه واحد

تشفير باتجاه واحد

التشفير ذو الاتجاه الواحد يعني أنه يمكن تشفير الرقم السري ولكن لا يمكن فك هذه الشيفرة، والطريقة الوحيدة لمعرفة الرقم السري المقترن بهذه الشفرة هي بالتخمين، أي أنه سيتم تشفير ملايين الأرقام السري وتجربتها واحدًا تلو الآخر حتى تصل للرقم السري المطلوب، هذا يجعل الجهد المبذول لفك تشفير الرقم السري لا يستحق عناء بذله إلا إن كان الرقم السري يخص شيئًا مهما.

الطريقة الصحيحة لتشفير الأرقام السرية في لغة البرمجة PHP.

كانت لغة PHP سابقًا توفر طرقًا كثيرة للتشفير، ولكن جميعها كانت طرق عامة لتشفير أي شيء، سواء كان رقمًا سريًا أو ملفًا أو حتى نصًا عاديًا، لم يكن هناك شيء مخصص للأرقام السرية، لهذا السبب إن كنت تشاهد درسًا في التشفير وكان هذا الدرس قديمًا فربما أنك قد رأيت المدرس يستخدم md5 أو sha1 (اللتان لم تعودا آمنتين في وقتنا الحاضر)، وفي أحسن الأحوال mcrypt (التي تم التخلي عنها في إصدار 7.1 من PHP وسيتم إزالتها في 7.2)، لذلك هذه الطرق تعد من أسوأ الخيارات لتشفير الرقم السري، ليس بسببها، بل لأن لغة PHP تطورت ووفرت حلولًا أفضل، إذًا قد تتساءل، ما الذي يجب عليك استخدامه؟

دوال تشفير الأرقام السرية password_*:

بدءًا من الإصدار 5.5 من PHP تم إضافة مجموعة دوال تُعنى بالأرقام السرية، هذه الدوال مخصصة فقط للتعامل مع الأرقام السرية سواء بتشفيرها أو التحقق من تطابق الرقم السري مع الشيفرة أو حتى التأكد مما إذا كان الرقم السري يحتاج لإعادة تشفير مرة أخرى أم لا.

تشفير الرقم السري:

لتشفير الرقم السري عليك أن تستخدم دالة password_hash:

string password_hash ( string $password , integer $algo [, array $options ] )

هذه الدالة تقبل ثلاثة قيم، وهي:

  1. الرقم السري: (تم الإشارة إليه بـ $password في المثال) وهي الرقم السري الذي تريد تشفيره، ونوعه سيكون نصي String.
  2. الخوارزمية: (تم الإشارة إليها بـ $algo في المثال) وهي الخوارزمية التي سيتم استخدامها في التشفير، يتم تغيير الخوارزمية بين الإصدارات لتحسين نسبة الأمان، ويُنصح باستخدام  PASSWORD_DEFAULT ليتم استخدام الخوازمية الافتراضية مع إصدارك.
  3. الخيارات الإضافية: (تم الإشارة لها بـ $options  في المثال) وهي مجموعة من الخيارات (الإختيارية) للتعامل مع الرقم السري، يمكنك معاينة هذه الخيارات في صفحة مرجع الدالة.

القيمة الراجعة ستكون واحد من اثنتين، إما أن تكون الرقم السري في حالة نجاح التشفير، أو عبارة عن False  في حالة فشل التشفير.

التحقق من الرقم السري:

بعد تشفير الرقم السري ستحصل على شيفرة، ولكن عند إدخال المستخدم للرقم السري، كيف تتأكد من أنه قام بإدخال رقم سري يتطابق مع الشيفرة؟

سابقًا كان يتم استخدام نفس دالة التشفير ومقارنتها مع الرقم السري المشفر، ولكن هذا لن يفلح مع دوال التشفير الخاصة بالأرقام السرية، لأنه يتم إنتاج شيفرة مختلفة كل مرة يتم فيها التشفير، بمعنى أنك إذا قمت بتشفير الرقم السري مرتين على التوالي فستظهر شيفرتان مختلفتان لنفس الرقم السري، لذلك كيف يمكنك التأكد من أن الشفيرة مخصصة لرقم سري معين؟

الحل في دالة password_verify، هذه الدالة تقوم بالتحقق من أن الشيفرة مخصصة للرقم السري المرفق.

boolean password_verify ( string $password , string $hash )

هذه الدالة تقبل قيمتان:

  1. الرقم السري دون تشفير: (تم الإشارة له بـ $password في المثال) وهو الرقم السري دون تشفير وسيكون من النوع النصي.
  2. الرقم السري بعد التشفير أو الشيفرة: (تم الإشارة لها بـ $hash  في المثال) وهي الشيفرة الناتجة عن دالة التشفير.

القيمة الراجعة من هذه الدالة ستكون True في حال التطابق وFalse في غير ذلك.

هل يحتاج الرقم السري لإعادة التشفير؟

قد تأتي بعض الحالات التي تحتاج فيها إلى التأكد من أن الرقم السري يحتاج إلى إعادة تشفير، فمثلًا تريد التأكد من أن الشفيرة الناتجة صالحة للإستخدام أو لأي سبب آخر، هذا ما وضعه مطوروا PHP في الحسبان لذلك أنشؤوا دالة password_needs_rehash، هذه الدالة تتحقق فيما إذا كان الرقم السري يحتاج إلى إعادة تشفير أم لا.

متى تستخدم هذه الدالة؟

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

boolean password_needs_rehash ( string $hash , integer $algo [, array $options ] )

تقبل هذه الدالة ثلاثة قيم وهي:

  1. الشيفرة: (تم الإشارة إليها بـ $hash في المثال) وهي الشيفرة التي تريد التحقق من صلاحيتها.
  2. الخوارزمية: (تم الإشارة إليها بـ $algo في المثال) وهي الخورزمية التي تريد التأكد من أن الشيفرة تستخدمها.
  3. الخيارات الإضافية: (تم الإشارة إليها بـ $options  في المثال) وهي مجموعة من الخيارات الإضافية، يجب أن تتطابق هذه الخيارات مع الخيارات التي استخدمتها أثناء تشفير الرقم السري لكي تكون عملية التحقق دقيقة.

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

معلومات حول الشيفرة:

إذا كنت تملك سيفرة ولكنك تريد معرفة خيارات التشفير المستخدمة فيها فذلك ممكن باستخدام دالة password_get_info، هذه الدالة تظهر لك معلومات التشفير التي تم استخدامها لتوليد الشيفرة.

array password_get_info ( string $hash )

تقبل هذه الدالة قيمة واحدة فقط وهي:

  • الشيفرة: (تم الإشارة إليها بـ $hash  في المثال) وهي الشيفرة التي تريد الحصول على معلومات حول خيارات تشفيرها.

القيمة الراجعة من هذه الدالة ستكون مصفوفة تحتوي على بيانات حول الشيفرة وهي:

  • algo وهي ثابت الخوارزمية الذي تمت كتابته في دالة التشفير، والثابت الافتراضي هو PASSWORD_DEFAULT.
  • algoName وهي اسم الخوارزمية بطريقة سهلة القراءة.
  • options وهي الخيارات التي تم استخدامها في التشفير.

الخلاصة:

بعد توفير هذه المجموعة من الدوال أصبح تشفير الرقم السري آمنًا وسهلًا، لذلك إذا كنت تستخدم الدوال القديمة مثل Md5 أو sha1 أو غيرها من الطرق التقليدية فعليك التوقف الآن، لأن في ذلك مخاطرة كبيرة، بيانات الناس أمانة، عليك الحفاظ عليها.

الكاتب أبو العصافير

أبو العصافير

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

مواضيع متعلقة