ToolDeck

تجزئة SHA-256 بـ Python — دليل hashlib وأمثلة

·DevOps Engineer & Python Automation Specialist·مراجعة بواسطةMaria Santos·نُشر

استخدم مولد Hash SHA-256 المجاني مباشرةً في متصفحك — لا حاجة للتثبيت.

جرّب مولد Hash SHA-256 أونلاين ←

كل خط أنابيب نشر بنيته احتاج في نهاية المطاف إلى التحقق من مجموع اختباري لملف، أو توقيع حمولة webhook، أو بصمة مفتاح ذاكرة تخزين مؤقت. تجزئة SHA-256 بـ Python مع الوحدة المدمجة hashlib يتعامل مع كل هذه الحالات — وهو مثبّت لديك بالفعل. hashlib.sha256() يُغلّف تنفيذ OpenSSL على CPython، فهو سريع ومتوافق مع FIPS افتراضياً. للحصول على تجزئة سريعة دون كتابة أي كود، يعطيك مولّد SHA-256 الأونلاين النتيجة فوراً. جميع الأمثلة تستهدف Python 3.9+.

  • hashlib.sha256(data).hexdigest() هي الطريقة المعيارية لتجزئة البايتات — جزء من stdlib ومدعومة بـ OpenSSL.
  • يجب تشفير النصوص إلى بايتات أولاً: hashlib.sha256("text".encode("utf-8")).
  • للمجاميع الاختبارية للملفات، أدخل البيانات في أجزاء عبر .update() — لا تحمّل ملفاً كبيراً في الذاكرة دفعةً واحدة.
  • يتطلب HMAC-SHA256 وحدة hmac: hmac.new(key, msg, hashlib.sha256) — SHA-256 وحده لا يدعم المفاتيح.

ما هي تجزئة SHA-256؟

يأخذ SHA-256 (خوارزمية التجزئة الآمنة، 256 بت) مدخلاً ذا طول اعتباطي وينتج ملخصاً ثابتاً بحجم 256 بت (32 بايت). المدخل ذاته ينتج دائماً المخرج ذاته، لكن حتى تغيير بت واحد في المدخل ينتج تجزئة مختلفة كلياً — وهذه الخاصية تُسمى تأثير الانهيار. SHA-256 جزء من عائلة SHA-2، معيار من NIST، وهو العمود الفقري لبصمات شهادات TLS ومعرّفات الإيداعات في Git وترويسات كتل Bitcoin والتحقق من سلامة الملفات. تستخدم الخوارزمية بنية Merkle-Damgård مع 64 جولة ضغط لإنتاج مخرجاتها البالغة 256 بت.

After · text
Before · text
a1f7c3d8e9b2...27ae41e4649b (64 حرفاً سداسياً)
deployment-v4.2.1

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

hashlib.sha256() — أسلوب المكتبة القياسية

وحدة hashlib مدمجة في Python من الأساس — لا حاجة لـ pip install. استدعِ hashlib.sha256() مع وسيطة bytes لإنشاء كائن تجزئة، ثم احصل على النتيجة عبر .hexdigest() (سلسلة سداسية) أو .digest() (بايتات خام). اسم الدالة بأحرف صغيرة: sha256، وليس SHA256.

Python 3.9+ — تجزئة SHA-256 بسيطة
import hashlib

# تجزئة سلسلة بايتات مباشرةً
digest = hashlib.sha256(b"deployment-v4.2.1").hexdigest()
print(digest)
# a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db

أكثر خطأ شائع مع hashlib.sha256() هو تمرير str بدلاً من bytes. نصوص Python هي Unicode، وتعمل دوال التجزئة على بايتات خام. يجب استدعاء .encode("utf-8") قبل التجزئة. يقع في هذا الخطأ كل مبتدئ تقريباً.

Python 3.9+ — تجزئة نص
import hashlib

# يجب تشفير النصوص إلى بايتات قبل التجزئة
config_key = "redis://cache.internal:6379/0"
digest = hashlib.sha256(config_key.encode("utf-8")).hexdigest()
print(digest)
# 7d3f8c2a1b9e4f5d6c8a7b3e2f1d9c4a5b8e7f6d3c2a1b9e4f5d6c8a7b3e2f1d

تتيح لك دالة .update() إدخال البيانات تدريجياً. استدعاء h.update(a); h.update(b) يعادل hashlib.sha256(a + b). هكذا تجزّئ الملفات في أجزاء دون تحميل المحتوى بأكمله في الذاكرة.

Python 3.9+ — تجزئة تدريجية مع update()
import hashlib

h = hashlib.sha256()
h.update(b"request_id=req_7f3a91bc")
h.update(b"&timestamp=1741614120")
h.update(b"&amount=4999")
print(h.hexdigest())
# يعادل hashlib.sha256(b"request_id=req_7f3a91bc&timestamp=1741614120&amount=4999").hexdigest()
ملاحظة:.digest() تُعيد 32 بايتاً خاماً. .hexdigest() تُعيد سلسلة سداسية من 64 حرفاً. استخدم .digest() عند تغذية النتيجة في HMAC أو ترميز Base64 أو البروتوكولات الثنائية. استخدم .hexdigest() للتسجيل وأعمدة قاعدة البيانات ومقارنة المجاميع الاختبارية.

HMAC-SHA256 — التجزئة بمفتاح مع وحدة hmac

لا يتعامل SHA-256 وحده مع المفاتيح السرية — أي شخص لديه المدخل ذاته يمكنه حساب التجزئة ذاتها. إذا أردت إثبات أن رسالة جاءت من مرسل محدد (التحقق من webhook، توقيع طلبات API، مصادقة الرموز)، تحتاج إلى HMAC. وحدة hmac جزء من المكتبة القياسية لـ Python وتدمج المفتاح في عملية التجزئة بحيث لا يمكن لأحد إنتاج هذا الملخص أو التحقق منه إلا من يملك المفتاح.

Python 3.9+ — HMAC-SHA256 أساسي
import hmac
import hashlib

# التحقق من توقيع webhook
secret_key = b"whsec_9f3a7b2e1d4c8a5b"
payload = b'{"event":"invoice.paid","invoice_id":"inv_8d2c","amount":14900}'

signature = hmac.new(secret_key, payload, hashlib.sha256).hexdigest()
print(signature)
# ملخص HMAC-SHA256 سداسي من 64 حرفاً

يستلزم التحقق من HMAC الوارد استخدام hmac.compare_digest() بدلاً من العامل ==. عامل المساواة عرضة لهجمات التوقيت — يتوقف عند أول بايت مختلف، ويمكن للمهاجم قياس أوقات الاستجابة لتخمين التوقيع الصحيح بايتاً بايتاً. compare_digest() يعمل في وقت ثابت بغض النظر عن موضع الاختلاف.

Python 3.9+ — التحقق من توقيع webhook
import hmac
import hashlib

def verify_webhook(payload: bytes, received_sig: str, secret: bytes) -> bool:
    """التحقق من توقيع webhook باستخدام المقارنة في وقت ثابت."""
    expected = hmac.new(secret, payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, received_sig)

# محاكاة التحقق من webhook بأسلوب Stripe
incoming_payload = b'{"event":"payment.completed","amount":4999}'
incoming_signature = "a1b2c3d4e5f6..."  # من ترويسة X-Signature
webhook_secret = b"whsec_9f3a7b2e1d4c"

if verify_webhook(incoming_payload, incoming_signature, webhook_secret):
    print("التوقيع صالح — معالجة الحدث")
else:
    print("عدم تطابق التوقيع — رفض الطلب")

توقيع طلبات API بـ HMAC-SHA256

يتبع توقيع طلبات API المبدأ ذاته: أنشئ سلسلة متعارفاً عليها من مكونات الطلب (الطريقة، المسار، الطابع الزمني، تجزئة الجسم) ثم وقّعها بمفتاحك السري. AWS Signature V4 وStripe وـGitHub webhooks كلها تستخدم أشكالاً من هذا النمط.

Python 3.9+ — توقيع طلب API بـ HMAC-SHA256
import hmac
import hashlib
import time

def sign_request(method: str, path: str, body: bytes, secret: bytes) -> str:
    """إنشاء توقيع HMAC-SHA256 لطلب API."""
    timestamp = str(int(time.time()))
    body_hash = hashlib.sha256(body).hexdigest()

    # السلسلة المتعارف عليها: الطريقة + المسار + الطابع الزمني + تجزئة الجسم
    canonical = f"{method}\n{path}\n{timestamp}\n{body_hash}"
    signature = hmac.new(secret, canonical.encode("utf-8"), hashlib.sha256).hexdigest()

    return f"ts={timestamp},sig={signature}"

# الاستخدام
api_secret = b"sk_live_9f3a7b2e1d4c8a5b6e7f"
request_body = b'{"customer_id":"cust_4f2a","plan":"enterprise"}'
auth_header = sign_request("POST", "/api/v2/subscriptions", request_body, api_secret)
print(f"Authorization: HMAC-SHA256 {auth_header}")
# Authorization: HMAC-SHA256 ts=1741614120,sig=7d3f8c2a...

HMAC-SHA256 مُشفَّر بـ Base64

تتوقع بعض واجهات API (AWS Signature V4 وبعض بوابات الدفع) نتيجة HMAC كسلسلة مشفّرة بـ Base64 بدلاً من السداسية. الفارق: السداسية تستخدم 64 حرفاً، بينما Base64 تستخدم 44 حرفاً للملخص ذاته بحجم 32 بايت.

Python 3.9+ — HMAC-SHA256 مُشفَّر بـ Base64
import hmac
import hashlib
import base64

secret = b"webhook_secret_9f3a"
message = b"POST /api/v2/events 1741614120"

# مخرجات سداسية: 64 حرفاً
hex_sig = hmac.new(secret, message, hashlib.sha256).hexdigest()
print(f"Hex:    {hex_sig}")

# مخرجات Base64: 44 حرفاً (أقصر، شائع في ترويسات HTTP)
raw_sig = hmac.new(secret, message, hashlib.sha256).digest()
b64_sig = base64.b64encode(raw_sig).decode("ascii")
print(f"Base64: {b64_sig}")

تجزئة datetime وUUID والكائنات المخصصة

يعمل SHA-256 على بايتات خام، لذا يجب تسلسل الأنواع غير البايتية — datetime وUUID والـ dataclasses ونماذج Pydantic — إلى بايتات قبل التجزئة. لا يوجد تحويل تلقائي؛ أنت تختار التمثيل المتعارف عليه. للتجزئة الحتمية عبر الأنظمة، استخدم دائماً ترميزاً صريحاً وصيغة تسلسل ثابتة (ISO 8601 لـ datetime، الصيغة النصية المعيارية لـ UUID، JSON بمفاتيح مرتبة للقواميس).

Python 3.9+ — تجزئة datetime وUUID
import hashlib
import uuid
from datetime import datetime, timezone

# datetime — استخدم ISO 8601 مع إزاحة UTC الصريحة للتنقلية
event_time = datetime(2026, 3, 28, 12, 0, 0, tzinfo=timezone.utc)
time_hash = hashlib.sha256(event_time.isoformat().encode("utf-8")).hexdigest()
print(f"datetime hash: {time_hash[:16]}...")

# UUID — جزّئ الصيغة النصية المعيارية (أحرف صغيرة مع شرطات)
record_id = uuid.uuid4()
uuid_hash = hashlib.sha256(str(record_id).encode("utf-8")).hexdigest()
print(f"UUID hash: {uuid_hash[:16]}...")

للكائنات المخصصة، سلسلها إلى تمثيل بايتات متعارف عليه قبل التجزئة. JSON بمفاتيح مرتبة يعمل جيداً للكائنات المشابهة للقواميس:

Python 3.9+ — تجزئة كائن مخصص
import hashlib
import json
from dataclasses import dataclass, asdict

@dataclass
class Event:
    id: str
    type: str
    amount: int
    timestamp: str

def hash_event(event: Event) -> str:
    """تجزئة كائن dataclass باستخدام JSON بمفاتيح مرتبة للحتمية."""
    canonical = json.dumps(asdict(event), sort_keys=True, separators=(",", ":"))
    return hashlib.sha256(canonical.encode("utf-8")).hexdigest()

e = Event(id="evt_4f2a", type="payment.completed", amount=4999, timestamp="2026-03-28T12:00:00Z")
print(hash_event(e))  # ثابت عبر التشغيلات والأجهزة
ملاحظة:رتّب مفاتيح القواميس دائماً (sort_keys=True) عند تجزئة الكائنات المسلسلة بـ JSON. ترتيب الإدراج محفوظ في Python 3.7+ لكنه قد يختلف عبر مسارات التسلسل، مما ينتج تجزئات مختلفة لبيانات متطابقة.

المجموع الاختباري SHA-256 للملفات — التحقق من التنزيلات والتصنيفات

حساب المجموع الاختباري SHA-256 لملف هو أحد أكثر استخدامات الخوارزمية شيوعاً. تجده في كل مكان: صفحات إصدار ثنائيات Go وملفات Python wheel وملفات بيان صور Docker وتحديثات البرامج الثابتة. المفتاح هو قراءة الملف في أجزاء بدلاً من تحميله دفعةً واحدة — صورة ISO بحجم 2 جيجابايت لا ينبغي أن تتطلب 2 جيجابايت من الذاكرة لمجرد تجزئتها.

Python 3.9+ — المجموع الاختباري SHA-256 لملف (بأجزاء)
import hashlib

def sha256_checksum(filepath: str, chunk_size: int = 8192) -> str:
    """احسب تجزئة SHA-256 لملف مع القراءة في أجزاء لتوفير الذاكرة."""
    h = hashlib.sha256()
    with open(filepath, "rb") as f:
        for chunk in iter(lambda: f.read(chunk_size), b""):
            h.update(chunk)
    return h.hexdigest()

# تجزئة ملف إصدار
checksum = sha256_checksum("/tmp/release-v4.2.1.tar.gz")
print(f"SHA-256: {checksum}")

أضاف Python 3.11 الدالة hashlib.file_digest() التي تجري القراءة المجزأة داخلياً وقد تستخدم تحسينات النسخ الصفري على المنصات المدعومة. إذا كنت على 3.11 أو أحدث، فضّلها على الحلقة اليدوية.

Python 3.11+ — hashlib.file_digest()
import hashlib

with open("/tmp/release-v4.2.1.tar.gz", "rb") as f:
    digest = hashlib.file_digest(f, "sha256")

print(digest.hexdigest())

التحقق من ملف محمّل مقابل مجموع اختباري معروف

Python 3.9+ — التحقق من المجموع الاختباري
import hashlib
import hmac as hmac_mod  # لـ compare_digest فقط

def verify_checksum(filepath: str, expected_hex: str) -> bool:
    """التحقق من مجموع SHA-256 الاختباري باستخدام المقارنة في وقت ثابت."""
    h = hashlib.sha256()
    with open(filepath, "rb") as f:
        for chunk in iter(lambda: f.read(8192), b""):
            h.update(chunk)
    return hmac_mod.compare_digest(h.hexdigest(), expected_hex.lower())

# التحقق من ملف إصدار
expected = "a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db"
if verify_checksum("/tmp/release-v4.2.1.tar.gz", expected):
    print("المجموع الاختباري متطابق — الملف سليم")
else:
    print("عدم تطابق المجموع الاختباري — قد يكون الملف تالفاً أو معدّلاً")
ملاحظة:استخدم دائماً hmac.compare_digest() لمقارنة المجاميع الاختبارية حتى حين لا يوجد مفتاح سري. المقارنة في وقت ثابت تمنع تسرب المعلومات عبر التوقيت. العامل == يعمل وظيفياً لكنه غير آمن للسياقات الأمنية الحساسة.

SHA-256 مع ترميز Base64

تتوقع بعض البروتوكولات ملخص SHA-256 كسلسلة Base64 بدلاً من سداسية. ترويسات HTTP مثل Content-Digest وIntegrity (سلامة الموارد الفرعية في المتصفحات) تستخدم Base64، وتوقيعات JWT مُشفَّرة بـ Base64url. الحيلة هي ترميز بايتات .digest() الخام بـ Base64، وليس السلسلة السداسية.

Python 3.9+ — SHA-256 مُشفَّر بـ Base64
import hashlib
import base64

data = b"integrity check payload"

# الصحيح: Base64 للبايتات الخام (32 بايت → 44 حرفاً بـ Base64)
raw_digest = hashlib.sha256(data).digest()
b64_digest = base64.b64encode(raw_digest).decode("ascii")
print(f"sha256-{b64_digest}")
# sha256-<44 حرفاً>

# الخطأ: Base64 للسلسلة السداسية (64 بايت ASCII → 88 حرفاً بـ Base64 — ضعف الحجم)
hex_digest = hashlib.sha256(data).hexdigest()
wrong = base64.b64encode(hex_digest.encode()).decode()
print(f"طول خاطئ: {len(wrong)} حرفاً")  # 88 — ليس ما تتوقعه الـ APIs
تحذير:ترميز السلسلة السداسية بـ Base64 بدلاً من البايتات الخام خطأ شائع ينتج مخرجات بضعف الطول المتوقع. ستُرفض من قِبل الـ APIs، ورسالة الخطأ عادةً لا تشير إلى السبب. استدعِ دائماً .digest() وليس .hexdigest() قبل ترميز Base64.

مرجع hashlib.sha256()

الدالة البانية والدوال على كائن تجزئة SHA-256:

المعامل / الدالة
النوع
الوصف
data (positional)
bytes
البيانات الأولية للتجزئة — يعادل استدعاء update(data) فور الإنشاء
.update(data)
bytes
تغذية بايتات إضافية في حالة التجزئة — يمكن استدعاؤها عدة مرات للبيانات المجزأة
.digest()
→ bytes
يُعيد ملخص ثنائي خام بحجم 32 بايت — استخدمه لمدخلات HMAC والبروتوكولات الثنائية وترميز Base64
.hexdigest()
→ str
يُعيد سلسلة سداسية عشرية من 64 حرفاً بأحرف صغيرة — التمثيل المعياري للمجاميع الاختبارية والتحقق
.copy()
→ hash object
يُعيد نسخة من حالة التجزئة الحالية — يتيح تفرّع الملخص دون إعادة التجزئة من البداية
hashlib.sha256()
constructor
ينشئ كائن تجزئة SHA-256 جديداً مدعوماً بـ OpenSSL في CPython — usedfips=True في 3.9+ يقيّد استخدام خوارزميات FIPS المعتمدة

معاملات hmac.new() للتجزئة بمفتاح:

المعامل
النوع
الوصف
key
bytes
المفتاح السري — يجب أن يكون bytes وليس str
msg
bytes | None
الرسالة الأولية للمصادقة — None افتراضياً، يمكن استدعاء update() لاحقاً
digestmod
str | callable
خوارزمية التجزئة: مرّر hashlib.sha256 أو السلسلة "sha256"

مكتبة cryptography — واجهة برمجية بديلة لـ SHA-256

توفر حزمة cryptography واجهة برمجية مختلفة لـ SHA-256 عبر primitives الـ hazmat. نادراً ما ألجأ إليها حين أحتاج فقط إلى تجزئة — hashlib أبسط ولا تعتمد على مكتبات خارجية. لكن إذا كان مشروعك يعتمد أصلاً على cryptography لـ TLS أو X.509 أو التشفير المتماثل، فاستخدام واجهة التجزئة الخاصة بها يُبقي كل شيء تحت مكتبة واحدة ويمنحك معالجة أخطاء متسقة.

Python 3.9+ — SHA-256 مع مكتبة cryptography
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend

digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(b"deployment-v4.2.1")
result = digest.finalize()  # 32 بايتاً خاماً

print(result.hex())  # سلسلة سداسية من 64 حرفاً
# a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db
تحذير:تتطلب مكتبة cryptography pip install cryptography. كائن التجزئة لاستخدام واحد: استدعاء .finalize() مرة ثانية يُثير AlreadyFinalized. استخدم .copy() قبل الإنهاء إذا أردت تفريع حالة التجزئة.

تجزئة البيانات من ملف وطلب API

سيناريوان يظهران باستمرار: تجزئة ملف على القرص للتحقق من ملف إصدار، وتجزئة جسم طلب HTTP لاستخدامه مفتاح تخزين مؤقت أو التحقق من webhook.

قراءة الملف → حساب SHA-256 → المقارنة

Python 3.9+ — تجزئة نسخة احتياطية مع معالجة الأخطاء
import hashlib
import sys

def hash_file_safe(filepath: str) -> str | None:
    """تجزئة ملف مع معالجة صحيحة للأخطاء."""
    try:
        h = hashlib.sha256()
        with open(filepath, "rb") as f:
            for chunk in iter(lambda: f.read(16384), b""):
                h.update(chunk)
        return h.hexdigest()
    except FileNotFoundError:
        print(f"خطأ: {filepath} غير موجود", file=sys.stderr)
        return None
    except PermissionError:
        print(f"خطأ: لا يوجد إذن قراءة لـ {filepath}", file=sys.stderr)
        return None

result = hash_file_safe("/etc/nginx/nginx.conf")
if result:
    print(f"SHA-256: {result}")

طلب HTTP → تجزئة الجسم كمفتاح تخزين مؤقت

Python 3.9+ — تجزئة استجابة API
import hashlib
import urllib.request
import json

def fetch_and_hash(url: str) -> tuple[dict, str]:
    """جلب JSON من API وإرجاع البيانات مع تجزئة SHA-256 الخاصة بها."""
    try:
        with urllib.request.urlopen(url, timeout=10) as resp:
            body = resp.read()
            content_hash = hashlib.sha256(body).hexdigest()
            data = json.loads(body)
            return data, content_hash
    except urllib.error.URLError as exc:
        raise ConnectionError(f"فشل الجلب من {url}: {exc}") from exc

# مفتاح تخزين مؤقت بناءً على محتوى الاستجابة
data, digest = fetch_and_hash("https://api.exchange.internal/v2/rates")
print(f"تجزئة الاستجابة: {digest[:16]}...")
print(f"EUR/USD: {data.get('rates', {}).get('EUR', 'N/A')}")

للتحقق السريع من مرة واحدة، مولّد SHA-256 من ToolDeck يعمل كلياً في متصفحك — دون الحاجة إلى كود.

تجزئة SHA-256 من سطر الأوامر

أحياناً تحتاج فقط إلى تجزئة سريعة في الطرفية خلال حادثة أو نشر. وحدة hashlib في Python لا تملك أمر فرعي لسطر الأوامر مدمجاً (بخلاف python3 -m json.tool)، لكن يمكنك استخدام سطر واحد أو أدوات النظام.

bash — تجزئة نص من سطر الأوامر
# سطر Python واحد
echo -n "deployment-v4.2.1" | python3 -c "import hashlib,sys; print(hashlib.sha256(sys.stdin.buffer.read()).hexdigest())"

# macOS / BSD
echo -n "deployment-v4.2.1" | shasum -a 256

# Linux (coreutils)
echo -n "deployment-v4.2.1" | sha256sum

# OpenSSL (متعدد المنصات)
echo -n "deployment-v4.2.1" | openssl dgst -sha256
bash — تجزئة ملف
# تجزئة ملف إصدار مضغوط
sha256sum release-v4.2.1.tar.gz
# أو
openssl dgst -sha256 release-v4.2.1.tar.gz

# التحقق مقابل مجموع اختباري معروف
echo "a8f5f167f44f4964e6c998dee827110c release-v4.2.1.tar.gz" | sha256sum -c -
# release-v4.2.1.tar.gz: OK
ملاحظة:استخدم دائماً echo -n (بدون سطر جديد في النهاية) عند تجزئة النصوص من سطر الأوامر. أمر echo العادي يُضيف \n مما يغير التجزئة. هذا السبب الأول الذي يجعل الناس يحصلون على تجزئات مختلفة بين Python والصدفة.

البديل عالي الأداء — hashlib مع OpenSSL وpycryptodome

على CPython، hashlib.sha256() يُفوّض بالفعل إلى تنفيذ OpenSSL بلغة C، فهو سريع — عادةً 500+ ميجابايت/ثانية على الأجهزة الحديثة.

إذا ظهرت تجزئة SHA-256 في مُحلّل الأداء — مثلاً عند حساب المجاميع الاختبارية لآلاف الملفات في خط أنابيب CI أو تجزئة كل جسم طلب في بوابة API عالية الإنتاجية — يوجد خياران: تحسين نمط استدعاء hashlib، أو التحول إلى pycryptodome للحصول على واجهة برمجية موحدة للتشفير تشمل SHA-3 وBLAKE2:

bash — تثبيت pycryptodome
pip install pycryptodome
Python 3.9+ — SHA-256 مع pycryptodome
from Crypto.Hash import SHA256

h = SHA256.new()
h.update(b"deployment-v4.2.1")
print(h.hexdigest())
# a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db

للتجزئة المتوازية للملفات عالية الإنتاجية، تأتي المكاسب الأكبر من تقليل overhead بايثون عبر أجزاء أكبر وتعدد الخيوط:

Python 3.9+ — تجزئة ملفات دفعية مع hashlib
import hashlib
import os
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor

def hash_file(path: Path) -> tuple[str, str]:
    """تجزئة ملف واحد وإرجاع (المسار، الملخص السداسي)."""
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for chunk in iter(lambda: f.read(65536), b""):  # أجزاء 64 كيلوبايت
            h.update(chunk)
    return str(path), h.hexdigest()

def hash_directory(directory: str, pattern: str = "*.tar.gz") -> dict[str, str]:
    """تجزئة جميع الملفات المطابقة بشكل متوازٍ باستخدام الخيوط."""
    files = list(Path(directory).glob(pattern))
    results = {}
    with ThreadPoolExecutor(max_workers=os.cpu_count()) as pool:
        for path, digest in pool.map(hash_file, files):
            results[path] = digest
    return results

# تجزئة جميع ملفات الإصدار بشكل متوازٍ
checksums = hash_directory("/var/releases", "*.tar.gz")
for path, digest in checksums.items():
    print(f"{digest}  {path}")

استخدام أجزاء 64 كيلوبايت بدلاً من 8 كيلوبايت يُقلل عدد الاستدعاءات من Python إلى C بمقدار 8 أضعاف. تعمل الخيوط جيداً هنا لأن GIL يُحرَّر خلال التجزئة على مستوى C — الاختناق هو في الإدخال/الإخراج للقرص وليس في المعالج.

مخرجات الطرفية مع تمييز بناء الجملة

مكتبة rich مفيدة حين تحتاج التحقق من دفعة ملفات وتريد جدولاً يُظهر حالة النجاح/الفشل لكل ملف بدلاً من تدفق المخرجات السداسية الخام.

bash — تثبيت rich
pip install rich
Python 3.9+ — مخرجات rich للتحقق من التجزئة
import hashlib
from pathlib import Path
from rich.console import Console
from rich.table import Table

console = Console()

def hash_and_display(files: list[str], expected: dict[str, str]) -> None:
    """تجزئة الملفات وعرض النتائج مع رمز لوني للتحقق."""
    table = Table(title="التحقق من SHA-256")
    table.add_column("الملف", style="cyan")
    table.add_column("SHA-256", style="dim", max_width=20)
    table.add_column("الحالة")

    for filepath in files:
        h = hashlib.sha256()
        with open(filepath, "rb") as f:
            for chunk in iter(lambda: f.read(8192), b""):
                h.update(chunk)
        digest = h.hexdigest()

        name = Path(filepath).name
        status = "[green]✓ OK[/green]" if expected.get(name) == digest else "[red]✗ MISMATCH[/red]"
        table.add_row(name, f"{digest[:16]}...", status)

    console.print(table)

# الاستخدام
expected_checksums = {
    "api-gateway-v3.1.tar.gz": "a8f5f167f44f4964...",
    "worker-v3.1.tar.gz": "7d3f8c2a1b9e4f5d...",
}
hash_and_display(
    ["/var/releases/api-gateway-v3.1.tar.gz", "/var/releases/worker-v3.1.tar.gz"],
    expected_checksums,
)
ملاحظة:مخرجات Rich للعرض في الطرفية فقط. لا تكتب رموز ANSI الملوّنة في ملفات السجل أو طلبات API — جرّدها باستخدام console.print(data, highlight=False) أو وجّهها إلى ملف بـ Console(file=open(...)).

العمل مع الملفات الكبيرة

نمط .update() المجزأ يتعامل مع ملفات بأي حجم باستخدام ذاكرة ثابتة. للملفات الكبيرة جداً (صور قرص بعدة جيجابايتات، نسخ احتياطية لقواعد البيانات)، ينتقل الاهتمام الرئيسي من الذاكرة إلى تغذية راجعة للمستخدم — تجزئة 10 جيجابايت بسرعة 500 ميجابايت/ثانية تستغرق 20 ثانية، والصمت خلال هذا الوقت يجعل المستخدم يظن أن البرنامج تعطّل.

Python 3.9+ — تجزئة ملفات كبيرة مع تقرير التقدم
import hashlib
import os

def sha256_with_progress(filepath: str) -> str:
    """تجزئة ملف كبير مع تقرير التقدم إلى stderr."""
    file_size = os.path.getsize(filepath)
    h = hashlib.sha256()
    bytes_read = 0

    with open(filepath, "rb") as f:
        while chunk := f.read(1 << 20):  # أجزاء 1 ميجابايت
            h.update(chunk)
            bytes_read += len(chunk)
            pct = (bytes_read / file_size) * 100
            print(f"\r  جارٍ التجزئة: {pct:.1f}% ({bytes_read >> 20} ميجابايت / {file_size >> 20} ميجابايت)",
                  end="", flush=True)

    print()  # سطر جديد بعد شريط التقدم
    return h.hexdigest()

digest = sha256_with_progress("/mnt/backups/db-snapshot-2026-03.sql.gz")
print(f"SHA-256: {digest}")

NDJSON / JSON Lines — تجزئة كل سجل على حدة

Python 3.9+ — تجزئة سجلات فردية في تدفق NDJSON
import hashlib
import json

def hash_ndjson_records(filepath: str) -> dict[str, str]:
    """تجزئة كل سجل JSON في ملف NDJSON لإزالة التكرارات."""
    seen = {}
    with open(filepath, "r", encoding="utf-8") as f:
        for line_num, line in enumerate(f, 1):
            line = line.strip()
            if not line:
                continue
            try:
                record = json.loads(line)
                # توحيد قبل التجزئة: ترتيب المفاتيح للمخرجات الحتمية
                canonical = json.dumps(record, sort_keys=True, separators=(",", ":"))
                digest = hashlib.sha256(canonical.encode("utf-8")).hexdigest()

                if digest in seen:
                    print(f"السطر {line_num}: مكرر من السطر {seen[digest]}")
                else:
                    seen[digest] = line_num
            except json.JSONDecodeError:
                print(f"السطر {line_num}: JSON غير صالح، تم التخطي")

    print(f"تمت معالجة {line_num} سطراً، {len(seen)} سجلاً فريداً")
    return seen

hash_ndjson_records("telemetry-events-2026-03.ndjson")
ملاحظة:انتقل من الاستدعاء المباشر hashlib.sha256(data) إلى حلقة .update() المجزأة عندما تتجاوز الملفات 50–100 ميجابايت. تحت هذا الحد، قراءة الملف بأكمله بـ f.read() مقبولة — سيكون استهلاك الذاكرة تقريباً مساوياً لحجم الملف.

الأخطاء الشائعة

تمرير str بدلاً من bytes إلى hashlib.sha256()

المشكلة: hashlib.sha256('text') يُثير TypeError: Unicode-objects must be encoded before hashing. الدالة تتطلب bytes وليس str.

الحل: شفّر النص أولاً: hashlib.sha256('text'.encode('utf-8')). أو استخدم b'' للقيم المكتوبة مباشرةً.

After · Python
Before · Python
import hashlib
digest = hashlib.sha256("deployment-v4.2.1".encode("utf-8")).hexdigest()
# يعمل — يُعيد سلسلة سداسية من 64 حرفاً
import hashlib
digest = hashlib.sha256("deployment-v4.2.1").hexdigest()
# TypeError: Unicode-objects must be encoded before hashing
استخدام == بدلاً من hmac.compare_digest() للتحقق من التوقيع

المشكلة: العامل == يتوقف عند أول بايت مختلف. يمكن للمهاجم قياس وقت الاستجابة لتخمين التوقيع الصحيح بايتاً بايتاً.

الحل: استخدم hmac.compare_digest() لجميع المقارنات الأمنية الحساسة — يعمل في وقت ثابت بغض النظر عن موضع الاختلاف.

After · Python
Before · Python
received_sig = request.headers["X-Signature"]
expected_sig = hmac.new(key, body, hashlib.sha256).hexdigest()
if hmac.compare_digest(received_sig, expected_sig):  # وقت ثابت
    process_webhook(body)
received_sig = request.headers["X-Signature"]
expected_sig = hmac.new(key, body, hashlib.sha256).hexdigest()
if received_sig == expected_sig:  # عرضة لهجمات التوقيت
    process_webhook(body)
ترميز السلسلة السداسية بـ Base64 بدلاً من البايتات الخام

المشكلة: base64.b64encode(digest.hexdigest().encode()) ينتج سلسلة من 88 حرفاً — ضعف الـ 44 المتوقعة. ستُرفض من الـ APIs التي تتوقع SHA-256 مُشفَّراً بـ Base64.

الحل: استدعِ .digest() (بايتات خام) قبل ترميز Base64 وليس .hexdigest() (سلسلة سداسية).

After · Python
Before · Python
import hashlib, base64
raw = hashlib.sha256(data).digest()
b64 = base64.b64encode(raw)  # 44 حرفاً — صحيح
import hashlib, base64
hex_str = hashlib.sha256(data).hexdigest()
b64 = base64.b64encode(hex_str.encode())  # 88 حرفاً — خطأ!
قراءة ملف كبير بأكمله في الذاكرة قبل التجزئة

المشكلة: hashlib.sha256(open('large.iso', 'rb').read()) يُحمّل الملف بأكمله في الذاكرة. ملف بحجم 4 جيجابايت يتطلب 4 جيجابايت من الذاكرة لمجرد حساب التجزئة.

الحل: اقرأ في أجزاء مع حلقة و.update(). استهلاك الذاكرة يظل ثابتاً بغض النظر عن حجم الملف.

After · Python
Before · Python
import hashlib
h = hashlib.sha256()
with open("disk.iso", "rb") as f:
    for chunk in iter(lambda: f.read(8192), b""):
        h.update(chunk)
digest = h.hexdigest()  # استهلاك ذاكرة ثابت
import hashlib
# يُحمّل ملف 4 جيجابايت بأكمله في الذاكرة
digest = hashlib.sha256(open("disk.iso", "rb").read()).hexdigest()

hashlib مقابل hmac مقابل البدائل — مقارنة سريعة

الطريقة
المخرجات
بمفتاح
السرعة
تدفق الملفات
يتطلب تثبيتاً
أنواع مخصصة
hashlib.sha256()
hex / bytes
سريع (C/OpenSSL)
✓ عبر update()
لا (stdlib)
ترميز يدوي encode()
hmac.new()
hex / bytes
سريع (C/OpenSSL)
✓ عبر update()
لا (stdlib)
ترميز يدوي encode()
hashlib.file_digest()
hex / bytes
سريع (zero-copy)
✓ (مدمج)
لا (3.11+)
ترميز يدوي encode()
cryptography hashes.SHA256()
bytes
سريع (OpenSSL)
✓ عبر update()
pip install
ترميز يدوي encode()
subprocess openssl dgst
hex string
✗ / ✓
أبطأ (fork)
✓ (على مستوى النظام)
System openssl
ترميز يدوي encode()
pyhashcat / مخصص
متنوع
مسرَّع بـ GPU
pip install
ترميز يدوي encode()

للتجزئة المباشرة — المجاميع الاختبارية ومفاتيح التخزين المؤقت وبصمات المحتوى — التزم بـ hashlib.sha256(). انتقل إلى hmac.new() فور احتياجك مفتاحاً سرياً (webhook، توقيعات API، مصادقة الرموز). الجأ إلى مكتبة cryptography فقط إذا كان مشروعك يستخدمها أصلاً للتشفير أو TLS — إضافة اعتماد على امتداد C فقط من أجل التجزئة مبالغة حين يكون hashlib مدعوماً بالفعل بـ OpenSSL.

هل يمكن فك تشفير SHA-256؟ — الفرق بين التجزئة والتشفير

الإجابة المختصرة: لا. SHA-256 دالة أحادية الاتجاه. الخوارزمية مصممة لتكون غير قابلة للعكس — لا يمكنك إعادة بناء المدخل الأصلي من الملخص بحجم 256 بت. هذه ليست قيوداً في التنفيذ؛ إنها خاصية رياضية لدالة التجزئة. فضاء المخرجات البالغ 256 بت ضخم بصورة فلكية (2256 قيمة ممكنة)، والدالة تتخلى عن المعلومات خلال 64 جولة ضغط.

يمكن للمهاجمين محاولة هجمات القوة الغاشمة أو القاموس ضد المدخلات الضعيفة (كلمات المرور الشائعة والنصوص القصيرة)، لكن لأي مدخل بإنتروبيا معقولة — مفاتيح API، رموز عشوائية، محتوى ملفات — عكس SHA-256 غير ممكن حسابياً بالأجهزة الحالية. إذا احتجت إلى تحويل قابل للعكس، استخدم التشفير المتماثل:

Python 3.9+ — التشفير مقابل التجزئة
# التجزئة — أحادية الاتجاه، لا يمكن استرداد الأصل
import hashlib
digest = hashlib.sha256(b"secret-config-value").hexdigest()
# لا طريقة للحصول على "secret-config-value" من الملخص

# التشفير — ثنائي الاتجاه، يمكن فك التشفير بالمفتاح
from cryptography.fernet import Fernet
key = Fernet.generate_key()
cipher = Fernet(key)
encrypted = cipher.encrypt(b"secret-config-value")
decrypted = cipher.decrypt(encrypted)
print(decrypted)  # b"secret-config-value" — استُرد الأصل

لطريقة سريعة بدون تثبيت أي شيء لتوليد تجزئة SHA-256، الأداة الأونلاين تعمل كلياً في متصفحك.

كيف تتحقق مما إذا كانت سلسلة نصية تجزئة SHA-256 صالحة في Python

ملخص SHA-256 السداسي الصالح هو بالضبط 64 حرفاً سداسياً عشرياً (0-9، a-f، A-F). التحقق السريع قبل معالجة المدخلات غير الموثوقة يمنع الأخطاء المُربكة في المراحل اللاحقة.

Python 3.9+ — التحقق من صيغة SHA-256
import re

def is_sha256_hex(value: str) -> bool:
    """التحقق مما إذا كانت السلسلة تطابق صيغة ملخص SHA-256 السداسي."""
    return bool(re.fullmatch(r"[a-fA-F0-9]{64}", value))

# حالات اختبار
print(is_sha256_hex("e3b0c44298fc1c149afbf4c8996fb924"
                     "27ae41e4649b934ca495991b7852b855"))  # True — SHA-256 للسلسلة الفارغة
print(is_sha256_hex("e3b0c44298fc1c14"))                   # False — قصير جداً
print(is_sha256_hex("zzzz" * 16))                          # False — أحرف سداسية غير صالحة
ملاحظة:هذا يتحقق من الصيغة فقط، وليس مما إذا كانت التجزئة محسوبة من مدخل معين. لا توجد طريقة لمعرفة ما إذا كانت سلسلة سداسية من 64 حرفاً ملخص SHA-256 "حقيقي" أو مجرد hex عشوائي — مخرجات SHA-256 غير قابلة للتمييز عن البيانات العشوائية بالتصميم.

الأسئلة الشائعة

كيف أجزّئ نصاً بـ SHA-256 في Python؟

استدعِ hashlib.sha256() مع تشفير النص إلى بايتات. النصوص في Python هي Unicode، وتعمل دوال التجزئة على بايتات خام، لذا يجب استدعاء .encode("utf-8") أولاً. تُعيد الدالة .hexdigest() السلسلة السداسية العشرية المعهودة من 64 حرفاً.

Python
import hashlib

api_key = "sk_live_9f3a7b2e1d4c"
digest = hashlib.sha256(api_key.encode("utf-8")).hexdigest()
print(digest)
# e3b7c4a1f8d2...64 حرفاً سداسياً

هل يمكن فك تشفير ملخص SHA-256 للحصول على النص الأصلي؟

لا. SHA-256 دالة أحادية الاتجاه — تحوّل مدخلات ذات طول اعتباطي إلى مخرجات ثابتة بحجم 256 بت وتفقد البنية الأصلية في العملية. لا يوجد معكوس رياضي. يمكن للمهاجمين محاولة هجمات القوة الغاشمة أو جداول قوس قزح ضد المدخلات الضعيفة (كلمات المرور القصيرة والكلمات الشائعة)، لكن لأي مدخل بإنتروبيا معقولة، عكس SHA-256 غير ممكن حسابياً. إذا احتجت إلى تحويل قابل للعكس، استخدم التشفير (AES-GCM أو Fernet) بدلاً من التجزئة.

ما الفرق بين .digest() و .hexdigest()؟

تُعيد .digest() البايتات الخام الـ 32 للملخص كـ bytes. تُعيد .hexdigest() البيانات ذاتها مشفّرة كسلسلة سداسية عشرية من 64 حرفاً بأحرف صغيرة. استخدم .digest() حين تحتاج مخرجات ثنائية — للتغذية في HMAC أو ترميز Base64 أو الكتابة في البروتوكولات الثنائية. استخدم .hexdigest() حين تحتاج سلسلة مقروءة للتسجيل أو التخزين في قاعدة البيانات أو مقارنة المجاميع الاختبارية.

Python
import hashlib

h = hashlib.sha256(b"deployment-v4.2.1")
print(len(h.digest()))     # 32 (bytes)
print(len(h.hexdigest()))  # 64 (hex characters)

كيف أحسب المجموع الاختباري SHA-256 لملف في Python؟

افتح الملف في وضع ثنائي وأدخله إلى أداة التجزئة في أجزاء عبر .update(). في Python 3.11+ استخدم hashlib.file_digest() للحصول على واجهة برمجية أبسط. لا تستدعِ f.read() على الملفات الكبيرة — فذلك يحمّل الملف بأكمله في الذاكرة.

Python
import hashlib

def sha256_file(path: str) -> str:
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for chunk in iter(lambda: f.read(8192), b""):
            h.update(chunk)
    return h.hexdigest()

print(sha256_file("release-v4.2.1.tar.gz"))

كيف أنشئ توقيع HMAC-SHA256 في Python؟

استخدم وحدة hmac مع hashlib.sha256 كـ digestmod. مرّر المفتاح السري والرسالة كـ bytes. الناتج هو ملخص مشفّر بمفتاح يُثبت كلاً من سلامة البيانات وأصالتها — يحتاج المستقبِل المفتاح ذاته للتحقق.

Python
import hmac
import hashlib

secret = b"webhook_secret_9f3a"
payload = b'{"event":"payment.completed","amount":4999}'
signature = hmac.new(secret, payload, hashlib.sha256).hexdigest()
print(signature)  # HMAC بـ 64 حرفاً سداسياً

كيف أتحقق مما إذا كانت سلسلة نصية تمثّل ملخص SHA-256 صالحاً؟

ملخص SHA-256 السداسي العشري هو بالضبط 64 حرفاً سداسياً عشرياً. استخدم تعبيراً نمطياً أو فحص بسيط للطول والأحرف. أسلوب التعبير النمطي هو الأكثر وضوحاً.

Python
import re

def is_sha256(s: str) -> bool:
    return bool(re.fullmatch(r"[a-fA-F0-9]{64}", s))

print(is_sha256("e3b0c44298fc1c149afbf4c8996fb924"
                 "27ae41e4649b934ca495991b7852b855"))  # True
print(is_sha256("not-a-hash"))  # False

أدوات ذات صلة

DV
Dmitri VolkovDevOps Engineer & Python Automation Specialist

Dmitri is a DevOps engineer who relies on Python as his primary scripting and automation language. He builds internal tooling, CI/CD pipelines, and infrastructure automation scripts that run in production across distributed teams. He writes about the Python standard library, subprocess management, file processing, encoding utilities, and the practical shell-adjacent Python that DevOps engineers use every day.

MS
Maria Santosالمراجع التقني

Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.