إجراء عمليّ لتمييز طريقة الـ hash من تمثيلها النصّيّ
· آخر تحديث: · 小村 豪 · hash, الأمن, كلمة المرور, الاستفادة من الأصول القائمة, التحقيق التقنيّ
سجل التعديلات (3 تحديثات، آخر تحديث 3 Sep، 2026)
سجل بالتغييرات التي أُجريت على هذا المقال. وحيثما حُفظت نسخة سابقة، تبقى متاحة للقراءة عبر رابط دائم يحمل معرّف DOI.
- أُضيفت روابط الاستشارة الموجودة في الأصل الياباني (consultation_services). ولم يتغيّر نصّ المقالة نفسه. قراءة النسخة السابقة لهذا التحديث (DOI: 10.5281/zenodo.22240912)
- أُعيدَت الترجمة العربية كترجمة كاملة عن النص الياباني الأصلي، وأُضيفَت خريطة المعرفة.
- أعيدت الترجمة كترجمة كاملة عن النص الياباني الأصلي. كانت النسخة العربية السابقة مختصراً يسقط أبواباً وجداول ورسوم Mermaid وتعليقات الأشكال وFAQ. أُعيدت هذه العناصر وفق الأصل الياباني، والادّعاءات التقنية مطابقة للنسخة اليابانية.
- النشر الأول
الاستشهاد بهذا المقال(DOI: 10.5281/zenodo.21621489)
هذا المقال محفوظ على Zenodo. يرد أدناه معرّف DOI الذي يشير دائمًا إلى أحدث نسخة، ومعرّف DOI المثبَّت على النسخة التي تقرؤها.
小村 豪 (2026). إجراء عمليّ لتمييز طريقة الـ hash من تمثيلها النصّيّ. شركة كومورا سوفت ذ.م.م.. https://doi.org/10.5281/zenodo.21621489 https://comcomponent.com/ar/blog/2026/04/10/000-hash-format-identification/
- DOI (أحدث نسخة)
- 10.5281/zenodo.21621489
- DOI (هذه النسخة)
- 10.5281/zenodo.22279946
كثيراً ما نحتاج إلى الحكم على «ما هذا الـ hash؟» عند رؤية سلسلة مثل 5f4dcc3b5aa765d61d8327deb882cf99 أو $2b$12$... متبقّية في السجلّات أو في DB. في ترحيل نظام قائم، وتحقيق طريقة المصادقة، وتحليل السجلّات، والتكامل مع نظام طرف ثالث، ليس من النادر أن يتوقّف العمل عند هذه النقطة.
غير أنّ الخطر هنا هو الجزم بناءً على الطول وحده.
أن تنظر إلى سلسلة hex من 64 خانة وتقول «هذا SHA-256» حكم متعجّل. SHA3-256 وSHA-512/256 وBLAKE2s-256 والمخرج الافتراضيّ بحجم 32-byte لـ BLAKE3 يمكن أن تعطي الطول نفسه. على العكس، فإنّ صيغ الحفظ التي تتضمّن الـ prefix والمعاملات مثل $2b$ أو $argon2id$ يمكن تحديدها بدقّة عالية من السلسلة وحدها.
في هذا المقال نستعمل كلمة hash بمعنى واسع: لا يقتصر الأمر على message digest مثل MD5 / SHA-2 / SHA-3، بل يشمل أيضاً التمثيلات النصّيّة لحفظ كلمات المرور مثل bcrypt / scrypt / Argon2 / PBKDF2.
المحتوى منظَّم استناداً إلى الوثائق الرسميّة المنشورة حتّى أبريل 2026 من RFC وNIST وLinux crypt(5) وApache وDjango وSpring Security.
القرّاء المستهدفون من يتولّى ترحيل نظام قائم، أو تحقيق طريقة المصادقة، أو تحليل السجلّات، ويريد فصل «سلسلة تشبه الـ hash» التي بين يديه. يكفي كمعرفة مسبقة أن تعرف ما تمثيل hex وما Base64.
علماً بأنّ إجراءات هذا المقال تُستعمل فقط على سلاسل في بيئة تديرونها أنتم، أو في بيئة صُرِّح لكم بالتحقيق فيها. استخراج password hash لحساب شخص آخر، أو تحليل hash في نظام بلا صلاحية، لا يُبرَّر حتّى لو كان الغرض تحقيقاً. أوامر التحقّق الواردة لاحقاً تفترض حساباً اختباريّاً أو عيّنة صنعتموها بأنفسكم.
جدول المحتويات
- الخلاصة أوّلاً
- جداول التحديد بنظرة واحدة
- إجراء التحديد في العمل الفعليّ
- أخطاء التحديد الشائعة
- ترتيب التحقّق عند الرغبة في التثبيت 100%
- الخلاصة
- الخدمات التي يتّصل بها هذا الموضوع
- المراجع
في المخطّط، يشير الخطّ المتّصل إلى علاقة قائمة دائماً، ويشير الخطّ المتقطّع إلى علاقة مشروطة (شروط قيامها مذكورة في شرح كلّ علاقة في الصفحة التفصيليّة). القائمة الكاملة للعلاقات (المجموع 27، مع الأدلّة ودرجة اليقين) وتعريفات المفاهيم الرئيسة مجمّعة في صفحة تفاصيل خريطة المعرفة (باليابانية). البيانات: JSON-LD / Turtle
1. الخلاصة أوّلاً
نلخّص أوّلاً بإيجاز.
-
صيغ الحفظ التي تحمل prefix أو فاصلاً يمكن تحديدها إلى حدّ بعيد من السلسلة وحدها. مثال:
$argon2id$...,$2b$...,$5$...,$6$...,{SHA}...,pbkdf2_sha256$... -
مجرّد سلسلة hex مجرّدة أو Base64 لا تتجاوز عادةً «تضييق المرشّحين». مثال:
32 hex قد تكون MD5، لكنّها قد تكون من MD4 أو من تجزئة NT -
مجموعة المحارف لا تقلّ أهمّيّة عن الطول. وجود
+/=يدلّ على Base64 وفق RFC 4648، ووجود.مع فاصل$يدلّ على عائلةcrypt(3)، وهذا النوع من التمييز فعّال. -
إذا أردنا تثبيتاً 100% فلا بدّ من السياق. هل المصدر
/etc/shadowأم.htpasswdأمauth_userفي Django أم Spring Security؟ يتغيّر الحديث بحسب ذلك.
باختصار، «الطرق التي يمكن تحديدها بالسلسلة وحدها» و«الطرق التي لا تتجاوز السلسلة وحدها مرحلة المرشّحين» شيئان مختلفان. إن فصلنا بينهما في التفكير، يتغيّر سير التحقيق.
2. جداول التحديد بنظرة واحدة
قبل قراءة الجداول، نرتّب أربعة أسماء «للصيغة» تظهر في هذا المقال. تُستعمل في سياقات متشابهة، لكنّ ما تشير إليه مختلف.
| المصطلح | الاسم الكامل | ماذا يعني |
|---|---|---|
crypt(3) |
- | دالّة hash لكلمات مرور Unix ذاتها. اسم دالّة في مكتبة C، وتُكتب هكذا لأنّها في الفصل 3 من صفحات man (دالّات المكتبة) |
crypt(5) |
- | صفحة man التي تصف صيغة السلسلة التي تقرأها تلك الدالّة وتكتبها. الفصل 5 من man (صيغ الملفّات)، وهي موضع كتابات مثل $6$salt$hash |
| MCF | Modular Crypt Format | اسم شائع لطريقة الكتابة التي «تضع $id$ في المقدّمة لتبيّن الطريقة». ليست مواصفة واحدة مكتوبة، بل تسمية ترسّخت عرفاً مع توسّع تنفيذات crypt(3) |
| PHC string format | Password Hashing Competition string format | مواصفة أعادت ترتيب MCF. تحدّد حتّى كتابة الإصدار والمعاملات، كما في $argon2id$v=19$m=65536,t=3,p=4$salt$hash |
باختصار، crypt(3) دالّة، وcrypt(5) مواصفة صيغة مخرجاتها، وMCF الاسم الشائع لتلك الصيغة، وPHC string format إعادة تدوين لها. عندما تقول الجداول لاحقاً «PHC string format» أو «عائلة crypt»، فاقرأها بهذا الفصل.
2.1 ما يمكن تحديده تقريباً عبر الـ prefix أو علامات الصيغة
«قوّة التحديد» في الجدول تعني ما يلي.
- قويّة: يمكن تحديدها تقريباً من السلسلة وحدها
- متوسّطة: يمكن تضييق المرشّحين كثيراً، لكن يجب الانتباه إلى اختلافات التنفيذ
- ضعيفة: لا يمكن الجزم اعتماداً على الطول أو المظهر فقط
| ملامح المظهر | الطريقة المرجَّحة أوّلاً | قوّة التحديد | ملاحظة | مثال |
|---|---|---|---|---|
$argon2id$... |
Argon2id | قويّة | PHC string format. غالباً ما تتبعه v=, m=, t=, p= |
$argon2id$v=19$m=65536,t=3,p=4$MDEyMzQ1Njc4OWFiY2RlZg$uKZLaN6muIyoyIYr5waqw3y+zaDbe9aLSPj6Ln/rbz4 |
$argon2i$... |
Argon2i | قويّة | كما أعلاه | $argon2i$v=19$m=65536,t=3,p=4$MDEyMzQ1Njc4OWFiY2RlZg$Kx1koF/7n8EytGJYTS5krh+ag+FlG5ksM4xOsjOSDvo |
$argon2d$... |
Argon2d | قويّة | كما أعلاه | $argon2d$v=19$m=65536,t=3,p=4$MDEyMzQ1Njc4OWFiY2RlZg$HLIGA+T1bwK8akx3LGOco+Df+PvxX6cIXhycO7O7t6c |
$2a$... / $2b$... / $2y$... |
bcrypt | قويّة | cost من خانتين + alphabet عائلة crypt | $2b$12$9YQ2u/e5Y/ArOnG.gJKxK.0makLATcYLP1q.Nsabzrw7XErYCfoYO |
$1$... |
md5crypt | قويّة | صيغة حفظ كلمة مرور MD5 من عائلة Unix | $1$vA7mQ9xZ$Erz32JUFnZ9991KdU5.N3. |
$5$... |
sha256crypt | قويّة | ليس plain SHA-256 | $5$rounds=5000$N3v8Kx2Lq9Rt$uOTla5GAHaRH2aHlUSjkrZUBCuFiahQZ36O/seB39r3 |
$6$... |
sha512crypt | قويّة | ليس plain SHA-512 | $6$rounds=5000$N3v8Kx2Lq9Rt$6LUcSUAELX3aC/.60pTB.TFLTQi1mOGRCwKqNCqtRSaXjorxj01HJ9oNni97Kci1uDt7a/Kn4t3OS20Dw/.vi1 |
$7$... |
scrypt (عائلة crypt) | قويّة | يُرى في تنفيذات Linux crypt(5) |
$7$CU..../....k2XAnEHBqQ1Ct2aMXFKNa/$y3Q0e/UlCHacIGWQshgvvz6UIbP.BCja.5BfVWP2Ml8 |
$y$... |
yescrypt | قويّة | يُرى في توزيعات Linux الأحدث | $y$j9T$k2XAnEHBqQ1Ct2aMXFKNa/$OVYXzjlkiQpWT/F1CUE0JrvV4phLY8FB.ofDttnrSQ7 |
$apr1$... |
Apache APR1-MD5 | قويّة | كثيراً ما يُرى في .htpasswd |
$apr1$vA7mQ9xZ$ZE64.ohiyK11sPZmtnJZQ. |
{SHA}... |
تمثيل Base64 لـ SHA-1 digest | قويّة | كثيراً ما يُرى في عائلة Apache / LDAP | {SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE= |
{SSHA}... |
salted SHA-1 | قويّة | عائلة LDAP | {SSHA}/OczD0GNNkOAUPbYhA3L9fjmcyBCbHVlTWVzYTQyIQ== |
{MD5}... / {SMD5}... |
MD5 / salted MD5 | قويّة | عائلة LDAP | {MD5}X03MO1qnZdYdgyfeuILPmQ=={SMD5}fOn1rOv4ZH0OrO/KT9H0fEJsdWVNZXNhNDIh |
pbkdf2_sha256$... |
PBKDF2-HMAC-SHA256 | متوسّطة إلى قويّة | تنفيذات مثل Django تضع اسم الصيغة في المقدّمة | pbkdf2_sha256$600000$N3v8Kx2Lq9Rt$CLxGB+zTiV1IdOt2y4m9JpaAONzHuRTOd96xKQwRQAs |
{bcrypt}$2b$... |
bcrypt | قويّة | مغلَّف بـ {id} الخاصّ بـ Spring Security |
{bcrypt}$2b$12$9YQ2u/e5Y/ArOnG.gJKxK.0makLATcYLP1q.Nsabzrw7XErYCfoYO |
{pbkdf2}... / {scrypt}... |
طرق ملصقة بعلامة التنفيذ | متوسّطة إلى قويّة | في Spring Security وغيره، نميّز صيغة الغلاف قبل الخوارزميّة الأساسيّة | {pbkdf2}sha256$600000$Qmx1ZU1lc2E0MiE$4eNuai1qNkgs1kXz3+tBUMzAexVsSUz9SrQKEhbk0Cw{scrypt}ln=14,r=8,p=1$Qmx1ZU1lc2E0MiE$xAgBRhXbMtHB1UHUR0br5bI+1XdXWKbwauiFv5VRQBY |
نقطة هذا الجدول أنّ الصيغ التي يكون لمحارفها الأولى معنى تكون قويّة.
وبالأخصّ ما يُفصَل بـ $...$، فاحتمال أن يكون من عائلة Unix crypt(3) / MCF / PHC مرتفع، والنظر إلى الـ prefix قبل الطول هو الأسرع.
2.2 جدول تضييق المرشّحين بالطول لـ hex / Base64 المجرَّد
هذا الجدول لرؤية «مجرّد سلسلة digest» بلا prefix.
في التمثيلات التي تختلط فيها : أو - أو فراغات، نزيل أوّلاً الفواصل ونعدّ الطول.
| طول البايتات الخام | عدد محارف hex | عدد محارف Base64 (مع = / بدون) |
المرشّحون الرئيسيّون | مثال |
|---|---|---|---|---|
| 4 | 8 | 8 / 6 | checksum مثل CRC32 | cbf43926 |
| 16 | 32 | 24 / 22 | عائلة MD5، MD4، تجزئة NT (على أساس MD4) | 5f4dcc3b5aa765d61d8327deb882cf99 |
| 20 | 40 | 28 / 27 | SHA-1، RIPEMD-160 | da39a3ee5e6b4b0d3255bfef95601890afd80709 |
| 28 | 56 | 40 / 38 | SHA-224، SHA-512/224، SHA3-224 | d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f |
| 32 | 64 | 44 / 43 | SHA-256، SHA-512/256، SHA3-256، BLAKE2s-256، المخرج الافتراضيّ بحجم 32-byte لـ BLAKE3 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 |
| 48 | 96 | 64 / 64 | SHA-384، SHA3-384، BLAKE2b-384 | 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b |
| 64 | 128 | 88 / 86 | SHA-512، SHA3-512، BLAKE2b-512، Whirlpool | cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e |
كيف تُقرأ عمود «عدد محارف Base64»: العمود يضع حالتين جنباً إلى جنب: مع حشو = / بدونه. Base64 وفق RFC 4648 تُحاذى على وحدات من 4 محارف، لذلك لا تُلحق = واحد أو اثنان في النهاية إلّا حين لا يكون طول البايتات الخام مضاعفاً لـ 3. في JWT أو التضمين في URL كثيراً ما تُسقط هذه =، فقد يظهر الـ digest نفسه بطول 43 محرفاً وبطول 44. بالمقابل، عند 48 بايتاً مثلاً (مضاعف لـ 3) لا يحدث حشو، فيتكرّر الرقم نفسه 64 / 64. عند تضييق المرشّحين بالطول، قابل دائماً الرقمين معاً.
المهمّ هنا أنّ تطابق الطول لا يعني تحديد الطريقة بصورة قطعيّة.
وبالأخصّ، hex بطول 32 / 64 / 128 يحتمل مرشّحين كثيرين، والجزم بناءً على ذلك وحده يجعل احتمال الخطأ كبيراً.
2.3 أمثلة شائعة يسهل الالتباس فيها
| كيف تبدو السلسلة | الحكم المتعجِّل المعتاد | الرؤية الصحيحة | مثال |
|---|---|---|---|
5f4dcc3b5aa765d61d8327deb882cf99 |
MD5 مؤكّد | تبدو MD5، لكنّها قد تكون MD4 أو تجزئة NT، أو استخداماً خاصّاً للتطبيق لـ MD5 | 8846f7eaee8fb117ad06bdd830b7586c |
64 hex مثل 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 |
SHA-256 مؤكّد | مرشّح SHA-256، لكنّ SHA3-256 / SHA-512/256 / BLAKE2s-256 / BLAKE3 محتملة | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 |
$6$rounds=5000$salt$hash |
تمثيل hex لـ SHA-512 | ليس كذلك، بل سلسلة password hash اسمها sha512crypt | $6$rounds=5000$N3v8Kx2Lq9Rt$6LUcSUAELX3aC/.60pTB.TFLTQi1mOGRCwKqNCqtRSaXjorxj01HJ9oNni97Kci1uDt7a/Kn4t3OS20Dw/.vi1 |
{SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE= |
شيء من نوع «SHA» | في سياق Apache / LDAP غالباً ما يدلّ على SHA-1 digest مرمَّز بـ Base64 | {SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE= |
{bcrypt}$2b$12$... |
طريقة خاصّة اسمها {bcrypt} |
bcrypt مغلَّفاً بغلاف Spring Security | {bcrypt}$2b$12$9YQ2u/e5Y/ArOnG.gJKxK.0makLATcYLP1q.Nsabzrw7XErYCfoYO |
3. إجراء التحديد في العمل الفعليّ
من هنا نرتّب كيف نفحص في الممارسة. الترتيب الموصى به هو prefix ← الفواصل ← مجموعة المحارف ← الطول ← السياق.
3.1 ابدأ بالنظر إلى الرموز الأولى
من المحرف الأوّل إلى نحو عشرة محارف، يمكن تضييق المرشّحين كثيراً.
-
$argon2id$/$argon2i$/$argon2d$نشكّ بقوّة في PHC string format لـ Argon2. يسهل تتبّع المكوّنات بالنظر إلى عمودمثالفي 2.1. -
$2a$/$2b$/$2y$نشكّ بقوّة في bcrypt. -
$1$/$5$/$6$/$7$/$y$نشكّ في password hash من عائلة Unixcrypt(3). -
{SHA}/{SSHA}/{MD5}/{SMD5}نشكّ في تمثيلات عائلة LDAP / Apache. -
{bcrypt}/{pbkdf2}/{scrypt}نشكّ في صيغ حفظ تحمل علامة التنفيذ كما في Spring Security.
النصيحة هنا هي النظر ليس فقط إلى «الخوارزميّة الأساسيّة» بل إلى «صيغة الحفظ» أيضاً.
مثلاً $6$ ليس «digest الخاصّ بـ SHA-512»، بل «سلسلة password hash تستعمل SHA-512». الخلط هنا يؤدّي إلى انحراف لاحق في التحقيق.
3.2 انظر إلى عدد محارف الفصل
ثمّ نتفقّد فواصل مثل $, :, {}, ,, =.
-
وجود عدّة
$نشكّ في صيغة تحوي معاملات وsalt وhash معاً. الأمثلة النمطيّة هي Argon2 وbcrypt وsha256crypt وsha512crypt. -
البدء بـ
{name}نشكّ في غلاف يصرّح باسم الطريقة كما في LDAP / Spring Security. -
صيغ مثل
algo:salt:hashأوalgo$iterations$salt$hashنشكّ في صيغ خاصّة بإطار عمل أو تطبيق. المثال النمطيّ هوpbkdf2_sha256$iterations$salt$hashفي Django.
كلّما ازدادت الفواصل في السلسلة، صار تحديد الطريقة أيسر. وعلى العكس، مجرّد كتلة hex أو Base64 وحدها يجعل الأمر مبهماً.
3.3 انظر إلى مجموعة المحارف
مجموعة المحارف لا تقلّ أهمّيّة عن الطول.
تمثيل hex
إن كانت السلسلة مكوّنة فقط من [0-9a-fA-F]، فأوّل ما نشكّ فيه هو تمثيل hex.
في هذه الحالة عدد المحارف ÷ 2 = طول البايتات الخام.
- 32 hex ← 16 bytes
- 40 hex ← 20 bytes
- 64 hex ← 32 bytes
- 128 hex ← 64 bytes
Base64 / Base64url وفق RFC 4648
وجود + / = يدلّ في الغالب على Base64 العاديّ.
وجود - _ يدلّ على Base64url.
قد تُحذف علامة الحشو =، فلذلك يحتمل أن نرى 43 / 44, 86 / 88 كأطوال محتملة.
radix64 من عائلة crypt
إذا ظهرت . و/ وكان الفاصل من نوع $...$، فمن الأنسب الشكّ في alphabet عائلة crypt قبل Base64 الاعتياديّ.
bcrypt وsha256crypt وsha512crypt وmd5crypt وyescrypt وscrypt كلّها تستخدم هذه العائلة من المحارف.
هذه نقطة بسيطة المظهر، لكنّها فعّالة جدّاً.
أن نظنّ «إنّها Base64 تالف لأنّ فيها .» يجعلنا نُغفل bcrypt أو عائلة crypt(3).
3.4 عدّ الطول
بعد تفقّد مجموعة المحارف، نأتي إلى الطول. الفكرة بسيطة.
- في hex:
طول البايتات الخام = عدد المحارف / 2 - في Base64:
عدد المحارف ≒ 4 × ceil(طول البايتات الخام / 3)مع ملاحظة أنّ حذف=للحشو يقصّر الطول من 0 إلى 2 محرفاً
في هذه المرحلة نضيّق المرشّحين. لكن من الآمن عدم القفز إلى الجزم بأنّ 64 hex هي SHA-256 مؤكّدة.
3.5 التثبيت بالسياق
ما يحسم في النهاية هو السياق. وهنا نقترب من 100%.
-
موجود في
/etc/shadowنشكّ في صيغ password hash لـ Linux مثل$y$,$6$,$5$,$1$ -
موجود في
.htpasswdنشكّ في عائلة Apache مثل$apr1$,{SHA}, bcrypt -
في إعدادات Django أو في
auth_user.passwordنشكّ في صيغة Django مثلpbkdf2_sha256$...أوargon2$... -
في جدول مصادقة Spring Security نشكّ في صيغة مع
{id}مثل{bcrypt}...أو{pbkdf2}... -
32 hex قرب تكامل SMB / AD نضع احتمال تجزئة NT (على أساس MD4) في مقدّمة الذهن
في الممارسة، توجد كثيراً مواقف يكون فيها النظر إلى المنتج / إطار العمل / اسم ملفّ الإعداد لمصدر الحفظ أسرع من النظر إلى السلسلة وحدها.
4. أخطاء التحديد الشائعة
4.1 الجزم بأنّ 64 hex = SHA-256
هذا متكرّر بكثرة. طبعاً SHA-256 مرشّح قويّ، لكن توجد عدّة طرق تنتج مخرجاً بحجم 32-byte. SHA3-256 وSHA-512/256 وBLAKE2s-256 والمخرج الافتراضيّ لـ BLAKE3 لها الطول نفسه.
الطول مادّة لتكوين مجموعة المرشّحين، لا مادّة للتثبيت.
4.2 سوء فهم $6$ على أنّه plain SHA-512
$6$... هو prefix sha512crypt.
هذه ليست «hex digest لـ SHA-512»، بل سلسلة password hash تتضمّن salt وعدد rounds.
وبالمثل،
$5$هو sha256crypt$1$هو md5crypt
من اللحظة التي يظهر فيها prefix، لم يعد الأمر «مجرّد digest».
4.3 الظنّ بأنّ {SHA} يعني «إمّا SHA-256 أو SHA-512»
في سياق Apache أو LDAP، لا يعني {SHA} معنىً غامضاً «من عائلة SHA».
بل يدلّ في كثير من الحالات على SHA-1 digest مرمَّز بـ Base64. و{SSHA} هو salted SHA-1.
التعامل مع {SHA} بصورة غامضة على أنّه «شيء من نوع SHA» اعتماداً على المظهر فقط، يجعلنا نخطئ في كود التحقّق ومعالجة الترحيل.
4.4 معاملة password hash و content hash كشيء واحد
«سلسلة الـ hash» نفسها قد تختلف أهدافها.
- digest للتحقّق من سلامة الملفّ
- digest لتوقيع API
- hash / KDF لحفظ كلمة المرور
هذه الثلاثة قد تتشابه في المظهر، لكنّ التعامل معها مختلف. وبالأخصّ password hash، إذ كثيراً ما يضمّ في السلسلة salt وrounds وmemory cost وparallelism. ولا يمكن كشف ذلك بفكر «المقارنة بين digest خامَين».
4.5 نسيان XOF أو digest متغيّر الطول
SHAKE128 / SHAKE256 من نوع XOF، فيمكن اختيار طول المخرج بحرّيّة. BLAKE2 يتيح أيضاً تغيير digest length، وBLAKE3 له extendable output.
أي إنّ افتراض «هذا الطول يعني هذه الطريقة» يخطئ إذا اعتمد كثيراً على digest كلاسيكيّ ثابت الطول.
4.6 معاملة «NTLM» و«تجزئة NT» كأنّهما الشيء نفسه
هذا حديث عن المصطلحات، لكنّه فعّال جدّاً في تحقيقات Windows / AD.
- تجزئة NT: قيمة من 16 بايتاً تُحسب بترميز كلمة المرور UTF-16LE ثمّ تطبيق MD4. تظهر كـ hex بطول 32 خانة، مثل
8846f7eaee8fb117ad06bdd830b7586c. في المواصفة تُعرَّف بـNTOWFv1(Passwd, User, UserDom) = MD4(UNICODE(Passwd)). هذا التعريف وارد كما هو في بند NTLM v1 Authentication من MS-NLMP المذكور في المرجع 13. - NTLM: اسم بروتوكول مصادقة يستعمل تلك القيمة مفتاحاً لتحدٍّ / استجابة. ليس اسم صيغة للسلسلة.
في الميدان يُفهم تعبير «NTLM hash»، لكن عند إسقاط الأمر على جدول التحديد الأدقّ أن نكتب تجزئة NT (على أساس MD4). بهذا الفصل لا يختلط تحديد الصيغة («هل هذه الـ 32 hex هي MD5 أم تجزئة NT؟») بحديث البروتوكول («هل هذا الاتّصال NTLM أم Kerberos؟»).
علماً بأنّ تجزئة NT بلا salt. كلمة المرور نفسها تنتج دائماً الـ 32 hex نفسها، لذا فإنّ «صفوف 32 hex بلا salt في جدول آتٍ من AD» دليل بحدّ ذاته.
5. ترتيب التحقّق عند الرغبة في التثبيت 100%
في الترحيل وتكامل المصادقة، نحتاج أخيراً إلى التثبيت. عندئذٍ يقلّ احتمال الحوادث إذا اتّبعنا الترتيب التالي.
5.1 تحديد مصدر الحفظ
أوّلاً نحدّد من أين أتت السلسلة.
- من shadow الخاصّ بـ Linux؟
- من basic auth الخاصّ بـ Apache / Nginx؟
- من LDAP؟
- من Django / Spring Security؟
- من DB لتطبيق خاصّ؟
غالباً ما تكون مواصفات مصدر الحفظ أقوى من السلسلة وحدها.
5.2 البحث عن «صيغة الحفظ» في الوثائق الرسميّة
ثمّ نبحث ليس عن اسم الخوارزميّة بل عن صيغة الحفظ.
Django password formatSpring Security password storage formatcrypt(5) sha512crypt formatApache htpasswd password formats
استخدام كلمات مفتاحيّة مثل format / storage / encoding يجعل العثور أسرع.
5.3 إن وُجد متن معروف، فجرِّب التحقّق فعليّاً بطرق المرشّحين
إن توفّر حساب اختباريّ أو متن معروف، فإنّ أسرع طريق هو حساب الـ hash فعليّاً بطرق المرشّحين والمقارنة. في password hash، يلزم استخراج salt وrounds من السلسلة وإعادة الحساب.
قالب الإجراء ثلاث مراحل في كلّ طريقة:
- استخرج salt والمعاملات من السلسلة
- أعد الحساب على المتن المعروف بالـ salt والمعاملات نفسها
- انظر هل السلسلة الناتجة تطابق الأصل حرفاً بحرف
التحقّق من digest بلا prefix
نبدأ من «مجرّد digest». تكفي المكتبة القياسيّة في Python 3.
# Python 3.8 以降 / 標準ライブラリのみ
import base64
import hashlib
target = "5f4dcc3b5aa765d61d8327deb882cf99" # السلسلة المراد تمييزها
plain = b"password" # نص واضح معروف
for name in ("md5", "sha1", "sha256", "sha512", "sha3_256", "blake2s"):
digest = hashlib.new(name, plain).digest()
if digest.hex() == target.lower():
print("تطابق hex:", name)
if base64.b64encode(digest).decode() == target:
print("تطابق base64:", name)
في هذا المثال يظهر تطابق hex: md5. الشكل الأساسيّ أن تضع في حلقة for الطرق المرشّحة في جدول 2.2 كما هي.
إن أردت تجزئة NT، تكتب شيئاً مثل hashlib.new("md4", "password".encode("utf-16-le"))، لكنّ Python المربوط بـ OpenSSL 3 يعطّل legacy provider افتراضيّاً، وقد تحصل على unsupported hash type md4. تأكّد من بيئتك أوّلاً.
التحقّق من password hash من عائلة crypt
$1$ / $5$ / $6$ / $apr1$ يمكن إعادة حسابها بتمرير salt إلى openssl passwd. أمثلة جدول 2.1 قابلة لإعادة الإنتاج بهذه الطريقة.
# OpenSSL 3.x
openssl passwd -6 -salt N3v8Kx2Lq9Rt password
# $6$N3v8Kx2Lq9Rt$6LUcSUAELX3aC/.60pTB.TFLTQi1mOGRCwKqNCqtRSaXjorxj01HJ9oNni97Kci1uDt7a/Kn4t3OS20Dw/.vi1
openssl passwd -5 -salt N3v8Kx2Lq9Rt password # sha256crypt
openssl passwd -1 -salt vA7mQ9xZ password # md5crypt
openssl passwd -apr1 -salt vA7mQ9xZ password # Apache APR1-MD5
إن طابق المخرج السلسلة قيد التحديد، تثبّت في تلك اللحظة الطريقة والمتن معاً.
السلاسل التي تحمل rounds= يلزم تمرير تلك القيمة أيضاً. $6$rounds=5000$... قيمة افتراضيّة، فيطابق الـ digest سواء صرّحت بها أم لا، أمّا قيمة مختلفة عن الافتراضيّ مثل rounds=100000 فيجب الحساب بها حتماً.
على Debian / Ubuntu يمكن فعل الأمر نفسه بـ mkpasswd من حزمة whois (بالشكل mkpasswd -m sha512crypt -S N3v8Kx2Lq9Rt password).
التحقّق من bcrypt وArgon2
في bcrypt وArgon2 يُرمَّز salt بأبجديّة خاصّة، لذا أدقّ أن تمرّر السلسلة كاملة إلى verify في المكتبة بدل قصّها يدوياً.
# pip install "passlib[bcrypt]" argon2-cffi
from passlib.hash import argon2, bcrypt
samples = [
(bcrypt, "$2b$12$9YQ2u/e5Y/ArOnG.gJKxK.0makLATcYLP1q.Nsabzrw7XErYCfoYO"),
(argon2, "$argon2id$v=19$m=65536,t=3,p=4$MDEyMzQ1Njc4OWFiY2RlZg$uKZLaN6muIyoyIYr5waqw3y+zaDbe9aLSPj6Ln/rbz4"),
]
for handler, stored in samples:
# identify はその形式かどうか、verify は平文と一致するかを返します
print(handler.name, handler.identify(stored), handler.verify("password", stored))
verify يقرأ cost وrounds وsalt من السلسلة ويعيد الحساب، فلا تحتاج إلى استخراج المعاملات بنفسك. مثال bcrypt أعلاه متنه password فيعيد True.
علماً بأنّ وحدة crypt القياسيّة في Python أُهملت وحُذفت في Python 3.13. من 3.13 فصاعداً عالج عائلة crypt عبر openssl passwd أو passlib.
5.4 ترجمة الطريقة المرشّحة إلى رقم hashcat أو اسم john
حين لا يُعرف المتن وتريد التعامل من جهة الأداة، تحتاج إلى الترجمة لا إلى اسم الطريقة بل إلى المعرّف الذي تستعمله الأداة. هنا كثيراً ما يتعثّر الناس، فنضع جدولاً للأشهر.
| المظهر | الطريقة | وضع hashcat (-m) |
|---|---|---|
| 32 hex | MD5 | 0 |
| 32 hex (من AD) | تجزئة NT | 1000 |
| 40 hex | SHA-1 | 100 |
| 64 hex | SHA-256 | 1400 |
| 128 hex | SHA-512 | 1700 |
$1$... |
md5crypt | 500 |
$apr1$... |
Apache APR1-MD5 | 1600 |
$2a$ / $2b$ / $2y$ |
bcrypt | 3200 |
$5$... |
sha256crypt | 7400 |
$6$... |
sha512crypt | 1800 |
pbkdf2_sha256$... |
Django PBKDF2-HMAC-SHA256 | 10000 |
| صيغة حفظ من عائلة scrypt | scrypt | 8900 |
أرقام الأوضاع تزداد مع الإصدارات، فالطرق الأحدث مثل Argon2 وyescrypt راجعها في قائمة المساعدة على hashcat الذي بين يديك.
John the Ripper يُحدَّد بالاسم لا برقم. ما يفعّله الأصل (1.8.0) هو descrypt، bsdicrypt، md5crypt، bcrypt، LM، AFS، tripcode، dummy، crypt، وكثير ممّا سواها يُضاف في إصدار jumbo. إن لم يكن اسم الطريقة التي تريدها في الأصل، فارجع إلى وثائق jumbo.
ونكرّر: هذه الأدوات تُستعمل فقط على بيئتكم، أو على بيئة صُرِّح لكم بالتحقيق فيها.
5.5 التحقّق من كود التطبيق أو الإعدادات
إذا كان موضوع التحقيق نظاماً داخل شركتنا، فإنّ النظر إلى الكود والإعدادات هو الأكثر تأكيداً في النهاية.
- المكتبات المستخدمة
- إعدادات إطار العمل
- خيارات وقت التوليد
- ترميز الإخراج (hex / Base64 / Base64url / crypt alphabet)
النظر إلى هذه عادةً يحسم الأمر.
5.6 الحفظ بعلامة الطريقة من أجل المستقبل
إن كنّا في موقع التصميم لما هو آتٍ، فاختيار صيغة تتضمّن اسم الطريقة في السلسلة يجعل الترحيل المستقبليّ أسهل بكثير.
- PHC string format لـ Argon2
{id}encodedPasswordفي Spring Securityalgo$iterations$salt$hashفي Django- صيغ عائلة Unix
crypt(3)ذات الـ prefix
عند فعل ذلك، يقلّ ارتباك من ينظر إلى السلسلة لاحقاً. وبالعكس، فإنّ تصميم يخزّن «مجرّد 64 hex» في DB ليس لطيفاً مع الذات المستقبليّة.
6. الخلاصة
عند التمييز بين طرق الـ hash من تمثيلها النصّيّ، يكون التنظيم أسهل بهذا الترتيب.
- هل يوجد prefix؟
- ما محارف الفصل؟
- ما مجموعة المحارف؟
- كم بايتاً يوازي الطول؟
- ما سياق مصدر الحفظ؟
أهمّ نقطتين كالتالي.
- صيغ الحفظ المسبوقة بـ prefix يسهل تحديدها كثيراً
- مجرّد hex / Base64 لا يتجاوز عادةً مجموعة المرشّحين
لذلك يصبح القرار في العمل كما يلي.
- إذا كان
$argon2id$...,$2b$...,$6$...,{SHA}...,pbkdf2_sha256$...، فيمكن التقدّم كثيراً بالسلسلة وحدها - إذا كان مجرّد hex من
32 / 40 / 64 / 128خانة، فلا نجزم بل نعتبره «تضييق المرشّحين» - إذا لزم التثبيت فعلاً، فلا بدّ من النظر إلى منتج مصدر الحفظ وإعداداته وكوده
بهذا الترتيب يصبح التحقيق أسرع كثيراً. وعلى العكس، الجزم بناءً على الطول وحده يسبّب التفافاً صامتاً.
7. الخدمات التي يتّصل بها هذا الموضوع
الاستشارة التقنيّة ومراجعة التصميم
في تحديد طريقة password hash المتبقّية في DB قائمة، وترحيل البنية التحتيّة للمصادقة، وتحقيق سجلّات الأنظمة المختلطة Windows / Web، نحتاج إلى تنظيم لا يقتصر على مظهر السلسلة، بل يمتدّ إلى تنفيذ مصدر الحفظ وسياسة الترحيل. تنظيم العمل من تحديد الطريقة إلى تصميم الترحيل دفعةً واحدة يقلّل الحوادث.
تحقيق الأعطال وتحليل الأسباب
ليس من النادر أن يتعطّل التحقيق عند «لا أعرف ما هذه السلسلة فلا يمكنني التقدّم في التحقّق». فصل أين تتقرّر الطريقة بين السجلّات وملفّات الإعداد ومخطّط DB وكود التطبيق يجعل تحديد السبب أسرع كثيراً.
8. المراجع
- RFC 1321 - The MD5 Message-Digest Algorithm
- NIST FIPS 180-4 - Secure Hash Standard (SHA-1, SHA-2, SHA-512/224, SHA-512/256)
- NIST FIPS 202 - SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions
- PHC string format specification
- Argon2 reference implementation
- RFC 7693 - The BLAKE2 Cryptographic Hash and Message Authentication Code (MAC)
- BLAKE3 C README - default output length and extendable output
- crypt(5) - prefixes and hashed passphrase formats
- Apache HTTP Server 2.4 - Password Formats
- slappasswd(8) - RFC 2307 schemes such as {SHA} and {SSHA}
- Django documentation - example of
pbkdf2_sha256$... - Spring Security -
DelegatingPasswordEncoderstorage format{id}encodedPassword - MS-NLMP: NTLM v1 Authentication -
NTOWFv1(Passwd, User, UserDom) = MD4(UNICODE(Passwd)) - hashcat wiki - example hashes (قائمة أرقام الأوضاع)
- John the Ripper - command line options (الأسماء المتاحة بـ
--format=NAME) - passlib -
PasswordHashAPI (identifyوverify) - openssl-passwd(1) -
-1/-apr1/-5/-6و-salt
مقالات ذات صلة
أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.
اختيار حساب خدمة ويندوز — LocalSystem والحسابات الافتراضية وgMSA
هل ما زلت تشغّل خدمات ويندوز بحساب LocalSystem؟ تقارن هذه المقالة الامتيازات وهويّة الشبكة لـ LocalService وNetworkService والحسابات الاف...
سياسة تدقيق أمن Windows وتحقيق سجلّ الأحداث عمليّاً ── لتصبح نظم المعلومات قادرة على قراءة 4625
دليل عمليّ للإجابة عن «حقِّق في سجلّات فشل تسجيل الدخول». يغطي علاقة سياسة التدقيق الأساسيّة والمفصَّلة، والفئات الفرعيّة التي ينبغي تفعي...
ترحيل ماكرو Excel VBA إلى Power Automate ── النطاق الذي يُستبدل بـ Office Scripts، والنطاق الذي يبقى على VBA
نرتب إمكانية ترحيل ماكرو Excel VBA إلى Power Automate. نشرح النطاق الذي يمكن استبداله بـ Office Scripts، وما لا يُنجز إلا عبر VBA، والقيم...
التعديل الآمن على تطبيق أعمال قديم بلا اختبارات ── ممارسة اختبار التوصيف وإعادة الهيكلة
لإجراء تعديلات آمنة على تطبيق أعمال بلا اختبارات، نشرح خطوات اختبار التوصيف (أسلوب Golden Master) الذي يثبّت السلوك الحالي، وكيفيّة صنع ن...
عندما ترث نظاماً بلا شيفرة مصدريّة ولا مواصفات ── الإجراءات العمليّة لتشغيله وصيانته دون توقّف
نُنظِّم الإجراءات العمليّة لبدء تشغيل وصيانة نظام أعمال بلا شيفرة مصدريّة ولا مواصفات. نشرح صون البيئة العاملة والنسخ الاحتياطيّ، وجرد ال...
أين يتصل هذا الموضوع
ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.
الاستشارات التقنية ومراجعة التصميم
لأنّه مناسب لفحص سجلّات النظام القائم وقاعدة بياناته وأسلوب المصادقة وصيغة التخزين كلٍّ على حدة لتحديد خوارزميّة التجزئة المستخدَمة، ولترتيب قرارات الترحيل أو التحقيق.
الأسئلة الشائعة
أسئلة شائعة حول موضوع هذه المقالة.
- بأيّ ترتيب أنظر لتمييز طريقة الـ hash من سلسلتها؟
- يسهل الترتيب بهذا التسلسل: prefix ثمّ محارف الفصل ثمّ نوع المحارف ثمّ الطول ثمّ السياق. الصيغ التي تحمل معنى في المحارف الأولى سهلة التحديد: $argon2id$ يرجّح Argon2 بقوّة، و$2b$ يرجّح bcrypt، و$5$ هو sha256crypt، و$6$ هو sha512crypt. في المقابل، hex أو Base64 المجرَّد بلا prefix لا يتجاوز تضييق المرشّحين، والحسم النهائيّ يكون بالنظر إلى منتج مصدر الحفظ وإطار العمل والإعدادات.
- هل يجوز الجزم بأنّ سلسلة hex بطول 64 خانة هي SHA-256؟
- الجزم خطر. SHA-256 مرشّح قويّ، لكنّ الطول نفسه ينتج عن SHA3-256 وSHA-512/256 وBLAKE2s-256 والمخرج الافتراضيّ لـ BLAKE3، فلا يميّزها الطول وحده. الطول مادّة لتكوين مجموعة المرشّحين، لا مادّة للتثبيت. إن لزم الحسم فانظر إلى مواصفات مصدر الحفظ، وصيغة الحفظ في الوثائق الرسميّة، والمطابقة بمتن معروف، ثمّ إلى شيفرة التنفيذ والإعدادات.
- هل السلسلة التي تبدأ بـ $6$ هي hash لـ SHA-512؟
- لا. $6$ prefix لصيغة حفظ كلمات مرور Unix اسمها sha512crypt. ليست hex digest لـ SHA-512 ذاتها، بل سلسلة password hash تتضمّن salt وrounds. وبالمثل $5$ هو sha256crypt و$1$ هو md5crypt. ما دام الـ prefix موجوداً فالأمر لم يعد «مجرّد digest»، والخلط هنا يُنحرف تنفيذ الترحيل وكود التحقّق.
- ماذا يبيّن نوع المحارف؟
- نوع المحارف دليل لا يقلّ أهمّيّة عن الطول. إن اقتصرت السلسلة على 0-9a-fA-F فهي تمثيل hex، ونصف عدد المحارف هو طول البايتات الخام. وجود + / = يرجّح Base64 وفق RFC 4648، ووجود - أو _ يرجّح Base64url. إن ظهرت نقطة وشرطة مائلة مع فاصل $، فمن الطبيعيّ الشكّ في alphabet عائلة crypt مثل bcrypt وsha512crypt لا في Base64 العاديّ. معاملة النقطة على أنّها Base64 تالف تُغفل صيغ crypt.
الملف الشخصي للمؤلف
صفحة الملف الشخصي لمؤلف المقالة.
غو كومورا
مؤسّس شركة كومورا سوفت ذ.م.م.
يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.