هش SHA-256 در Python — راهنمای hashlib + مثالهای کد
از تولیدکننده هش 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 با ۶۴ دور فشردهسازی برای تولید خروجی ۲۵۶ بیتی استفاده میکند.
a1f7c3d8e9b2...27ae41e4649b (64 کاراکتر هگز)
deployment-v4.2.1
خلاصه هگز بالا نمایش استاندارد است — ۶۴ کاراکتر هگزادسیمال، همیشه با طول ثابت صرفنظر از اینکه یک بایت هش کرده باشید یا یک تصویر کامل دیسک.
hashlib.sha256() — رویکرد کتابخانه استاندارد
ماژول hashlib با هر نصب Python همراه است — نیازی به pip install نیست. hashlib.sha256() را با یک آرگومان bytes فراخوانی کنید تا یک شیء هش بسازید، سپس نتیجه را با .hexdigest() (رشته هگز) یا .digest() (bytes خام) دریافت کنید. نام تابع با حروف کوچک است: sha256، نه SHA256.
import hashlib # هش مستقیم یک رشته بایتی digest = hashlib.sha256(b"deployment-v4.2.1").hexdigest() print(digest) # a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db
رایجترین اشتباه در hashlib.sha256() ارسال str به جای bytes است. رشتههای Python از نوع Unicode هستند و توابع هش روی bytes خام کار میکنند. باید قبل از هش کردن .encode("utf-8") را فراخوانی کنید. این موضوع تقریباً همه را دفعه اول گیج میکند.
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) است. این روشی است که فایلها را تکهتکه هش میکنید بدون اینکه تمام محتوا را در حافظه بارگذاری کنید.
import hashlib h = hashlib.sha256() h.update(b"request_id=req_7f3a91bc") h.update(b"×tamp=1741614120") h.update(b"&amount=4999") print(h.hexdigest()) # معادل hashlib.sha256(b"request_id=req_7f3a91bc×tamp=1741614120&amount=4999").hexdigest()
.digest() خروجی خام ۳۲ بایتی را برمیگرداند. .hexdigest() یک رشته هگز ۶۴ کاراکتری برمیگرداند. از .digest() زمانی استفاده کنید که نتیجه را به HMAC، رمزگذاری Base64، یا پروتکلهای باینری میدهید. از .hexdigest() برای لاگگیری، ستونهای پایگاه داده، و مقایسه چکسام استفاده کنید.HMAC-SHA256 — هش کلیددار با ماژول hmac
SHA-256 به تنهایی هیچ مفهومی از کلید محرمانه ندارد — هر کسی با همان ورودی میتواند همان هش را محاسبه کند. اگر نیاز دارید ثابت کنید که یک پیام از یک فرستنده خاص آمده است (تأیید webhook، امضای درخواست API، احراز هویت توکن)، به HMAC نیاز دارید. ماژول hmac بخشی از کتابخانه استاندارد Python است و کلید را در فرآیند هش کردن جاسازی میکند به طوری که فقط کسی با کلید میتواند همان خلاصه را تولید یا تأیید کند.
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() صرفنظر از اینکه ناهمخوانی کجا رخ دهد، در زمان ثابت اجرا میشود.
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 همه از تغییرات این الگو استفاده میکنند.
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 برای همان خلاصه ۳۲ بایتی ۴۴ کاراکتر استفاده میکند.
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ها).
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مانند به خوبی کار میکند:
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). ترتیب درج dict در Python 3.7+ حفظ میشود اما ممکن است در مسیرهای سریالسازی مختلف متفاوت باشد و هشهای متفاوتی برای دادههای یکسان تولید کند.چکسام فایل SHA-256 — تأیید دانلودها و آثار
محاسبه چکسام SHA-256 یک فایل یکی از رایجترین کاربردهای این الگوریتم است. آن را همه جا میبینید: صفحات انتشار باینریهای Go، فایلهای wheel Python، مانیفستهای تصویر Docker، بهروزرسانیهای firmware. نکته کلیدی این است که فایل را به صورت تکهتکه بخوانید نه یکجا — یک تصویر ISO 2 گیگابایتی نباید فقط برای هش کردن نیاز به 2 گیگابایت RAM داشته باشد.
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 یا بالاتر استفاده میکنید، آن را به حلقه دستی ترجیح دهید.
import hashlib
with open("/tmp/release-v4.2.1.tar.gz", "rb") as f:
digest = hashlib.file_digest(f, "sha256")
print(digest.hexdigest())تأیید فایل دانلودشده در برابر یک چکسام شناختهشده
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 رمزگذاری کنید، نه رشته هگز را.
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ها انتظار دارند نیست.digest()، نه .hexdigest()، را قبل از رمزگذاری Base64 فراخوانی کنید.مرجع hashlib.sha256()
سازنده و متدهای یک شیء هش SHA-256:
پارامترهای hmac.new() برای هش کلیددار:
کتابخانه cryptography — یک رابط جایگزین SHA-256
پکیج cryptography از طریق اولیههای hazmat خود یک رابط متفاوت برای SHA-256 ارائه میدهد. وقتی فقط به یک هش نیاز دارم به ندرت به آن دست میزنم — hashlib سادهتر است و وابستگی خارجی ندارد. اما اگر پروژهتان قبلاً به cryptography برای TLS، X.509، یا رمزگذاری متقارن وابسته است، استفاده از رابط هش آن همه چیز را زیر یک کتابخانه نگه میدارد و مدیریت خطا را یکپارچه میکند.
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 → مقایسه
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 → هش بدنه برای کلید کش
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 یا ابزارهای سیستمی استفاده کنید.
# 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
# هش یک 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 را هم پوشش میدهد تغییر دهید:
pip install pycryptodome
from Crypto.Hash import SHA256 h = SHA256.new() h.update(b"deployment-v4.2.1") print(h.hexdigest()) # a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db
برای هش موازی پرکارایی فایلها، بهبودهای بزرگتر از کاهش سربار Python از طریق اندازههای تکه بزرگتر و threading حاصل میشود:
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 زمانی مفید است که نیاز دارید یک دسته از فایلها را تأیید کنید و میخواهید یک جدول نشاندهنده وضعیت قبول/رد به ازای هر فایل داشته باشید به جای اینکه خروجی هگز خام از صفحه رد شود.
pip install 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,
)console.print(data, highlight=False) پاک کنید یا با Console(file=open(...)) به فایل هدایت کنید.کار با فایلهای بزرگ
الگوی .update() تکهتکه، فایلهایی با هر اندازه را با استفاده ثابت از حافظه مدیریت میکند. برای فایلهای خیلی بزرگ (تصاویر دیسک چند گیگابایتی، پشتیبانهای پایگاه داده)، نگرانی اصلی از حافظه به بازخورد کاربر تغییر میکند — هش کردن 10 گیگابایت با سرعت 500 مگابایت بر ثانیه هنوز 20 ثانیه طول میکشد، و سکوت در آن مدت نگرانکننده است.
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 — هش کردن جداگانه هر رکورد
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() کافی است — مصرف حافظه تقریباً برابر اندازه فایل خواهد بود.اشتباهات رایج
مشکل: hashlib.sha256('text') خطای TypeError میدهد: Unicode-objects must be encoded before hashing. این تابع به bytes نیاز دارد، نه str.
راهحل: ابتدا رشته را رمزگذاری کنید: hashlib.sha256('text'.encode('utf-8')). یا برای مقادیر ثابت از literal b'' استفاده کنید.
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() برای تمام مقایسههای حساس امنیتی استفاده کنید — صرفنظر از اینکه ناهمخوانی کجا رخ دهد در زمان ثابت اجرا میشود.
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.b64encode(digest.hexdigest().encode()) یک رشته ۸۸ کاراکتری تولید میکند — دو برابر ۴۴ کاراکتر مورد انتظار. APIهایی که Base64-encoded SHA-256 انتظار دارند آن را رد میکنند.
راهحل: قبل از رمزگذاری Base64، .digest() (bytes خام) را فراخوانی کنید، نه .hexdigest() (رشته هگز) را.
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() به صورت تکهتکه بخوانید. مصرف حافظه صرفنظر از اندازه فایل ثابت میماند.
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() استفاده کنید. به محض نیاز به کلید محرمانه (webhookها، امضاهای API، احراز هویت توکن) به hmac.new() تغییر دهید. فقط اگر پروژهتان قبلاً برای رمزگذاری یا TLS از cryptography استفاده میکند به آن دست بزنید — افزودن یک وابستگی C extension فقط برای هش کردن، وقتی hashlib از قبل توسط OpenSSL پشتیبانی میشود، مازاد است.
آیا میتوان SHA-256 را رمزگشایی کرد؟ — هش در برابر رمزگذاری
پاسخ کوتاه: خیر. SHA-256 یک تابع یکطرفه است. الگوریتم برای غیرقابل برگشت بودن طراحی شده است — نمیتوانید ورودی اصلی را از خلاصه ۲۵۶ بیتی بازسازی کنید. این محدودیت پیادهسازی نیست؛ خاصیت ریاضی تابع هش است. فضای خروجی ۲۵۶ بیتی به طور نجومی بزرگ است (۲۲۵۶ مقدار ممکن)، و تابع در طول ۶۴ دور فشردهسازی خود اطلاعات را از بین میبرد.
مهاجمان میتوانند حملات brute-force یا dictionary را روی ورودیهای ضعیف (رمزعبورهای رایج، رشتههای کوتاه) امتحان کنند، اما برای هر ورودی با آنتروپی معقول — کلیدهای API، توکنهای تصادفی، محتوای فایل — بازگردانی SHA-256 با سختافزار فعلی از نظر محاسباتی غیرممکن است. اگر به تبدیل برگشتپذیر نیاز دارید، از رمزگذاری متقارن استفاده کنید:
# هش — یکطرفه، نمیتوان مقدار اصلی را بازیابی کرد 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) است. اعتبارسنجی سریع قبل از پردازش ورودی غیرقابل اعتماد از خطاهای گیجکننده در پاییندست جلوگیری میکند.
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 در Python هش کرد؟
hashlib.sha256() را با رشتهای که به bytes تبدیل شده فراخوانی کنید. رشتهها در Python از نوع Unicode هستند و توابع هش روی bytes خام کار میکنند، بنابراین ابتدا باید .encode("utf-8") را فراخوانی کنید. متد .hexdigest() رشته هگزادسیمال آشنای ۶۴ کاراکتری را برمیگرداند.
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() برای لاگگیری، ذخیره در پایگاه داده، و مقایسه چکسام استفاده کنید.
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() را روی فایلهای بزرگ فراخوانی نکنید — این کار تمام محتوای فایل را در حافظه بارگذاری میکند.
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 ارسال کنید. نتیجه یک هش کلیددار است که هم صحت و هم اصالت را اثبات میکند — گیرنده برای تأیید به همان کلید نیاز دارد.
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 خواناترین است.
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ابزارهای مرتبط
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.
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.