تخزين كلمات المرور واحد من المجالات القليلة في البرمجيات التي تملك إجابة صحيحة حقيقية، منشورة ومصانة ومتاحة مجاناً. وهو في الوقت نفسه من أكثر المجالات التي يقع فيها الخطأ باستمرار، لأن الإجابات الخاطئة كانت صحيحة في وقت ما ولم يعد إليها أحد بالمراجعة.
الإخفاق نادراً ما يكون غريباً. إنه نظام بُني في 2016 وفق نصائح كانت سارية في 2012، ولا يزال يعمل، ولا يزال يقبل عمليات الدخول، ولم يفتح أحد تلك الدالة منذ أن غادر الشخص الذي كتبها.
إن كنت ستأخذ شيئاً واحداً: استخدم Argon2id، وإن لم تستطع فاستخدم bcrypt. وكل ما تبقى في هذه المقالة تفصيل. دالة تجزئة عامة الغرض مثل SHA-256 ليست دالة تجزئة لكلمات المرور مهما كررت تطبيقها، لأن سرعتها هدف تصميمي، والسرعة هي بالضبط ما تحاول حرمان المهاجم منه وهو يملك قاعدة بياناتك.
لتخزين كلمات المرور شكل صحيح واحد فقط
خزّن قيمة تجزئة أنتجتها دالة بطيئة عمداً وكثيفة الاستهلاك للذاكرة، مع ملح عشوائي فريد لكل كلمة مرور، وبمعاملات مضبوطة على عتادك أنت.
إرشادات OWASP لتخزين كلمات المرور تذكر التوصيات الحالية بدقة، ويستحق الأمر أن تُقتبس بوصفها أرقاماً لا مبادئ.
| الخوارزمية | المعاملات الموصى بها | متى تستخدمها |
|---|---|---|
| Argon2id | 19 MiB من الذاكرة، 2 تكرار، 1 درجة توازٍ | الخيار الأول |
| scrypt | N=2^17 (128 MiB)، r=8، p=1 | إذا لم يتوفر Argon2id |
| bcrypt | معامل كلفة 10 أو أكثر، حد 72 byte لكلمة المرور | الأنظمة القديمة |
| PBKDF2-HMAC-SHA256 | 600,000 تكرار | حيث يُطلب الامتثال لـ FIPS-140 |
ملاحظتان على هذا الجدول. رقم Argon2id حد أدنى، وزيادة الذاكرة مقابل تقليل التكرارات مقايضة مكافئة، فإعداد بـ 47 MiB مع 1 تكرار يوفر أماناً مماثلاً لخط الأساس. أما حد 72 byte في bcrypt فهو اقتطاع فعلي لا قاعدة تحقق: كل ما يتجاوز 72 byte يُهمل بصمت، وهذا مهم إن كنت تقبل عبارات مرور طويلة أو تجزّئ المدخل مسبقاً.
تُراجَع هذه المعاملات كلما تحسن العتاد. اقرأ المصدر لا هذا الجدول عند التنفيذ.
الملح ليس اختيارياً وليس كافياً
الملح قيمة عشوائية فريدة تُخزَّن بجانب كل قيمة تجزئة. غرضه ضيق ومهم: يضمن أن مستخدمَين لهما كلمة المرور نفسها ينتجان قيمتَي تجزئة مختلفتين، وهذا يبطل جداول قوس قزح المحسوبة مسبقاً ويمنع المهاجم من كسر كلمة مرور واحدة والحصول على كل حساب شاركها.
ما لا يفعله الملح هو إبطاء أي أحد. المهاجم الذي يملك قاعدة بياناتك يملك الأملاح أيضاً، لأنها يجب أن تكون قابلة للقراءة للتحقق من عملية دخول. التمليح وحده أمام تجزئة سريعة يعني أن المهاجم يهاجم كل كلمة مرور على حدة بسرعة هائلة، وهو بالضبط الوضع الذي كنت تحاول تفاديه.
البطء يجب أن يأتي من الخوارزمية نفسها. هذا هو جوهر الدالة كثيفة الذاكرة: تستهلك الموارد عن قصد كي يكسب المهاجم المزوّد بعتاد متخصص ميزة أقل بكثير مما كان سيكسبه أمام تجزئة سريعة.
الفلفل، وهو قيمة سرية تُطبَّق على كل كلمة مرور وتُحفظ خارج قاعدة البيانات، يضيف طبقة حقيقية، لأن تسريب قاعدة البيانات وحده يصبح غير كافٍ. وهو يضيف عبئاً تشغيلياً كذلك، إذ يتطلب تدويره إعادة التجزئة عند الدخول التالي، وفقدانه يقفل كل حساب. يستحق العناء في الأنظمة عالية القيمة، ويمكن تجاوزه في معظم الحالات.
الأخطاء التي تعيش سنوات
تجزئة سريعة مع ملح. يبدو استعمال SHA-256 مع ملح تصرفاً مسؤولاً وهو ليس كذلك. السرعة نفسها هي الثغرة.
التشفير بدل التجزئة. التشفير قابل للعكس بحكم تصميمه، أي أن مفتاحاً موجود، ومن يحصل عليه يحصل على كل كلمات المرور نصاً صريحاً. لا ينبغي أن تكون كلمات المرور قابلة للاسترجاع أبداً، بل قابلة للتحقق فقط.
معاملات كلفة تُضبط مرة ولا تُرفع أبداً. قيمة كلفة اختيرت لـ bcrypt في 2015 أضعف بكثير أمام عتاد 2026. ارفعها عند أول دخول ناجح تالٍ، حين يكون النص الصريح بين يديك للحظة ويمكنك إعادة التجزئة.
الاقتطاع أو تقييد المحارف. الحد الأقصى للطول دون 64 محرفاً تقريباً، أو منع محارف بعينها، يشير عادة إلى أن كلمة المرور تُخزَّن بطريقة تهتم بما تحتويه. ولا ينبغي أن تهتم، فأنت تجزّئها على أي حال.
مقارنة تسرّب التوقيت. يجب أن يستعمل التحقق مقارنة بزمن ثابت. دوال المكتبات القياسية تفعل ذلك، وفحوص التساوي المكتوبة يدوياً لا تفعله.
تسجيل كلمة المرور في السجلات. تصل إلى سجل أخطاء أو تتبع طلب أو نظام مراقبة، فتصبح في ثلاثة أماكن ضوابط الوصول فيها أضعف من ضوابط قاعدة البيانات.
ترحيل نظام قائم
لا يمكنك إعادة تجزئة ما لا تملكه، لأنك لا تحتفظ إلا بقيم التجزئة. الطريقة العملية هي الترقية عند تسجيل الدخول.
عندما ينجح مستخدم في المصادقة، تكون كلمة مروره الصريحة في الذاكرة للحظة. تحقق منها مقابل التجزئة القديمة، ثم احسب فوراً قيمة جديدة بالخوارزمية الحالية واستبدل القيمة المخزَّنة. خلال بضعة أشهر تنتقل معظم الحسابات النشطة دون أي تغيير يلحظه المستخدم.
تتبّع الخوارزمية على مستوى كل سجل كي تتعايش الاثنتان، وحدد تاريخاً تُبطَل بعده قيم التجزئة القديمة المتبقية ويضطر أصحابها إلى إعادة التعيين. الحسابات الخاملة ذات التجزئة الضعيفة هي بالضبط ما يريده المهاجم.
لا تغلّف التجزئة القديمة داخل الخوارزمية الجديدة كطريق مختصر. الأمر ينجح، لكنه يترك التجزئة الضعيفة حدّاً أمنياً فعلياً بينما يبدو كل شيء حديثاً.
ما هو أهم من الخوارزمية
التجزئة الصحيحة تحميك حين تتسرب قاعدة البيانات. وهي لا تفعل شيئاً أمام الهجوم الأكثر شيوعاً، وهو أن يسجّل أحدهم الدخول بكلمة مرور حقيقية حصل عليها من مكان آخر.
تحديد معدل المحاولات عند المصادقة، وإتاحة التحقق متعدد العوامل، وفحص كلمات المرور الجديدة مقابل قوائم التسريبات المعروفة، والتنبيه على أنماط حشو بيانات الاعتماد، كلها تعالج ذلك، وكلها أهم في العمل اليومي من الاختيار بين Argon2id وbcrypt. وضوابط أمن واجهات API تنتمي إلى العائلة نفسها من المشكلات.
كلا الأمرين يستحق التنفيذ، والترتيب يستحق الصراحة: أصلح التجزئة مرة واحدة لأنها رخيصة ودائمة، ثم أنفق الجهد المستمر على مسار تسجيل الدخول، فهناك تصل الهجمات فعلاً. وتراجع Mecanik الأمرين معاً ضمن خدمة تحليل أمن التطبيقات.
الأسئلة الشائعة
ما أفضل خوارزمية لتجزئة كلمات المرور في 2026؟ Argon2id، بحد أدنى 19 MiB من الذاكرة و2 تكرار و1 درجة توازٍ. وإن لم تكن متاحة فإن scrypt بإعداد N=2^17 وr=8 وp=1 بديل مقبول، وbcrypt بمعامل كلفة 10 أو أكثر يناسب الأنظمة القديمة، وPBKDF2-HMAC-SHA256 بـ 600,000 تكرار يغطي متطلبات FIPS-140.
هل يكفي تمليح كلمات المرور؟ لا. الملح يضمن أن كلمات المرور المتطابقة تنتج قيم تجزئة مختلفة، فيبطل جداول قوس قزح ويمنع كلمة مرور واحدة مكسورة من فتح كل حساب شاركها. لكنه لا يبطئ المهاجم، لأن الأملاح يجب أن تكون قابلة للقراءة للتحقق من عمليات الدخول. البطء يجب أن يأتي من خوارزمية كثيفة الذاكرة عن قصد.
لماذا لا نستخدم SHA-256 لكلمات المرور؟ لأن سرعتها هدف تصميمي، والسرعة هي بالضبط ما تحاول حرمان المهاجم الذي يحمل قاعدة بياناتك منه. دالة التجزئة عامة الغرض ليست دالة تجزئة لكلمات المرور، مهما تكرر تطبيقها وسواء أُضيف إليها ملح أم لا.
هل لدى bcrypt حد لطول كلمة المرور؟ نعم، 72 byte، وكل ما يتجاوز ذلك يُقتطع بصمت بدل أن يُرفض. وهذا مهم إن كنت تقبل عبارات مرور طويلة أو تجزّئ المدخل قبل تمريره إلى bcrypt، لأن الاقتطاع يحدث دون أي خطأ يشير إليه.
كيف أرقّي تجزئات كلمات المرور دون كلمات مرور المستخدمين؟ عند تسجيل الدخول. حين يصادق المستخدم تحتفظ بنصه الصريح للحظة، فتحقق منه مقابل التجزئة القديمة وأعد التجزئة فوراً بالخوارزمية الحالية. تتبّع الخوارزمية على مستوى كل سجل كي تتعايش الاثنتان، وحدد تاريخاً تُبطَل بعده قيم التجزئة القديمة المتبقية ويضطر أصحابها إلى إعادة التعيين.
التعليقات