كيف تخزّن كلمات سر المستخدمين؟ Argon2id بإعدادات OWASP

خزّن كلمة السر كـ hash بطيء مش كنص مشفّر: Argon2id بـ 19 MiB ذاكرة وتكرارين وخيط واحد حسب OWASP، والـ salt بتعمله المكتبة لحالها.

نُشر في 5 دقائق قراءة#أمن التطبيقات#تطوير الويب

يوم بتتسرّب قاعدة بيانات موقعك، الشي الوحيد يلي بيوقف بين المهاجم وكلمات سر مستخدمينك هو سطر واحد كتبته يوم عملت صفحة التسجيل: الدالة يلي بتحوّل كلمة السر لنص بالجدول. إذا هالسطر بيستعمل تشفير بمفتاح، أو hash سريع، التسريب بيصير تسريب كلمات سر. رح تعرف تحت شو بتستعمل بداله، وبأي إعدادات، وكيف تنقل الحسابات القديمة بلا ما توقّف حدا.

ليش التشفير مش الطريقة الصح لتخزين كلمات السر؟

التشفير بيشتغل باتجاهين: يلي معه المفتاح بيرجّع كلمة السر الأصلية، فإذا المفتاح انسرق مع قاعدة البيانات، كل كلمات السر بتنكشف.

الـ hash هو دالة باتجاه واحد: بتاخد كلمة السر وبتطلّع بصمة، وما في طريق يرجع من البصمة لكلمة السر. لما المستخدم بيسجّل دخول، بتعمل hash للكلمة يلي كتبها وبتقارن البصمتين. هاد الفرق مكتوب بأول دليل تخزين كلمات السر عند OWASP: الـ hashing دالة باتجاه واحد، والتشفير باتجاهين، والمهاجم بيقدر يرجّع النص الأصلي من البيانات المشفّرة.

الغلطة يلي بيوقع فيها كتير مطورين منطقية: بيسمعوا «احمي كلمات السر»، فبيشفّروها. بس موقعك ما بيحتاج يعرف كلمة السر أبداً، بيحتاج يقارن معها بس، فالعمود الآمن هو يلي حتى إنت ما بتقدر ترجّع كلمة السر منه.

شو هو الـ Argon2id وبأي إعدادات بتستعمله؟

الـ Argon2id هو خوارزمية hash بطيئة عن قصد ومصمّمة لكلمات السر، وهي أول اختيار عند OWASP بأقل إعدادات: 19 MiB ذاكرة، وتكرارين، وخيط واحد.

البطء هون هو الحماية. كل محاولة تخمين بتكلّف المهاجم ذاكرة ووقت، فتجريب قائمة كلمات سر طويلة على البصمات المسروقة بيصير أغلى بكتير. بلغة إعدادات الخوارزمية، هالإعدادات بتنكتب m=19456, t=2, p=1: الذاكرة بالـ KiB، وعدد التكرارات، وعدد الخيوط.

OWASP بتعطي كمان تركيبات تانية بنفس مستوى الحماية، والفرق بينها بس بين استهلاك المعالج واستهلاك الذاكرة. يعني إذا سيرفرك ذاكرته قليلة، فيك تقلّل الذاكرة وتزيد التكرارات حسب الجدول بالدليل.

شو بتستعمل إذا ما في Argon2id؟

إذا ما في Argon2id، OWASP بتنصح بـ scrypt، وبعده bcrypt بس للأنظمة القديمة يلي ما فيها ولا وحدة منهن.

الخوارزمية

إمتى

أقل إعدادات حسب OWASP

Argon2id

الاختيار الأول

19 MiB ذاكرة، تكرارين، خيط واحد

scrypt

إذا ما في Argon2id

كلفة ذاكرة ومعالج 2^17، حجم بلوك 8، وتوازي 1

bcrypt

أنظمة قديمة بس

عامل شغل 10 على الأقل، وأكبر قد ما بيتحمّل سيرفرك

انتبه لشغلة بالـ bcrypt: أغلب تطبيقاته بتقرا أول 72 بايت بس من كلمة السر، فـ OWASP بتنصح تحط حد أقصى لطول كلمة السر 72 بايت إذا بتستعمله.

لازم تعمل الـ salt بإيدك؟

لأ، الـ salt بتعمله المكتبة لحالها. الـ salt قيمة عشوائية بتنضاف لكل كلمة سر قبل الـ hash، لحتى مستخدمين عندهم نفس كلمة السر ما يطلعلهم نفس البصمة.

دليل OWASP بيقول إنو أغلب المكتبات المنتشرة بتعمل الـ salt وبتديره من جوّا، فما بتحتاج تكتب كود إله. وبـ PHP الشي أوضح: حسب صفحة password_hash بتوثيق PHP، خيار الـ salt صار قديم، ومن PHP 8.0.0 أي salt بتعطيه بإيدك بينتجاهل.

والـ pepper شي تاني: سر زيادة ما بينحفظ مع الـ hash، وبينضاف فوق الـ salt. إذا قررت تستعمله، خزّنه متل أي مفتاح سري برّا قاعدة البيانات، وشوف كيف بتبدّل هيك أسرار بمقال تسريب متغيرات البيئة بـ Railway.

كيف بيطلع الكود بـ PHP؟

بـ PHP بتستعمل password_hash مع PASSWORD_ARGON2ID لتخزين كلمة السر، وpassword_verify لتسجيل الدخول، وبتعطي الإعدادات بالخيارات.

<?php
$options = ['memory_cost' => 19456, 'time_cost' => 2, 'threads' => 1];

$hash = password_hash($password, PASSWORD_ARGON2ID, $options);

if (password_verify($password, $hash)) {
    // سجّل دخول المستخدم
}

تلات شغلات من نفس صفحة التوثيق لازم تعرفها قبل ما تنسخ الكود:

  1. PASSWORD_ARGON2ID انزاد بـ PHP 7.3.0، وبيشتغل بس إذا PHP مبني مع دعم Argon2. جرّبه على سيرفرك قبل ما تعتمد عليه.

  2. memory_cost بالـ KiB، فـ 19456 هي الـ 19 MiB تبع OWASP. وخيار threads بيشتغل بس لما PHP بيستعمل libargon2، مش libsodium.

  3. PASSWORD_DEFAULT هلق هو bcrypt، مش Argon2id. فإذا بدك Argon2id، اكتبه بالاسم.

وخلّي عمود الـ hash بقاعدة البيانات واسع: التوثيق بينصح بعمود بيوسع أكتر من 60 بايت، و255 بايت اختيار منيح.

كيف تنقل كلمات السر القديمة لـ Argon2id؟

بتنقلها وقت تسجيل الدخول: بعد ما كلمة السر تطابق البصمة القديمة، بتعمل hash جديد بـ Argon2id وبتحفظه مكان القديم.

بـ PHP هالشغلة إلها دالة جاهزة. صفحة password_needs_rehash بتقول إنها بترجّع true إذا البصمة المحفوظة مش بالخوارزمية والإعدادات يلي عطيتها:

<?php
$options = ['memory_cost' => 19456, 'time_cost' => 2, 'threads' => 1];

if (password_verify($password, $storedHash)) {
    if (password_needs_rehash($storedHash, PASSWORD_ARGON2ID, $options)) {
        $newHash = password_hash($password, PASSWORD_ARGON2ID, $options);
        // احفظ $newHash بسجل المستخدم مكان القديم
    }
    // سجّل دخول المستخدم
}

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

من وين تبلّش اليوم؟

افتح الكود يلي بيحفظ كلمة السر بصفحة التسجيل، وشوف شو الدالة يلي بيستعملها. إذا تشفير أو hash سريع، حط مكانه Argon2id بإعدادات OWASP، وزيد خطوة إعادة الـ hash بتسجيل الدخول اليوم.

الدرس إلنا كمطورين: كلمة السر ما بتنحفظ لحتى نرجعلها، بتنحفظ لحتى نقارن معها بس. لهيك بتستعمل hash بطيء بـ salt لكل مستخدم، فحتى لو البصمات تسرّبت، كل تخمين بيكلّف المهاجم ذاكرة ووقت.

وبعد كلمات السر، الجلسة هي يلي بتحمي الحساب: افحص أقفال كوكي الجلسة بموقعك. وإذا بدك حدا يفحص تسجيل الدخول والجلسات بمنصتك مع باقي الثغرات، مُحَصَّن بيفحص منصتك وبيسلّمك خطة إصلاح واضحة.

أسئلة شائعة

شو الفرق بين الـ salt والـ pepper؟

الـ salt قيمة عشوائية لكل كلمة سر، بتنحفظ مع الـ hash والمكتبة بتعملها لحالها. الـ pepper سر زيادة ما بينحفظ مع الـ hash، وبينضاف فوق الـ salt، مش بداله.

شو بعمل إذا PHP عندي ما فيه دعم Argon2؟

PASSWORD_ARGON2ID بيشتغل بس إذا PHP مبني مع دعم Argon2. إذا ما في، OWASP بتنصح بـ scrypt، وbcrypt بس للأنظمة القديمة يلي ما فيها لا Argon2 ولا scrypt.

قديش لازم يكون طول عمود الـ hash بقاعدة البيانات؟

توثيق PHP بينصح بعمود بيوسع أكتر من 60 بايت، و255 بايت اختيار منيح، لأنو طول الناتج ممكن يتغيّر لما تتغيّر الخوارزمية.

لازم أجبر كل المستخدمين يغيّروا كلمات السر لما أغيّر الخوارزمية؟

مش دايماً. فيك تعيد الـ hash وقت تسجيل الدخول، وتخلّي القديم والجديد يشتغلوا سوا بفترة الانتقال. وOWASP بتقترح كمان تنهي صلاحية كلمة السر الحالية وتطلب من المستخدم وحدة جديدة.

شارك المقال

نسخة Markdown

مقالات أخرى