MD5 أم SHA-1 أم SHA-256: أي خوارزمية تجزئة تستخدم؟
استخدم SHA-256 في كل ما يتعلق بالأمان؛ أما MD5 وSHA-1 فمقبولتان فقط حيث لا يكسب أحد شيئًا من تزوير بصمة مطابقة.
تؤدي MD5 وSHA-1 وSHA-256 المهمة نفسها: تحوّل مدخلًا بأي طول إلى بصمة قصيرة ثابتة الطول تُسمّى الملخّص (digest). المدخل نفسه يعطي البصمة نفسها دائمًا، وتغيير بت واحد فيه يغيّر النتيجة كلها. وتختلف الخوارزميات الثلاث في طول البصمة وفي السرعة، والأهم من ذلك في سؤال واحد: هل يستطيع أحد أن يُنتج عمدًا مدخلين مختلفين لهما البصمة نفسها؟ في MD5 وSHA-1 حدث ذلك علنًا، أما في SHA-256 فلم يحدث.
الخوارزميات الثلاث في لمحة
| MD5 | SHA-1 | SHA-256 | |
|---|---|---|---|
| طول البصمة | 128 بت، أي 32 محرفًا ست عشريًا | 160 بت، أي 40 محرفًا ست عشريًا | 256 بت، أي 64 محرفًا ست عشريًا |
| سنة النشر | 1992 (RFC 1321) | 1995 (FIPS 180-1) | 2001، ضمن عائلة SHA-2 |
| التصادمات | عملية منذ 2004 | عملية منذ 2017 | لا يوجد هجوم معروف |
| إيجاد مدخل لبصمة معيّنة | لا يوجد هجوم عملي | لا يوجد هجوم عملي | لا يوجد هجوم عملي |
| تصلح اليوم لـ | مجاميع اختبارية لا علاقة لها بالأمان، ومفاتيح التخزين المؤقت | التوافق مع الأنظمة القديمة فقط | الخيار الافتراضي لأي عمل جديد |
هذه هي البصمات الكاملة للبايتات الخمسة hello كما تطبعها الأوامر md5sum وsha1sum وsha256sum. ويعرض مولّد التجزئة القيم نفسها جنبًا إلى جنب، ومعها SHA-384 وSHA-512، سواء لنص أو لملف يصل حجمه إلى 50 ميغابايت.
MD5 5d41402abc4b2a76b9719d911017c592
SHA-1 aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
SHA-256 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
ما الذي تضيفه البتات الإضافية
يحدّد طول البصمة كلفة الهجوم العام، أي الهجوم الذي يعامل الدالة كصندوق أسود لا يعرف ما بداخله. فبسبب مفارقة عيد الميلاد، يتطلب إيجاد أي مدخلين متصادمين نحو 2^(n/2) محاولة لبصمة طولها n بت: أي 2^64 في MD5، و2^80 في SHA-1، و2^128 في SHA-256. أما إيجاد مدخل يطابق بصمة محدّدة بعينها، وهو ما يُسمّى الصورة الأولية (preimage)، فيتطلب نحو 2^n محاولة.
لكن هذه الأرقام لا تصح إلا ما دام التصميم خاليًا من الطرق المختصرة. ولكلٍّ من MD5 وSHA-1 طرق مختصرة لإيجاد التصادمات، ولهذا لم يعد طول البصمة فيهما يروي القصة كاملة. أما SHA-256 فلا يُعرف لها طريق مختصر، والرقم 2^128 أبعد بكثير من أي قدرة حوسبية موجودة اليوم.
كيف كُسرت MD5 وSHA-1
هجوم التصادم لا يسمح لأحد بعكس التجزئة. ما يسمح به هو أن يُعدّ المهاجم مسبقًا مدخلين مختلفين يشتركان في بصمة واحدة، ثم يجعل أحدهما موضع ثقة ويضع الآخر مكانه. والنوع الخطير منه هو التصادم ذو البادئة المختارة (chosen-prefix)، إذ يختار المهاجم بدايتين لهما معنى، كشهادتين تحملان اسمين مختلفين، ثم يحسب بايتات إضافية تجعل البصمتين متساويتين.
- MD5، عام 2004: نشرت الباحثة Xiaoyun Wang وزملاؤها تصادمات عملية في MD5.
- MD5، عام 2008: استخدم فريق من الباحثين تصادمًا ذا بادئة مختارة في MD5 لإنشاء شهادة مزيّفة لجهة تصديق (CA) كانت المتصفحات ستثق بها، لأن جهة تصديق تجارية كانت لا تزال توقّع الشهادات باستخدام MD5.
- MD5، عام 2012: استخدمت البرمجية الخبيثة Flame تصادمًا في MD5 لتزوير شهادة توقيع برمجيات تابعة لمايكروسوفت.
- SHA-1، عام 2017: أعلنت Google وCWI Amsterdam عن هجوم SHAttered: ملفا PDF مختلفان لهما بصمة SHA-1 نفسها. وذكر الفريق أن الحساب استغرق نحو 6,500 سنة من وقت المعالجات المركزية (CPU) و110 سنوات من وقت المعالجات الرسومية (GPU).
- SHA-1، عام 2020: نشر Gaëtan Leurent وThomas Peyrin تصادمًا عمليًا ذا بادئة مختارة في SHA-1، واستخدماه لانتحال مفتاح PGP.
توقفت المتصفحات عن قبول شهادات TLS الموقّعة بـ SHA-1 في 2017، وأعلن NIST في ديسمبر 2022 وجوب التخلص من SHA-1 كليًا بحلول نهاية 2030. ومع ذلك لا يوجد لأيٍّ من MD5 أو SHA-1 هجوم عملي على الصورة الأولية: فمن يملك البصمة وحدها لا يستطيع إيجاد مدخل ينتجها. ولهذا ما زالت الخوارزميتان صالحتين لكشف التلف العرضي.
السرعة: قياس لا افتراض
كثيرًا ما تُوصف MD5 بأنها الخوارزمية السريعة. لذلك جزّأنا الكمية نفسها من البيانات العشوائية، 256 ميغابايت، باستخدام Node 24 (OpenSSL 3.5) على حاسوب مكتبي واحد، وكررنا القياس ثلاث مرات لكل خوارزمية:
| الخوارزمية | الإنتاجية على ذلك الجهاز |
|---|---|
| SHA-1 | نحو 1,000 ميغابايت في الثانية |
| MD5 | نحو 730 ميغابايت في الثانية |
| SHA-512 | نحو 690 ميغابايت في الثانية |
| SHA-256 | نحو 460 ميغابايت في الثانية |
هذا الترتيب يتبع المعالج. فالمعالج المستخدم هنا يفتقر إلى امتدادات مجموعة تعليمات SHA، أما المعالجات التي تملكها فتسرّع SHA-1 وSHA-256 عتاديًا، وعندها قد تتفوق SHA-256 على MD5. وتفوقت SHA-512 هنا على SHA-256 لأنها تعمل على كلمات بطول 64 بت. ومع المدخلات القصيرة يختفي الفرق تقريبًا: استغرقت مليون عملية تجزئة لعنوان بريد إلكتروني قصير ما بين 1.8 و2.1 ثانية مع كلٍّ من MD5 وSHA-1 وSHA-256، لأن الكلفة الثابتة لكل استدعاء تفوق كلفة التجزئة نفسها. الخلاصة أن السرعة لا تكاد تكون أبدًا سببًا حقيقيًا لاختيار MD5.
ما الذي ما زالت كل خوارزمية تصلح له
- MD5: كشف التلف العرضي، وإزالة التكرار بين ملفاتك أنت، ومفاتيح التخزين المؤقت وقيم ETag، والتخاطب مع الأنظمة القديمة التي تتوقعها. ولا تستخدمها أبدًا للتواقيع أو الشهادات أو لفحوص السلامة التي قد يكون فيها المهاجم هو من يقدّم الملف.
- SHA-1: الأنظمة القائمة التي لا تستطيع تغييرها بعد. فقد ظل Git طويلًا يسمّي كائناته بـ SHA-1، عبر تنفيذ مُحصَّن يكتشف هجمات التصادم المعروفة، وهو يدعم أيضًا مستودعات تستخدم SHA-256. أما HMAC-SHA1، وهي الخوارزمية الافتراضية خلف رموز تطبيقات المصادقة بنظام TOTP، فلا تتأثر بهجمات التصادم.
- SHA-256: المجاميع الاختبارية للتنزيلات، والتواقيع الرقمية، والشهادات، وHMAC، والعنونة بحسب المحتوى، وكل ما هو جديد. استخدم مولّد SHA-256 حين يجب أن يصمد المجموع الاختباري أمام التلاعب، واحتفظ بـ مولّد MD5 للقيم القديمة التي ما زلت تحتاج إلى مطابقتها.
تريد التحقق من ملف نزّلته؟ تحسب أداة التحقق من المجموع الاختباري للملفات بصمة الملف محليًا على جهازك، وتخبرك بالخوارزمية التي يطابقها المجموع الاختباري الذي تلصقه.
لا تصلح أي منها لتخزين كلمات المرور
صُمّمت الخوارزميات الثلاث لتكون سريعة، والسرعة هي بالضبط ما يريده مهاجم يخمّن مليارات كلمات المرور. والملح (salt) يُبطل الجداول المحسوبة مسبقًا، لكنه لا يبطئ التخمين نفسه. أما تخزين كلمات المرور فيحتاج إلى دالة بطيئة عن قصد، ويُفضَّل أن تكون كثيفة الاستهلاك للذاكرة (memory-hard). وهذه أزمنة قسناها على الجهاز نفسه المذكور أعلاه:
| الدالة وإعداداتها | الزمن لكل كلمة مرور |
|---|---|
| SHA-256، استدعاء واحد من Node | نحو 2.5 ميكروثانية |
| Argon2id، ذاكرة 19 MiB، تكراران، مسار واحد (lane) | نحو 33 ملّي ثانية |
| PBKDF2-HMAC-SHA256، عدد التكرارات 600,000 | نحو 270 ملّي ثانية |
| scrypt، N=2^17، r=8، p=1 | نحو 310 ملّي ثانية |
هذه الإعدادات هي الحدود الدنيا الواردة في دليل OWASP Password Storage Cheat Sheet، الذي يوصي أولًا بـ Argon2id، ثم scrypt، ثم bcrypt بمعامل عمل 10 أو أكثر للأنظمة القديمة، ثم PBKDF2 حيث يُشترط الامتثال لمعيار FIPS-140. واعتمد على واجهة تجزئة كلمات المرور التي يوفرها إطار العمل لديك، بدل أن تركّب واحدة بنفسك من دالة تجزئة عادية.
HMAC: حين تحتاج التجزئة إلى مفتاح
إن أردت إثبات أن رسالة صدرت عن طرف يملك سرًا، فلا تحسب sha256(secret + message). فالخوارزميات MD5 وSHA-1 وSHA-256 كلها معرّضة لهجوم تمديد الطول (length extension): معرفة بصمة رسالة واحدة تتيح للمهاجم حساب بصمة صالحة للرسالة نفسها بعد إلحاق بيانات إضافية بها، دون أن يعرف السر. ويتجنب HMAC (RFC 2104) هذه المشكلة. وHMAC-SHA256 هو الخيار المعياري، وكل الأسطر التالية تطبع القيمة نفسها:
// Node.js
crypto.createHmac('sha256', 'secret').update('hello').digest('hex')
# Python
hmac.new(b'secret', b'hello', hashlib.sha256).hexdigest()
// PHP
hash_hmac('sha256', 'hello', 'secret')
// 88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0b
وقارن قيم HMAC بدالة ثابتة الزمن مثل crypto.timingSafeEqual أو hmac.compare_digest أو hash_equals، لا بالمعامل ==.
التجزئة من سطر الأوامر وفي الشيفرة
# Linux (coreutils)
md5sum file.iso
sha1sum file.iso
sha256sum file.iso
# macOS
md5 file.iso
shasum -a 1 file.iso
shasum -a 256 file.iso
# Windows PowerShell
Get-FileHash file.iso -Algorithm MD5
Get-FileHash file.iso -Algorithm SHA1
Get-FileHash file.iso # SHA256 is the default
# Any system with OpenSSL
openssl dgst -sha256 file.iso
# Hashing a string: printf adds no newline, echo does
printf '%s' hello | sha256sum # 2cf24dba5fb0a30e...
echo hello | sha256sum # 5891b5b522d5df08...
في PowerShell تكون SHA256 هي الخوارزمية الافتراضية حين لا تحدد غيرها. ولاحظ السطرين الأخيرين: printf لا يضيف سطرًا جديدًا إلى النص بينما يضيفه echo، ولهذا تختلف البصمتان. وفي المتصفح تدعم crypto.subtle.digest() خوارزميات SHA-1 وSHA-256 وSHA-384 وSHA-512 لكنها لا تدعم MD5، وطلب MD5 منها يرمي الخطأ NotSupportedError. ولهذا تحسب أدوات المتصفح، ومنها أدوات هذا الموقع، بصمة MD5 بتنفيذ منفصل مكتوب بـ JavaScript.