ToolDeck

هش SHA-256 در Python — راهنمای hashlib + مثال‌های کد

·DevOps Engineer & Python Automation Specialist·بررسی‌شده توسطMaria Santos·منتشر شده

از تولیدکننده هش SHA-256 آنلاین رایگان مستقیم در مرورگرتان استفاده کنید — نیازی به نصب نیست.

امتحان کردن تولیدکننده هش SHA-256 آنلاین ←

هر deployment pipeline که ساخته‌ام در نهایت نیاز به تأیید چک‌سام یک فایل، امضای یک payload وب‌هوک، یا اثرانگشت یک کلید کش داشته است. هش SHA-256 در Python با ماژول داخلی hashlib همه این موارد را پوشش می‌دهد — و از پیش نصب شده است. hashlib.sha256() در CPython روی پیاده‌سازی OpenSSL اجرا می‌شود، بنابراین سریع است و از همان ابتدا با FIPS سازگار. برای یک هش سریع بدون نوشتن کد، مولد آنلاین SHA-256 نتیجه را فوری ارائه می‌دهد. تمام مثال‌ها برای Python 3.9+ طراحی شده‌اند.

  • hashlib.sha256(data).hexdigest() روش استاندارد هش کردن bytes است — بخشی از کتابخانه استاندارد، پشتیبانی‌شده توسط OpenSSL.
  • رشته‌ها ابتدا باید به bytes تبدیل شوند: hashlib.sha256("text".encode("utf-8")).
  • برای چک‌سام فایل، داده را تکه‌تکه از طریق .update() بدهید — هرگز یک فایل بزرگ را یکجا در حافظه نخوانید.
  • HMAC-SHA256 به ماژول hmac نیاز دارد: hmac.new(key, msg, hashlib.sha256) — SHA-256 به تنهایی کلیدی ندارد.

هش SHA-256 چیست؟

SHA-256 (الگوریتم هش امن، ۲۵۶ بیتی) ورودی با طول دلخواه را دریافت کرده و یک خلاصه ثابت ۲۵۶ بیتی (۳۲ بایتی) تولید می‌کند. همان ورودی همیشه همان خروجی را می‌دهد، اما حتی تغییر یک بیت در ورودی یک هش کاملاً متفاوت تولید می‌کند — این ویژگی اثر بهمن نام دارد. SHA-256 بخشی از خانواده SHA-2 است، توسط NIST استانداردسازی شده، و پایه اثرانگشت گواهی‌های TLS، شناسه‌های commit در Git، سرفصل‌های بلاک Bitcoin، و تأیید صحت فایل است. این الگوریتم از ساختار Merkle-Damgård با ۶۴ دور فشرده‌سازی برای تولید خروجی ۲۵۶ بیتی استفاده می‌کند.

After · text
Before · text
a1f7c3d8e9b2...27ae41e4649b (64 کاراکتر هگز)
deployment-v4.2.1

خلاصه هگز بالا نمایش استاندارد است — ۶۴ کاراکتر هگزادسیمال، همیشه با طول ثابت صرف‌نظر از اینکه یک بایت هش کرده باشید یا یک تصویر کامل دیسک.

hashlib.sha256() — رویکرد کتابخانه استاندارد

ماژول hashlib با هر نصب Python همراه است — نیازی به pip install نیست. hashlib.sha256() را با یک آرگومان bytes فراخوانی کنید تا یک شیء هش بسازید، سپس نتیجه را با .hexdigest() (رشته هگز) یا .digest() (bytes خام) دریافت کنید. نام تابع با حروف کوچک است: 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 هستند و توابع هش روی bytes خام کار می‌کنند. باید قبل از هش کردن .encode("utf-8") را فراخوانی کنید. این موضوع تقریباً همه را دفعه اول گیج می‌کند.

Python 3.9+ — هش کردن یک رشته
import hashlib

# رشته‌ها باید قبل از هش کردن به bytes تبدیل شوند
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() خروجی خام ۳۲ بایتی را برمی‌گرداند. .hexdigest() یک رشته هگز ۶۴ کاراکتری برمی‌گرداند. از .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 هگز ۶۴ کاراکتری

تأیید یک 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("امضا نامعتبر است — درخواست را رد کنید")

امضای درخواست 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 انتظار دارند. تفاوت: هگز ۶۴ کاراکتر استفاده می‌کند، Base64 برای همان خلاصه ۳۲ بایتی ۴۴ کاراکتر استفاده می‌کند.

Python 3.9+ — HMAC-SHA256 رمزگذاری‌شده با Base64
import hmac
import hashlib
import base64

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

# خروجی هگز: ۶۴ کاراکتر
hex_sig = hmac.new(secret, message, hashlib.sha256).hexdigest()
print(f"Hex:    {hex_sig}")

# خروجی Base64: ۴۴ کاراکتر (کوتاه‌تر، رایج در هدرهای 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 روی bytes خام کار می‌کند، بنابراین انواع غیر bytes — datetime، UUID، dataclass‌ها، مدل‌های Pydantic — باید قبل از هش کردن به bytes تبدیل شوند. هیچ تبدیل خودکاری وجود ندارد؛ شما نمایش متعارف را انتخاب می‌کنید. برای هش قطعی در سیستم‌های مختلف، همیشه از یک رمزگذاری صریح و یک فرمت سریال‌سازی پایدار استفاده کنید (ISO 8601 برای datetime‌ها، فرم رشته استاندارد برای UUID‌ها، JSON با کلیدهای مرتب‌شده برای dict‌ها).

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]}...")

برای اشیاء سفارشی، قبل از هش کردن به یک نمایش bytes متعارف تبدیل کنید. JSON با کلیدهای مرتب‌شده برای اشیاء dict‌مانند به خوبی کار می‌کند:

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))  # در تمام اجراها و ماشین‌ها یکسان است
توجه:هنگام هش کردن اشیاء سریال‌شده JSON همیشه کلیدهای dict را مرتب کنید (sort_keys=True). ترتیب درج dict در Python 3.7+ حفظ می‌شود اما ممکن است در مسیرهای سریال‌سازی مختلف متفاوت باشد و هش‌های متفاوتی برای داده‌های یکسان تولید کند.

چک‌سام فایل SHA-256 — تأیید دانلودها و آثار

محاسبه چک‌سام SHA-256 یک فایل یکی از رایج‌ترین کاربردهای این الگوریتم است. آن را همه جا می‌بینید: صفحات انتشار باینری‌های Go، فایل‌های wheel Python، مانیفست‌های تصویر Docker، به‌روزرسانی‌های firmware. نکته کلیدی این است که فایل را به صورت تکه‌تکه بخوانید نه یکجا — یک تصویر ISO 2 گیگابایتی نباید فقط برای هش کردن نیاز به 2 گیگابایت RAM داشته باشد.

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() را اضافه کرد که خواندن تکه‌تکه را در داخل انجام می‌دهد و ممکن است از بهینه‌سازی‌های zero-copy در پلتفرم‌های پشتیبانی‌شده استفاده کند. اگر از نسخه 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 (Subresource Integrity در مرورگرها) از Base64 استفاده می‌کنند و امضاهای JWT با Base64url رمزگذاری می‌شوند. نکته کلیدی این است که bytes خام حاصل از .digest() را با Base64 رمزگذاری کنید، نه رشته هگز را.

Python 3.9+ — SHA-256 رمزگذاری‌شده با Base64
import hashlib
import base64

data = b"integrity check payload"

# صحیح: Base64 از bytes خام (۳۲ بایت → ۴۴ کاراکتر Base64)
raw_digest = hashlib.sha256(data).digest()
b64_digest = base64.b64encode(raw_digest).decode("ascii")
print(f"sha256-{b64_digest}")
# sha256-<44 کاراکتر>

# اشتباه: Base64 از رشته هگز (۶۴ بایت ASCII → ۸۸ کاراکتر Base64 — دو برابر اندازه)
hex_digest = hashlib.sha256(data).hexdigest()
wrong = base64.b64encode(hex_digest.encode()).decode()
print(f"طول اشتباه: {len(wrong)} کاراکتر")  # 88 — آنچه API‌ها انتظار دارند نیست
هشدار:رمزگذاری رشته هگز به جای bytes خام با Base64 یک اشتباه رایج است که خروجی دو برابر طول مورد انتظار تولید می‌کند. API‌ها آن را رد می‌کنند و پیام خطا معمولاً هیچ اشاره‌ای به دلیل نمی‌دهد. همیشه .digest()، نه .hexdigest()، را قبل از رمزگذاری Base64 فراخوانی کنید.

مرجع hashlib.sha256()

سازنده و متدهای یک شیء هش SHA-256:

پارامتر / متد
نوع
توضیح
data (موضعی)
bytes
داده اولیه برای هش کردن — معادل فراخوانی update(data) بلافاصله پس از ساخت شیء
.update(data)
bytes
داده بیشتری به وضعیت هش اضافه می‌کند — می‌توان چندین بار برای ورودی تکه‌تکه فراخوانی کرد
.digest()
→ bytes
خروجی خام ۳۲ بایتی را برمی‌گرداند — برای ورودی HMAC، پروتکل‌های باینری و رمزگذاری Base64 استفاده کنید
.hexdigest()
→ str
رشته هگزادسیمال ۶۴ کاراکتری با حروف کوچک را برمی‌گرداند — نمایش استاندارد برای چک‌سام‌ها و تأییدیه‌ها
.copy()
→ hash object
یک کپی از وضعیت فعلی هش برمی‌گرداند — بدون نیاز به هش مجدد از ابتدا، می‌توانید یک خروجی جداگانه بسازید
hashlib.sha256()
سازنده
یک شیء هش SHA-256 جدید مبتنی بر OpenSSL در CPython می‌سازد — usedfips=True در نسخه ۳.۹+ الگوریتم‌ها را به موارد تأییدشده FIPS محدود می‌کند

پارامترهای hmac.new() برای هش کلیددار:

پارامتر
نوع
توضیح
key
bytes
کلید محرمانه — باید bytes باشد، نه str
msg
bytes | None
پیام اولیه برای احراز هویت — به‌طور پیش‌فرض None است، می‌توان بعداً update() را فراخوانی کرد
digestmod
str | callable
الگوریتم هش: hashlib.sha256 یا رشته "sha256" را ارسال کنید

کتابخانه cryptography — یک رابط جایگزین SHA-256

پکیج cryptography از طریق اولیه‌های hazmat خود یک رابط متفاوت برای SHA-256 ارائه می‌دهد. وقتی فقط به یک هش نیاز دارم به ندرت به آن دست می‌زنم — 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()  # ۳۲ بایت خام

print(result.hex())  # رشته هگز ۶۴ کاراکتری
# 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 زیرفرمان CLI داخلی ندارد (برخلاف python3 -m json.tool)، اما می‌توانید از یک one-liner یا ابزارهای سیستمی استفاده کنید.

bash — هش یک رشته از خط فرمان
# Python one-liner
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 — هش یک فایل
# هش یک tarball انتشار
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 و shell هش‌های متفاوتی می‌گیرند.

جایگزین پرکارایی — hashlib با OpenSSL و pycryptodome

در CPython، hashlib.sha256() از قبل کار را به پیاده‌سازی C در OpenSSL واگذار می‌کند، بنابراین سریع است — معمولاً 500+ مگابایت بر ثانیه روی سخت‌افزار مدرن.

اگر هش SHA-256 در پروفایلر شما نمایان شد — مثلاً برای هزاران فایل در یک pipeline CI چک‌سام محاسبه می‌کنید یا هر بدنه درخواست را در یک API gateway پر‌ترافیک هش می‌کنید — دو گزینه وجود دارد: الگوی فراخوانی 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

برای هش موازی پرکارایی فایل‌ها، بهبودهای بزرگ‌تر از کاهش سربار Python از طریق اندازه‌های تکه بزرگ‌تر و threading حاصل می‌شود:

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""):  # تکه‌های ۶۴ کیلوبایتی
            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}")

استفاده از تکه‌های ۶۴ کیلوبایتی به جای ۸ کیلوبایتی تعداد فراخوانی‌های Python-به-C را ۸ برابر کاهش می‌دهد. thread‌ها اینجا خوب کار می‌کنند چون GIL در حین هش کردن در سطح C آزاد می‌شود — گلوگاه I/O دیسک است، نه CPU.

خروجی ترمینال با برجسته‌سازی نحوی

کتابخانه 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]✓ تأیید شد[/green]" if expected.get(name) == digest else "[red]✗ ناهمخوان[/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):  # تکه‌های ۱ مگابایتی
            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() تکه‌تکه تغییر دهید وقتی فایل‌ها از ۵۰ تا ۱۰۰ مگابایت تجاوز می‌کنند. پایین‌تر از این آستانه، خواندن کل فایل با 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')). یا برای مقادیر ثابت از literal b'' استفاده کنید.

After · Python
Before · Python
import hashlib
digest = hashlib.sha256("deployment-v4.2.1".encode("utf-8")).hexdigest()
# کار می‌کند — رشته هگز ۶۴ کاراکتری برمی‌گرداند
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)
رمزگذاری رشته هگز به جای bytes خام با Base64

مشکل: base64.b64encode(digest.hexdigest().encode()) یک رشته ۸۸ کاراکتری تولید می‌کند — دو برابر ۴۴ کاراکتر مورد انتظار. API‌هایی که Base64-encoded SHA-256 انتظار دارند آن را رد می‌کنند.

راه‌حل: قبل از رمزگذاری Base64، .digest() (bytes خام) را فراخوانی کنید، نه .hexdigest() (رشته هگز) را.

After · Python
Before · Python
import hashlib, base64
raw = hashlib.sha256(data).digest()
b64 = base64.b64encode(raw)  # ۴۴ کاراکتر — صحیح
import hashlib, base64
hex_str = hashlib.sha256(data).hexdigest()
b64 = base64.b64encode(hex_str.encode())  # ۸۸ کاراکتر — اشتباه!
خواندن یک فایل بزرگ کامل در حافظه قبل از هش کردن

مشکل: hashlib.sha256(open('large.iso', 'rb').read()) کل فایل را در حافظه بارگذاری می‌کند. یک فایل ۴ گیگابایتی فقط برای محاسبه هش به ۴ گیگابایت RAM نیاز دارد.

راه‌حل: با یک حلقه و .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
# کل فایل ۴ گیگابایتی را در حافظه بارگذاری می‌کند
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
سریع (بدون کپی)
✓ (داخلی)
خیر (نسخه ۳.۱۱+)
encode() دستی
cryptography hashes.SHA256()
bytes
سریع (OpenSSL)
✓ از طریق update()
pip install
encode() دستی
subprocess openssl dgst
hex string
✗ / ✓
کندتر (fork)
✓ (سطح سیستم‌عامل)
openssl سیستمی
encode() دستی
pyhashcat / سفارشی
متغیر
شتاب‌دهنده GPU
pip install
encode() دستی

برای هش ساده — چک‌سام‌ها، کلیدهای کش، اثرانگشت محتوا — از hashlib.sha256() استفاده کنید. به محض نیاز به کلید محرمانه (webhook‌ها، امضاهای API، احراز هویت توکن) به hmac.new() تغییر دهید. فقط اگر پروژه‌تان قبلاً برای رمزگذاری یا TLS از cryptography استفاده می‌کند به آن دست بزنید — افزودن یک وابستگی C extension فقط برای هش کردن، وقتی hashlib از قبل توسط OpenSSL پشتیبانی می‌شود، مازاد است.

آیا می‌توان SHA-256 را رمزگشایی کرد؟ — هش در برابر رمزگذاری

پاسخ کوتاه: خیر. SHA-256 یک تابع یک‌طرفه است. الگوریتم برای غیرقابل برگشت بودن طراحی شده است — نمی‌توانید ورودی اصلی را از خلاصه ۲۵۶ بیتی بازسازی کنید. این محدودیت پیاده‌سازی نیست؛ خاصیت ریاضی تابع هش است. فضای خروجی ۲۵۶ بیتی به طور نجومی بزرگ است (۲۲۵۶ مقدار ممکن)، و تابع در طول ۶۴ دور فشرده‌سازی خود اطلاعات را از بین می‌برد.

مهاجمان می‌توانند حملات brute-force یا dictionary را روی ورودی‌های ضعیف (رمزعبورهای رایج، رشته‌های کوتاه) امتحان کنند، اما برای هر ورودی با آنتروپی معقول — کلیدهای API، توکن‌های تصادفی، محتوای فایل — بازگردانی SHA-256 با سخت‌افزار فعلی از نظر محاسباتی غیرممکن است. اگر به تبدیل برگشت‌پذیر نیاز دارید، از رمزگذاری متقارن استفاده کنید:

Python 3.9+ — رمزگذاری در برابر هش
# هش — یک‌طرفه، نمی‌توان مقدار اصلی را بازیابی کرد
import hashlib
digest = hashlib.sha256(b"secret-config-value").hexdigest()
# هیچ راهی برای دستیابی به "secret-config-value" از digest وجود ندارد

# رمزگذاری — دو طرفه، می‌توان با کلید رمزگشایی کرد
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 معتبر دقیقاً ۶۴ کاراکتر هگزادسیمال (۰-۹، 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 — کاراکترهای هگز نامعتبر
توجه:این فقط فرمت را اعتبارسنجی می‌کند، نه اینکه آیا هش از یک ورودی خاص محاسبه شده است. هیچ راهی وجود ندارد که بفهمیم آیا یک رشته ۶۴ کاراکتری هگز یک خلاصه SHA-256 "واقعی" است یا فقط هگز تصادفی — خروجی SHA-256 از نظر طراحی از داده تصادفی قابل تشخیص نیست.

سوالات متداول

چطور می‌توان یک رشته را با SHA-256 در Python هش کرد؟

hashlib.sha256() را با رشته‌ای که به bytes تبدیل شده فراخوانی کنید. رشته‌ها در Python از نوع Unicode هستند و توابع هش روی bytes خام کار می‌کنند، بنابراین ابتدا باید .encode("utf-8") را فراخوانی کنید. متد .hexdigest() رشته هگزادسیمال آشنای ۶۴ کاراکتری را برمی‌گرداند.

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 یک تابع یک‌طرفه است — ورودی با طول دلخواه را به خروجی ۲۵۶ بیتی ثابت تبدیل می‌کند و ساختار آن را از بین می‌برد. هیچ معکوس ریاضی‌ای وجود ندارد. مهاجمان می‌توانند حملات brute-force یا rainbow table را بر روی ورودی‌های ضعیف (رمزعبورهای کوتاه، کلمات رایج) امتحان کنند، اما برای هر ورودی با آنتروپی معقول، بازگردانی SHA-256 از نظر محاسباتی غیرممکن است. اگر به تبدیل برگشت‌پذیر نیاز دارید، از رمزگذاری (AES-GCM، Fernet) به جای هش کردن استفاده کنید.

تفاوت .digest() و .hexdigest() چیست؟

.digest() خروجی خام ۳۲ بایتی هش را به صورت یک شیء bytes برمی‌گرداند. .hexdigest() همان داده را به صورت رشته هگزادسیمال ۶۴ کاراکتری با حروف کوچک برمی‌گرداند. از .digest() زمانی استفاده کنید که به خروجی باینری نیاز دارید — ارسال به HMAC، رمزگذاری Base64، یا نوشتن در پروتکل‌های باینری. از .hexdigest() برای لاگ‌گیری، ذخیره در پایگاه داده، و مقایسه چک‌سام استفاده کنید.

Python
import hashlib

h = hashlib.sha256(b"deployment-v4.2.1")
print(len(h.digest()))     # 32 (بایت)
print(len(h.hexdigest()))  # 64 (کاراکتر هگز)

چطور می‌توان چک‌سام SHA-256 یک فایل را در Python محاسبه کرد؟

فایل را در حالت باینری باز کنید و آن را به صورت تکه‌تکه با .update() به hasher بدهید. در 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 ۶۴ کاراکتری

چطور می‌توان بررسی کرد که آیا یک رشته یک خلاصه هگز SHA-256 معتبر است؟

یک خلاصه هگز SHA-256 دقیقاً ۶۴ کاراکتر هگزادسیمال است. از یک regex یا بررسی ساده طول + کاراکتر استفاده کنید. روش regex خواناترین است.

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.