SHA-256 Hash Python — hashlib Gids + Codevoorbeelden
Gebruik de gratis SHA-256 Hash Generator direct in je browser — geen installatie nodig.
SHA-256 Hash Generator online uitproberen →Elke deployment-pipeline die ik ooit heb gebouwd, heeft uiteindelijk een bestandschecksum nodig om te verifiëren, een webhook-payload te ondertekenen of een cache-sleutel te fingerprinting. Python SHA-256 hashing met de ingebouwde hashlib module verwerkt al deze gevallen — en je hebt hem al geïnstalleerd. hashlib.sha256() maakt gebruik van OpenSSL's implementatie op CPython, dus het is snel en FIPS-conform zonder extra configuratie. Voor een snelle eenmalige hash zonder code te schrijven, geeft de online SHA-256 hash generator direct het resultaat. Alle voorbeelden zijn gericht op Python 3.9+.
- ✓hashlib.sha256(data).hexdigest() is de standaardmanier om bytes te hashen — onderdeel van de stdlib, gebaseerd op OpenSSL.
- ✓Strings moeten eerst naar bytes worden gecodeerd: hashlib.sha256("tekst".encode("utf-8")).
- ✓Voor bestandschecksums, stuur chunks door via .update() — lees een groot bestand nooit in één keer volledig in het geheugen.
- ✓HMAC-SHA256 vereist de hmac-module: hmac.new(key, msg, hashlib.sha256) — SHA-256 alleen heeft geen sleutel.
Wat is SHA-256 hashing?
SHA-256 (Secure Hash Algorithm, 256-bit) neemt invoer van willekeurige lengte en produceert een vaste 256-bit (32-byte) digest. Dezelfde invoer levert altijd dezelfde uitvoer op, maar zelfs een verandering van één bit in de invoer produceert een volledig andere hash — deze eigenschap heet het lawiine-effect. SHA-256 maakt deel uit van de SHA-2-familie, gestandaardiseerd door NIST, en vormt de ruggengraat van TLS-certificaat-fingerprints, Git-commit-ID's, Bitcoin-blokheaders en bestandsintegriteitsverificatie. Het algoritme gebruikt een Merkle-Damgård-constructie met 64 compressieronden om zijn 256-bit uitvoer te produceren.
deployment-v4.2.1
a1f7c3d8e9b2...27ae41e4649b (64 hex chars)
De hex digest hierboven is de standaardweergave — 64 hexadecimale tekens, altijd dezelfde lengte ongeacht of je één byte hasht of een volledig schijfimage.
hashlib.sha256() — De standaardbibliotheek aanpak
De hashlib module wordt meegeleverd met elke Python-installatie — geen pip install nodig. Roep hashlib.sha256() aan met een bytes argument om een hashobject te maken, en haal vervolgens het resultaat op via .hexdigest() (hexadecimale string) of .digest() (ruwe bytes). De functienaam is in kleine letters: sha256, niet SHA256.
import hashlib # Hash een byte-string direct digest = hashlib.sha256(b"deployment-v4.2.1").hexdigest() print(digest) # a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db
De meest voorkomende fout bij hashlib.sha256() is het doorgeven van een str in plaats van bytes. Python-strings zijn Unicode en hashfuncties werken op ruwe bytes. Je moet .encode("utf-8") aanroepen voor het hashen. Dit gaat bijna iedereen de eerste keer fout.
import hashlib
# Strings moeten worden gecodeerd naar bytes voor het hashen
config_key = "redis://cache.internal:6379/0"
digest = hashlib.sha256(config_key.encode("utf-8")).hexdigest()
print(digest)
# 7d3f8c2a1b9e4f5d6c8a7b3e2f1d9c4a5b8e7f6d3c2a1b9e4f5d6c8a7b3e2f1dDe methode .update() stelt je in staat om data stapsgewijs aan te leveren. Het aanroepen van h.update(a); h.update(b) is gelijkwaardig aan hashlib.sha256(a + b). Zo hash je bestanden in stukken zonder de volledige inhoud in het geheugen te laden.
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()) # Gelijkwaardig aan hashlib.sha256(b"request_id=req_7f3a91bc×tamp=1741614120&amount=4999").hexdigest()
.digest() geeft ruwe 32 bytes terug. .hexdigest() geeft een 64-tekens lange hexadecimale string terug. Gebruik .digest() wanneer je het resultaat doorgeeft aan HMAC, Base64-codering of binaire protocollen. Gebruik .hexdigest() voor logging, databasekolommen en checksumvergelijking.HMAC-SHA256 — Gesleuteld hashen met de hmac-module
SHA-256 heeft op zichzelf geen concept van een geheime sleutel — iedereen met dezelfde invoer kan dezelfde hash berekenen. Als je moet bewijzen dat een bericht afkomstig is van een specifieke afzender (webhook-verificatie, API-request-ondertekening, tokenauthenticatie), heb je HMAC nodig. De hmac module maakt deel uit van de standaardbibliotheek van Python en verwerkt de sleutel in het hashingproces zodat alleen iemand met de sleutel dezelfde digest kan produceren of verifiëren.
import hmac
import hashlib
# Webhook-handtekeningverificatie
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)
# 64-character hex HMAC-SHA256 digestHet verifiëren van een inkomende HMAC vereist hmac.compare_digest() in plaats van de == operator. De gelijkheidsoperator is kwetsbaar voor timing-aanvallen — hij stopt bij de eerste niet-overeenkomende byte, en een aanvaller kan de reactietijden meten om de juiste handtekening byte voor byte te raden. compare_digest() werkt in constante tijd, ongeacht waar de afwijking optreedt.
import hmac
import hashlib
def verify_webhook(payload: bytes, received_sig: str, secret: bytes) -> bool:
"""Verifieer een webhook-handtekening met een constante-tijd vergelijking."""
expected = hmac.new(secret, payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, received_sig)
# Simulatie van een Stripe-stijl webhook-verificatie
incoming_payload = b'{"event":"payment.completed","amount":4999}'
incoming_signature = "a1b2c3d4e5f6..." # from the X-Signature header
webhook_secret = b"whsec_9f3a7b2e1d4c"
if verify_webhook(incoming_payload, incoming_signature, webhook_secret):
print("Handtekening geldig — verwerk het event")
else:
print("Handtekening klopt niet — wijs het verzoek af")HMAC-SHA256 request-ondertekening
API-request-ondertekening volgt hetzelfde principe: stel een canonieke string samen uit de requestcomponenten (methode, pad, tijdstempel, body-hash) en onderteken deze met je geheime sleutel. AWS Signature V4, Stripe en GitHub-webhooks gebruiken allemaal varianten van dit patroon.
import hmac
import hashlib
import time
def sign_request(method: str, path: str, body: bytes, secret: bytes) -> str:
"""Maak een HMAC-SHA256-handtekening voor een API-request."""
timestamp = str(int(time.time()))
body_hash = hashlib.sha256(body).hexdigest()
# Canonieke string: methode + pad + tijdstempel + body-hash
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}"
# Gebruik
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...Base64-gecodeerde HMAC-SHA256
Sommige API's (AWS Signature V4, diverse betalingsgateway's) verwachten het HMAC-resultaat als een Base64-gecodeerde string in plaats van hex. Het verschil: hex gebruikt 64 tekens, Base64 gebruikt 44 tekens voor dezelfde 32-byte digest.
import hmac
import hashlib
import base64
secret = b"webhook_secret_9f3a"
message = b"POST /api/v2/events 1741614120"
# Hex-uitvoer: 64 tekens
hex_sig = hmac.new(secret, message, hashlib.sha256).hexdigest()
print(f"Hex: {hex_sig}")
# Base64-uitvoer: 44 tekens (korter, gangbaar in HTTP-headers)
raw_sig = hmac.new(secret, message, hashlib.sha256).digest()
b64_sig = base64.b64encode(raw_sig).decode("ascii")
print(f"Base64: {b64_sig}")Hashen van datetime, UUID en aangepaste objecten
SHA-256 werkt op ruwe bytes, dus niet-bytes-typen — datetime, UUID, dataclasses, Pydantic-modellen — moeten naar bytes worden geserialiseerd voor het hashen. Er is geen automatische conversie; jij kiest de canonieke weergave. Voor deterministische hashing over systemen heen gebruik je altijd een expliciete codering en een stabiel serialisatieformaat (ISO 8601 voor datetimes, de standaard stringvorm voor UUID's, JSON met gesorteerde sleutels voor dicts).
import hashlib
import uuid
from datetime import datetime, timezone
# datetime — gebruik ISO 8601 met expliciete UTC-offset voor overdraagbaarheid
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 — hash de canonieke stringvorm (kleine letters, met koppeltekens)
record_id = uuid.uuid4()
uuid_hash = hashlib.sha256(str(record_id).encode("utf-8")).hexdigest()
print(f"UUID hash: {uuid_hash[:16]}...")Serialiseer aangepaste objecten naar een canonieke bytes-weergave voor het hashen. JSON met gesorteerde sleutels werkt goed voor dict-achtige objecten:
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:
"""Hash een dataclass-instantie met gesorteerd-sleutel JSON voor determinisme."""
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)) # stabiel over runs en machinessort_keys=True) bij het hashen van JSON-geserialiseerde objecten. Dict-invoegordering is behouden in Python 3.7+ maar kan verschillen via verschillende serialisatiepaden, wat leidt tot verschillende hashes voor identieke data.SHA-256 bestandschecksum — Downloads en artefacten verifiëren
Het berekenen van een SHA-256-checksum van een bestand is een van de meest voorkomende toepassingen van het algoritme. Je ziet het overal: releasepagina's voor Go-binaries, Python-wheel-bestanden, Docker-image-manifesten, firmware-updates. Het is essentieel om het bestand in stukken te lezen in plaats van alles tegelijk — een ISO-image van 2 GB zou niet 2 GB RAM moeten vereisen om te hashen.
import hashlib
def sha256_checksum(filepath: str, chunk_size: int = 8192) -> str:
"""Bereken SHA-256-hash van een bestand, gelezen in stukken om geheugen te besparen."""
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()
# Hash een release-artefact
checksum = sha256_checksum("/tmp/release-v4.2.1.tar.gz")
print(f"SHA-256: {checksum}")Python 3.11 heeft hashlib.file_digest() toegevoegd, die het lezen in stukken intern afhandelt en op ondersteunde platforms zero-copy-optimalisaties kan gebruiken. Als je op 3.11 of hoger zit, gebruik dit dan bij voorkeur boven de handmatige lus.
import hashlib
with open("/tmp/release-v4.2.1.tar.gz", "rb") as f:
digest = hashlib.file_digest(f, "sha256")
print(digest.hexdigest())Een gedownload bestand vergelijken met een bekende checksum
import hashlib
import hmac as hmac_mod # only for compare_digest
def verify_checksum(filepath: str, expected_hex: str) -> bool:
"""Verifieer SHA-256-checksum met een constante-tijdvergelijking."""
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())
# Verifieer een release-artefact
expected = "a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db"
if verify_checksum("/tmp/release-v4.2.1.tar.gz", expected):
print("Checksum komt overeen — bestand is intact")
else:
print("Checksum klopt niet — bestand is mogelijk beschadigd of gemanipuleerd")hmac.compare_digest() voor checksumvergelijking, ook als er geen geheime sleutel bij betrokken is. De constante-tijdvergelijking voorkomt lekken van informatie via timing. De == operator werkt functioneel maar is niet veilig voor beveiligingsgevoelige contexten.SHA-256 met Base64-codering
Sommige protocollen verwachten de SHA-256-digest als een Base64-string in plaats van hex. HTTP-headers zoals Content-Digest en Integrity (Subresource Integrity in browsers) gebruiken Base64, en JWT-handtekeningen zijn Base64url-gecodeerd. Het is van belang om de ruwe .digest() bytes te Base64-coderen, niet de hexadecimale string.
import hashlib
import base64
data = b"integrity check payload"
# Correct: Base64 van ruwe bytes (32 bytes → 44 Base64-tekens)
raw_digest = hashlib.sha256(data).digest()
b64_digest = base64.b64encode(raw_digest).decode("ascii")
print(f"sha256-{b64_digest}")
# sha256-<44 characters>
# Fout: Base64 van hex-string (64 ASCII-bytes → 88 Base64-tekens — dubbele grootte)
hex_digest = hashlib.sha256(data).hexdigest()
wrong = base64.b64encode(hex_digest.encode()).decode()
print(f"Verkeerde lengte: {len(wrong)} tekens") # 88 — niet wat API's verwachten.digest() aan, niet .hexdigest(), voor Base64-codering.hashlib.sha256() referentie
De constructor en methoden op een SHA-256-hashobject:
hmac.new() parameters voor gesleuteld hashen:
De cryptography-bibliotheek — een alternatieve SHA-256 API
Het cryptography pakket biedt een andere API voor SHA-256 via zijn hazmat-primitieven. Ik grijp er zelden naar als ik alleen een hash nodig heb — hashlib is eenvoudiger en heeft geen externe afhankelijkheid. Maar als je project al afhankelijk is van cryptography voor TLS, X.509 of symmetrische encryptie, houdt het gebruik van de hash-API alles onder één bibliotheek en geeft het je consistente foutafhandeling.
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() # raw 32 bytes print(result.hex()) # 64-char hex string # a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db
cryptography-bibliotheek vereist pip install cryptography. Het hashobject is voor eenmalig gebruik: .finalize() een tweede keer aanroepen geeft een AlreadyFinalized-fout. Gebruik .copy() voor het finaliseren als je de hashstatus wilt vertakken.Data hashen uit een bestand en API-respons
Twee scenario's komen voortdurend voor: een bestand op schijf hashen om een release-artefact te verifiëren, en een HTTP-responsbody hashen als cache-sleutel of om een webhook te verifiëren.
Bestand lezen → SHA-256 berekenen → Vergelijken
import hashlib
import sys
def hash_file_safe(filepath: str) -> str | None:
"""Hash een bestand met goede foutafhandeling."""
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"Fout: {filepath} niet gevonden", file=sys.stderr)
return None
except PermissionError:
print(f"Fout: geen leesrechten voor {filepath}", file=sys.stderr)
return None
result = hash_file_safe("/etc/nginx/nginx.conf")
if result:
print(f"SHA-256: {result}")HTTP-respons → Body hashen als cache-sleutel
import hashlib
import urllib.request
import json
def fetch_and_hash(url: str) -> tuple[dict, str]:
"""Haal JSON op van een API en geef zowel de data als de SHA-256-hash terug."""
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"Ophalen van {url} mislukt: {exc}") from exc
# Cache-sleutel gebaseerd op de inhoud van de respons
data, digest = fetch_and_hash("https://api.exchange.internal/v2/rates")
print(f"Response hash: {digest[:16]}...")
print(f"EUR/USD: {data.get('rates', {}).get('EUR', 'N/A')}")Voor een snelle eenmalige controle werkt ToolDeck's SHA-256 generator volledig in je browser — geen code nodig.
SHA-256 hashen via de commandoregel
Soms heb je gewoon een snelle hash nodig in de terminal tijdens een incident of deployment. Python's hashlib module heeft geen ingebouwde CLI-subcommand (in tegenstelling tot python3 -m json.tool), maar je kunt een one-liner of systeemtools gebruiken.
# 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 (platformonafhankelijk) echo -n "deployment-v4.2.1" | openssl dgst -sha256
# Hash een release-tarball sha256sum release-v4.2.1.tar.gz # of openssl dgst -sha256 release-v4.2.1.tar.gz # Vergelijken met een bekende checksum echo "a8f5f167f44f4964 release-v4.2.1.tar.gz" | sha256sum -c - # release-v4.2.1.tar.gz: OK
echo -n (zonder afsluitende newline) bij het hashen van strings via de commandoregel. Een gewone echo voegt \n toe, wat de hash verandert. Dit is de belangrijkste reden waarom mensen verschillende hashes krijgen tussen Python en de shell.Hoge-prestatiealternatief — hashlib met OpenSSL en pycryptodome
Op CPython delegeert hashlib.sha256() al aan de C-implementatie van OpenSSL, dus het is snel — doorgaans 500+ MB/s op moderne hardware.
Als SHA-256-hashing opduikt in je profiler — bijvoorbeeld bij het berekenen van checksums voor duizenden bestanden in een CI-pipeline of het hashen van elke requestbody in een API-gateway met hoge doorvoer — bestaan er twee opties: het aanroeppatroon van hashlib optimaliseren, of overstappen op pycryptodome voor een uniforme crypto-API die ook SHA-3 en BLAKE2 ondersteunt:
pip install pycryptodome
from Crypto.Hash import SHA256 h = SHA256.new() h.update(b"deployment-v4.2.1") print(h.hexdigest()) # a8f5f167f44f4964e6c998dee827110c3f1de4d0280c68cba98cf70b4b5157db
Voor parallel hashen van bestanden met hoge doorvoer komen de grootste verbeteringen van het verminderen van Python-overhead via grotere stukken en threading:
import hashlib
import os
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
def hash_file(path: Path) -> tuple[str, str]:
"""Hash één bestand en geef (pad, hex digest) terug."""
h = hashlib.sha256()
with open(path, "rb") as f:
for chunk in iter(lambda: f.read(65536), b""): # 64 KB stukken
h.update(chunk)
return str(path), h.hexdigest()
def hash_directory(directory: str, pattern: str = "*.tar.gz") -> dict[str, str]:
"""Hash alle overeenkomende bestanden parallel met threads."""
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
# Hash alle release-artefacten parallel
checksums = hash_directory("/var/releases", "*.tar.gz")
for path, digest in checksums.items():
print(f"{digest} {path}")Het gebruik van 64 KB-stukken in plaats van 8 KB vermindert het aantal Python-naar-C aanroepen met 8x. Threads werken hier goed omdat de GIL wordt vrijgegeven tijdens het hashing op C-niveau — de bottleneck is schijf-I/O, niet de CPU.
Terminaluitvoer met syntaxisaccentuering
De rich bibliotheek is handig wanneer je een reeks bestanden wilt verifiëren en een tabel wilt tonen met geslaagd/mislukt per bestand in plaats van ruwe hexuitvoer die voorbijscrolt.
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:
"""Hash bestanden en toon resultaten met kleurgecodeerde verificatie."""
table = Table(title="SHA-256 Verificatie")
table.add_column("Bestand", style="cyan")
table.add_column("SHA-256", style="dim", max_width=20)
table.add_column("Status")
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]✗ KLOPT NIET[/red]"
table.add_row(name, f"{digest[:16]}...", status)
console.print(table)
# Gebruik
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) of leid ze om naar een bestand met Console(file=open(...)).Werken met grote bestanden
Het chunked .update() patroon verwerkt bestanden van elke omvang met constant geheugengebruik. Voor zeer grote bestanden (multi-GB schijfimages, databaseback-ups) verschuift de aandacht van geheugen naar gebruikersfeedback — het hashen van 10 GB bij 500 MB/s duurt nog steeds 20 seconden, en stilte in die tijd wekt onrust.
import hashlib
import os
def sha256_with_progress(filepath: str) -> str:
"""Hash een groot bestand met voortgangsrapportage naar 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 MB stukken
h.update(chunk)
bytes_read += len(chunk)
pct = (bytes_read / file_size) * 100
print(f"\r Hashen: {pct:.1f}% ({bytes_read >> 20} MB / {file_size >> 20} MB)",
end="", flush=True)
print() # nieuwe regel na voortgang
return h.hexdigest()
digest = sha256_with_progress("/mnt/backups/db-snapshot-2026-03.sql.gz")
print(f"SHA-256: {digest}")NDJSON / JSON Lines — elk record afzonderlijk hashen
import hashlib
import json
def hash_ndjson_records(filepath: str) -> dict[str, str]:
"""Hash elk JSON-record in een NDJSON-bestand voor deduplicatie."""
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)
# Normaliseer voor het hashen: sorteer sleutels voor deterministische uitvoer
canonical = json.dumps(record, sort_keys=True, separators=(",", ":"))
digest = hashlib.sha256(canonical.encode("utf-8")).hexdigest()
if digest in seen:
print(f"Regel {line_num}: duplicaat van regel {seen[digest]}")
else:
seen[digest] = line_num
except json.JSONDecodeError:
print(f"Regel {line_num}: ongeldige JSON, overgeslagen")
print(f"Verwerkt: {line_num} regels, {len(seen)} unieke records")
return seen
hash_ndjson_records("telemetry-events-2026-03.ndjson")hashlib.sha256(data) aanroep naar de chunked .update() lus wanneer bestanden groter zijn dan 50–100 MB. Onder die drempel is het gehele bestand lezen met f.read() prima — het geheugengebruik is dan ruwweg gelijk aan de bestandsgrootte.Veelgemaakte fouten
Probleem: hashlib.sha256('tekst') geeft een TypeError: Unicode-objects must be encoded before hashing. De functie vereist bytes, niet str.
Oplossing: Codeer de string eerst: hashlib.sha256('tekst'.encode('utf-8')). Of gebruik een b''-letterwoord voor vaste waarden.
import hashlib
digest = hashlib.sha256("deployment-v4.2.1").hexdigest()
# TypeError: Unicode-objects must be encoded before hashingimport hashlib
digest = hashlib.sha256("deployment-v4.2.1".encode("utf-8")).hexdigest()
# Werkt — geeft 64-tekens hexadecimale string terugProbleem: De ==-operator stopt bij de eerste niet-overeenkomende byte. Een aanvaller kan reactietijden meten om de juiste handtekening byte voor byte te raden.
Oplossing: Gebruik hmac.compare_digest() voor alle beveiligingsgevoelige vergelijkingen — het werkt in constante tijd ongeacht waar de afwijking optreedt.
received_sig = request.headers["X-Signature"]
expected_sig = hmac.new(key, body, hashlib.sha256).hexdigest()
if received_sig == expected_sig: # kwetsbaar voor timing-aanvallen
process_webhook(body)received_sig = request.headers["X-Signature"]
expected_sig = hmac.new(key, body, hashlib.sha256).hexdigest()
if hmac.compare_digest(received_sig, expected_sig): # constante tijd
process_webhook(body)Probleem: base64.b64encode(digest.hexdigest().encode()) produceert een string van 88 tekens — het dubbele van de verwachte 44 tekens. API's die Base64-gecodeerde SHA-256 verwachten, zullen dit weigeren.
Oplossing: Roep .digest() (ruwe bytes) aan voor Base64-codering, niet .hexdigest() (hex-string).
import hashlib, base64 hex_str = hashlib.sha256(data).hexdigest() b64 = base64.b64encode(hex_str.encode()) # 88 tekens — fout!
import hashlib, base64 raw = hashlib.sha256(data).digest() b64 = base64.b64encode(raw) # 44 tekens — correct
Probleem: hashlib.sha256(open('large.iso', 'rb').read()) laadt het volledige bestand in het geheugen. Een bestand van 4 GB vereist 4 GB RAM alleen voor de hashberekening.
Oplossing: Lees in stukken met een lus en .update(). Het geheugengebruik blijft constant ongeacht de bestandsgrootte.
import hashlib
# Laadt het volledige 4 GB-bestand in geheugen
digest = hashlib.sha256(open("disk.iso", "rb").read()).hexdigest()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() # constant geheugengebruikhashlib vs hmac vs alternatieven — Snelle vergelijking
Voor eenvoudig hashen — checksums, cache-sleutels, content-fingerprinting — gebruik hashlib.sha256(). Schakel over naar hmac.new() zodra je een geheime sleutel nodig hebt (webhooks, API-handtekeningen, tokenauthenticatie). Gebruik de cryptography bibliotheek alleen als je project al gebruikmaakt van encryptie of TLS — een C-extensie toevoegen puur voor hashing is overdreven als hashlib al door OpenSSL wordt ondersteund.
Kun je SHA-256 ontcijferen? — Hashing versus encryptie
Kort antwoord: nee. SHA-256 is een eenrichtingsfunctie. Het algoritme is ontworpen om onomkeerbaar te zijn — je kunt de originele invoer niet reconstrueren uit de 256-bit digest. Dit is geen implementatiebeperking; het is een wiskundige eigenschap van de hashfunctie. De 256-bit uitvoerruimte is astronomisch groot (2256 mogelijke waarden) en de functie gooit informatie weg tijdens zijn 64 compressieronden.
Aanvallers kunnen brute-force of woordenboekaanvallen proberen op zwakke invoer (gangbare wachtwoorden, korte strings), maar voor invoer met redelijke entropie — API-sleutels, willekeurige tokens, bestandsinhoud — is het omkeren van SHA-256 computationeel onhaalbaar met de huidige hardware. Als je een omkeerbare transformatie nodig hebt, gebruik dan symmetrische encryptie:
# Hashing — eenrichtingsverkeer, origineel niet te herstellen import hashlib digest = hashlib.sha256(b"secret-config-value").hexdigest() # Geen manier om "secret-config-value" terug te krijgen uit digest # Encryptie — twee richtingen, te ontcijferen met de sleutel 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" — origineel hersteld
Voor een snelle manier om zonder installatie een SHA-256-hash te genereren, werkt de online tool volledig in je browser.
Controleren of een string een geldige SHA-256-hash is in Python
Een geldige SHA-256 hex digest bestaat uit precies 64 hexadecimale tekens (0-9, a-f, A-F). Snelle validatie vóór het verwerken van onbetrouwbare invoer voorkomt verwarrende fouten verderop.
import re
def is_sha256_hex(value: str) -> bool:
"""Controleer of een string overeenkomt met het SHA-256 hex digest-formaat."""
return bool(re.fullmatch(r"[a-fA-F0-9]{64}", value))
# Testgevallen
print(is_sha256_hex("e3b0c44298fc1c149afbf4c8996fb924"
"27ae41e4649b934ca495991b7852b855")) # True — SHA-256 van lege string
print(is_sha256_hex("e3b0c44298fc1c14")) # False — te kort
print(is_sha256_hex("zzzz" * 16)) # False — ongeldige hex-tekensVeelgestelde vragen
Hoe hash ik een string met SHA-256 in Python?
Roep hashlib.sha256() aan met de string gecodeerd naar bytes. Strings in Python zijn Unicode en hashfuncties werken op ruwe bytes, dus je moet eerst .encode("utf-8") aanroepen. De methode .hexdigest() geeft de bekende 64-tekens lange hexadecimale string terug.
import hashlib
api_key = "sk_live_9f3a7b2e1d4c"
digest = hashlib.sha256(api_key.encode("utf-8")).hexdigest()
print(digest)
# e3b7c4a1f8d2...64 hex charactersKun je een SHA-256-hash terugdraaien naar de originele tekst?
Nee. SHA-256 is een eenrichtingsfunctie — het zet invoer van willekeurige lengte om in een vaste 256-bit uitvoer en gooit daarbij structuur weg. Er bestaat geen wiskundig inverse. Aanvallers kunnen brute-force of rainbow table-aanvallen uitvoeren op zwakke invoer (korte wachtwoorden, veelgebruikte woorden), maar voor invoer met voldoende entropie is het omkeren van SHA-256 computationeel onhaalbaar. Als je een omkeerbare transformatie nodig hebt, gebruik dan encryptie (AES-GCM, Fernet) in plaats van hashing.
Wat is het verschil tussen .digest() en .hexdigest()?
.digest() geeft de ruwe 32 bytes van de hash terug als bytes-object. .hexdigest() geeft dezelfde data terug gecodeerd als een 64-tekens lange hexadecimale string in kleine letters. Gebruik .digest() wanneer je binaire uitvoer nodig hebt — voor invoer in HMAC, Base64-codering of het schrijven naar binaire protocollen. Gebruik .hexdigest() wanneer je een leesbare string nodig hebt voor logging, databaseopslag of vergelijking van checksums.
import hashlib h = hashlib.sha256(b"deployment-v4.2.1") print(len(h.digest())) # 32 (bytes) print(len(h.hexdigest())) # 64 (hex characters)
Hoe bereken ik de SHA-256-checksum van een bestand in Python?
Open het bestand in binaire modus en stuur het in stukken door naar de hasher via .update(). Op Python 3.11+ gebruik je hashlib.file_digest() voor een nog eenvoudigere API. Roep nooit f.read() aan op grote bestanden — dat laadt het hele bestand in het geheugen.
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"))Hoe maak ik een HMAC-SHA256-handtekening in Python?
Gebruik de hmac-module met hashlib.sha256 als digestmod. Geef de geheime sleutel en het bericht mee als bytes. Het resultaat is een gesleutelde hash die zowel integriteit als authenticiteit aantoont — de ontvanger heeft dezelfde sleutel nodig om te verifiëren.
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) # 64-char hex HMACHoe controleer ik of een string een geldige SHA-256 hex digest is?
Een SHA-256 hex digest bestaat uit precies 64 hexadecimale tekens. Gebruik een regex of een eenvoudige lengte- en tekencontrole. De regex-aanpak is het meest leesbaar.
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")) # FalseGerelateerde tools
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.