SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-08-25

كيف تتحقق من سلامة التنزيل باستخدام sha256sum في Linux

تعلّم استخدام sha256sum لمقارنة ملفك مع SHA256SUMS، ثم غيّر بايتاً واحداً لترى رسالة الخطأ ويظهر لك ما يثبته checksum وما لا يثبته.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, August 12, 2026.

تحقّق من التنزيل باستخدام checksum خلال دقيقتين

للتحقّق من التنزيل باستخدام checksum، احسب hash للملف الذي استلمته، ودَع أداة تقارن هذه القيمة مع القيمة التي نشرها المصدّر. ينفّذ sha256sum كلا الجزأين: يطبع digest عند استخدامه منفرداً، ومع -c يقرأ قائمة من قيم digest ويعرض الملفات المطابقة. يطبّق هذا الدليل العملية كاملة على ملف تنشئه، ثم يتلف ذلك الملف عمداً كي تشاهد الفشل يحدث بدلاً من الاكتفاء بقراءة وصفه.

تذكّر جملة واحدة طوال الدليل: يخبرك checksum ما إذا كانت وحدات البايت التي لديك هي وحدات البايت التي أنتجت digest، لكنه لا يخبرك شيئاً عن الجهة التي أنتجتها. يتطلب السؤال الثاني signature وkey تثق بهما. يوضح الجزء الأخير من هذا الدليل بدقة الحد الفاصل بين الأمرين.

أنشئ ملفاً للتدرب عليه

اعمل داخل دليل مؤقت حتى لا يؤثر أي شيء هنا في بقية النظام. تأتي كل الأوامر أدناه من GNU coreutils، وهي مجموعة الأوامر الأساسية الموجودة في أي خادم Ubuntu أو Debian، لذلك لا تحتاج إلى تثبيت أي شيء.

mkdir -p ~/checksum-demo
cd ~/checksum-demo
printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum payload.txt

تحصل على سطر واحد: 64 محرفاً سداسي عشر، ومسافتين، ثم اسم الملف. هذه المحارف الـ64 هي ملخص الملف. شغّل الأمر مرة أخرى، وسيكون السطر مطابقاً، لأن إنشاء الملخصات حتمي: الإدخال نفسه يعطي الناتج نفسه دائماً. غيّر محرفاً واحداً في الملف وشغّل الأمر مرة أخرى، ولن يتغير الملخص قليلاً فقط. سيبدو مختلفاً تماماً، لأن قلب بت واحد في الإدخال يقلب نحو نصف بتات الناتج. هذه الخاصية هي ما يجعل سلسلة من 64 محرفاً بديلاً عملياً عن صورة بحجم 4 GB.

احفظ ملف SHA256SUMS ثم تحقّق منه

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

sha256sum payload.txt > SHA256SUMS
cat SHA256SUMS
sha256sum -c SHA256SUMS

يقرأ sha256sum -c كل سطر من القائمة، ويحسب تجزئة الملف المذكور في ذلك السطر، ثم يقارن بين الملخصين. يعرض التشغيل السليم سطراً واحداً لكل ملف:

payload.txt: OK

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

غيّر بايتاً واحداً وشاهد فشل التحقق

عطّل الملف عمداً الآن. يكتب هذا الأمر بايتاً واحداً عند الإزاحة 5، ويترك كل شيء آخر كما هو، لذلك يحتفظ الملف بطوله واسمه.

printf 'X' | dd of=payload.txt bs=1 seek=5 conv=notrunc status=none
cat payload.txt
sha256sum -c SHA256SUMS

يمثّل conv=notrunc الخيار المهم: من دونه، يقتطع dd الملف عند الموضع الذي يتوقف فيه عن الكتابة، وستختبر نوعاً أوضح بكثير من التلف. يطبع التحقق الآن:

payload.txt: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match

يطبع echo $? القيمة 1. وتعني FAILED أن الملف قُرئ وأن بصمته لم تطابق البصمة الموجودة في القائمة. أعد البايتات الأصلية، وتأكد من أن التحقق يعيد النتيجة OK:

printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum -c SHA256SUMS

هذه هي الممارسة كاملة. يؤدي اختلاف بايت واحد، في أي موضع من الملف، إلى ظهور FAILED. ينتهي التنزيل قبل اكتماله بسبب انقطاع الاتصال، أو يقدّم mirror إصدار الأمس، أو يعيد proxy كتابة الملف أثناء نقله، أو يعيد القرص كتلة تالفة: جميع هذه الحالات تظهر في السطر نفسه.

عندما تسمي القائمة ملفاً لم تنزّله

يسرد ملف SHA256SUMS حقيقي من إحدى التوزيعات كل صورة يصدرها المشروع، وقد نزّلت واحدة منها. أعد إنتاج هذه الحالة هنا.

printf 'a second file\n' > notes.txt
sha256sum payload.txt notes.txt > SHA256SUMS.all
rm notes.txt
sha256sum -c SHA256SUMS.all
payload.txt: OK
sha256sum: notes.txt: No such file or directory
notes.txt: FAILED open or read
sha256sum: WARNING: 1 listed file could not be read

يختلف FAILED open or read عن FAILED، والخلط بينهما يهدر الوقت. يعني FAILED أن البايتات غير صحيحة. ويعني FAILED open or read أن sha256sum لم يحصل على الملف أصلاً، لذلك لم تُجرَ أي مقارنة. في التنزيل الفعلي، يكون السبب المعتاد هو دليل العمل، لأن الأسماء الواردة في القائمة تكون نسبية إلى الدليل الذي تشغّل فيه الأمر. انتقل إلى الدليل الذي يحتوي على الملف ثم شغّل الأمر مرة أخرى. وللتحقق فقط من الملفات الموجودة لديك فعلياً، اطلب ذلك:

sha256sum --ignore-missing -c SHA256SUMS.all

يطبع ذلك payload.txt: OK ويخرج بالرمز 0. إذا لم يكن أي من الأسماء المدرجة موجوداً، فلا ينجح --ignore-missing بصمت عند التعامل مع صفر من الملفات. بل يفيد بأن no file was verified ويخرج برمز غير صفري. وهذا هو السلوك المطلوب، لأن نجاحاً تحقّق من لا شيء هو الفشل الذي لن تلاحظه أبداً.

الصق ملخصاً منشوراً من دون قراءته بصرياً

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

printf '%s  %s\n' "$EXPECTED" payload.txt > payload.sha256
cat payload.sha256
sha256sum -c payload.sha256

توجد مسافتان بين الملخص واسم الملف، ولذلك تحتوي سلسلة التنسيق على مسافتين. هذا هو الشكل الذي يكتبه sha256sum، وهو أيضاً الشكل الذي يحلله -c. الملف الذي يحتوي على ملخص فقط، من دون أي شيء آخر، ليس سطر checksum على الإطلاق. لذلك يرفض الفحص الملف بأكمله باستخدام no properly formatted checksum lines found بدلاً من التخمين بشأن الملف المقصود. تنشر بعض المشاريع النمط المعنون BSD بدلاً من ذلك، وهو SHA256 (payload.txt) = متبوعاً بالملخص. يكتب GNU coreutils هذا الشكل باستخدام sha256sum --tag payload.txt ويقرأه مجدداً باستخدام -c، ولذلك يمكنك حفظ أي من الشكلين.

عندما يتصرف الفحص بطريقة غير متوقعة، افحص القائمة نفسها باستخدام cat -A SHA256SUMS، الذي يضع العلامة $ في نهاية كل سطر ويعرض الأحرف التي لا يمكنك رؤيتها بطريقة أخرى. السطر الذي ينتهي بـ^M$ التقط محرف إرجاع من محرر Windows. يتجاهل GNU sha256sum هذا المحرف الزائد في النهاية، ويطبع OK رغم ذلك. لذلك لا تكون قائمة CRLF هي سبب فشل الفحص، مع أن الأدوات خارج coreutils أقل تسامحاً معها. طبّع النسخة التي تحتفظ بها باستخدام tr -d '\r' < SHA256SUMS > SHA256SUMS.clean.

ماذا يثبت checksum، وماذا لا يثبت؟

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

لا يثبت شيئاً عن جهة التأليف. فـdigest حقيقة تتعلق بوحدات البايت، وليس بالأشخاص. إذا كانت الصفحة نفسها توفّر الملف وdigest، فإن من يستطيع تغيير أحدهما يستطيع تغيير الآخر، ويعني سطر OK لديك أن mirror يطابق نفسه فقط. لذلك، هذه هي القاعدة التي تجعل تشغيل checksums مفيداً: خذ digest من مكان غير المكان الذي أخذت منه الملف. على سبيل المثال، خذ digest من النطاق الرسمي للمشروع عبر TLS (أمن طبقة النقل)، بينما حصلت على image من mirror أو torrent. عندها يجب على المهاجم السيطرة على مكانين بدلاً من مكان واحد. ولا يخبرك ذلك شيئاً عن سلوك وحدات البايت التي تحققت منها بعد تشغيلها، وهي مسألة مستقلة تستحق طرحها بشأن أي شيء ينفّذ إجراءات نيابة عنك، من install script إلى إضافة dsh تعمل بصلاحيات agent الخاص بك.

الخوارزمية مهمة أيضاً. لا توجد collision معروفة في SHA-256 (خوارزمية التجزئة الآمنة، بمخرج 256-bit) حتى August 2026، ولذلك يستخدمها الناشرون. أما MD5 (message digest 5) وSHA-1 فلا يصمدان أمام ذلك: يمكن إنشاء ملفين مختلفين لهما digest MD5 نفسه منذ 2004، وقد نُشرت collision ببادئة مختارة في SHA-1 عام 2020. لا يزال ملف MD5SUMS يكشف التنزيل المبتور، لأن التلف العشوائي ليس collision مصممة. لكنه لا يستطيع إيقاف شخص يحاول خداعك. عندما ينشر المشروع السطرين معاً، استخدم سطر SHA-256.

عندما تصبح التواقيع هي طبقة التحقق

يسدّ التوقيع الفجوة التي يتركها الملخّص. يوقّع الناشر ملف الملخّص بمفتاح خاص، وتتحقق منه باستخدام مفتاحه العام: gpg --verify SHA256SUMS.asc SHA256SUMS. إذا نجح ذلك، فقد جاءت قائمة الملخّصات من الجهة التي تملك ذلك المفتاح. ثم يربط sha256sum -c SHA256SUMS الملف الموجود على قرصك بالقائمة، وتمتد سلسلة التحقق من المفتاح وصولاً إلى البايتات.

تنتقل نقطة الضعف إلى المفتاح. إن جلب المفتاح من الصفحة نفسها التي قدّمت الملف يسلّم كلا الجزأين إلى المهاجم. يتعامل GnuPG مع هذا بوضوح، إذ يعرض التحقق الأول Good signature مع WARNING: This key is not certified with a trusted signature!. يعني Good signature أن الحسابات الرياضية صحيحة. لكنه لا يعني أن المفتاح يعود إلى المشروع الذي تقصده. احصل على بصمة المفتاح من مصدر ثانٍ، مثل وثائق المشروع على نطاق مختلف أو حزمة توزيع تتضمن المفتاح مسبقاً، وقارن البصمة الكاملة بدلاً من آخر ثمانية أحرف. هذه هي العناية نفسها التي يستحقها مفتاح SSH الخاص، للسبب نفسه: المفتاح هو قرار الثقة، وكل ما يأتي بعده يعتمد عليه.

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

مدير الحزم ينفّذ ذلك نيابةً عنك

في Debian وUbuntu، ينفّذ apt هذه السلسلة عند كل عملية تثبيت من دون طلب تأكيد. يحتوي فهرس الحزم على قيمة SHA-256 لكل ملف .deb. ويحتوي ملف Release على قيم التجزئة لملفات الفهرس هذه، بينما يحتوي InRelease على توقيع للقيمة Release، ويُتحقق منه باستخدام المفاتيح الموجودة في /usr/share/keyrings و/etc/apt/trusted.gpg.d. عند انقطاع هذه السلسلة، يوضح apt السبب: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY عندما يكون مفتاح مستودع تابع لجهة خارجية مفقوداً، أو Hash Sum mismatch عندما لا يطابق الفهرس الذي جلبته القيمة الموقعة Release، وهذا يعني عادةً أن خادماً وسيطاً للتخزين المؤقت قدّم ملفاً قديماً أو أنك التقطت خادماً مرآة أثناء مزامنته.

هذا هو المعيار الذي ينبغي القياس عليه عندما تطلب منك الصفحة الرئيسية لمشروع ما تمرير script من curl مباشرةً إلى shell. لا يتحقق أي شيء من البايتات، ولا تراها أنت. ويمكن للخادم أيضاً أن يعيد محتوى إلى script ويعيد محتوى آخر إلى المتصفح، ولن تملك نسخة تفحصها بعد ذلك. نزّل المحتوى إلى ملف باستخدام curl -fsSL <url> -o install.sh، واحسب تجزئته، واقرأه باستخدام less، ثم شغّله. تستغرق هذه العادة نحو عشرين ثانية، وهي العادة نفسها التي يجدر بك البدء بها على VPS جديد تماماً خلال أول عشر دقائق منه، قبل تثبيت أي شيء آخر على الخادم.

احتفظ بقائمة ببصمات الملفات التي تثبّتها يدوياً

تُتتبَّع الحزم التي يثبّتها apt. أما الملف التنفيذي الذي نسخته إلى /usr/local/bin فلا يُتتبَّع، ولا توجد على النظام أي آلية تراقبه. تحوّل قائمة البصمات ذلك إلى شيء يمكنك التحقق منه عند الطلب:

printf 'a second file\n' > notes.txt
sha256sum *.txt > inventory.sha256
sha256sum -c --quiet inventory.sha256

يطبع --quiet لا شيء عندما تتطابق جميع الملفات، ويطبع فقط الأسطر التي فشلت عندما لا تتطابق بعض الملفات. لذلك يعني الصمت نجاح الفحص، ويؤكد echo $? ذلك باستخدام 0. هذه هي الصيغة التي تضعها في مهمة مجدولة. يذهب --status إلى أبعد من ذلك، فلا يطبع أي شيء على الإطلاق، ويترك لك حالة الخروج فقط. طبّق النمط نفسه على الملفات الفعلية باستخدام sha256sum /usr/local/bin/* > ~/local-bin.sha256، وستحصل على خط أساس. تُخزَّن المسارات في القائمة تماماً كما كتبتها، لذلك تجعل المسارات المطلقة الفحص يعمل من أي دليل.

كن واضحاً بشأن قيمة خط الأساس هذا. فهو يكتشف تغيّر أحد الملفات. لكنه لا يكتشف مهاجماً لديه صلاحيات root مسبقاً، لأن ذلك المهاجم يستطيع إعادة كتابة inventory.sha256 بسهولة إعادة كتابة الملف التنفيذي. احتفظ بالقائمة خارج الجهاز إذا أردت أن تكون لها قيمة فعلية. وهذا جزء من السؤال الأوسع المتعلق بـمدى ثقتك الفعلية بخادم VPS ومن يمكنه أيضاً الوصول إلى القرص الموجود تحته.

FAQ

هل يعني تطابق قيمة checksum أن التنزيل آمن؟

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

لماذا تطبع sha256sum -c القيمة FAILED open or read؟

لأنها لم تقرأ الملف قط. يوجد سطر منفصل فوقها مباشرة يقول No such file or directory مع اسم الملف الذي بحثت عنه. تكون أسماء الملفات داخل ملف SHA256SUMS نسبية إلى الدليل الذي تشغّل فيه الأمر. لذلك انتقل إلى الدليل الذي يحتوي على التنزيل وشغّل الأمر مرة أخرى. إذا كانت القائمة تتضمن أيضاً ملفات لم تنزّلها، فأضف --ignore-missing. أما FAILED العادية من دون open or read فتعني الحالة العكسية: تمت قراءة الملف، لكن قيمة digest الخاصة به لم تتطابق.

هل تكفي MD5 للتحقق من تنزيل؟

نعم، عند التحقق من التلف العرضي. فلن ينتج النقل المبتور أو كتلة القرص التالفة قيمة MD5 مطابقة بالصدفة. لكن الإجابة لا عند مواجهة مهاجم. أصبح من الممكن إنشاء ملفين مختلفين لهما قيمة MD5 نفسها منذ 2004، وتعرّضت SHA-1 لتصادم ذي بادئة مختارة في 2020. استخدم سطر SHA-256 عندما ينشر المشروع القيمتين، واعتبر المشروع الذي يستخدم MD5 فقط مؤشراً إلى عملية إصدار قديمة.

ما الفرق بين sha256sum -c وgpg --verify؟

تثبت sha256sum -c أن الملف يطابق قيمة digest. وتثبت gpg --verify أن ملف digest وُقّع باستخدام المفتاح الخاص لشخص أو جهة تملك مفتاحاً خاصاً محدداً. يجيب كل منهما عن سؤال مختلف. لذلك شغّلهما معاً عندما يوفّر المشروع كليهما. يجعل التوقيع قائمة digest موثوقة، ثم تجعل قائمة digest الملف الذي نزّلته موثوقاً.

كيف أتحقق من ملف واحد باستخدام قيمة digest مطبوعة على صفحة ويب؟

لا تقارن المحارف بصرياً. احفظ قيمة digest واسم الملف في سطر واحد، مع فاصل من مسافتين بينهما، ثم شغّل sha256sum -c على ذلك الملف واقرأ OK أو FAILED التي يطبعها. يساعد إنشاء السطر باستخدام printf '%s %s\n' على تجنب أخطاء التنسيق التي تجعل sha256sum ترفض الملف مع no properly formatted checksum lines found.

#checksums#sha256sum#integrity#supply-chain#أمان