SHA-256 Hash Python — hashlib Gids + Codevoorbeelden

·DevOps Engineer & Python Automation Specialist·Beoordeeld doorMaria Santos·Gepubliceerd

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.

Before · text
After · text
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.

Python 3.9+ — minimale SHA-256 hash
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.

Python 3.9+ — een string hashen
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)
# 7d3f8c2a1b9e4f5d6c8a7b3e2f1d9c4a5b8e7f6d3c2a1b9e4f5d6c8a7b3e2f1d

De 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.

Python 3.9+ — incrementeel hashen met 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())
# Gelijkwaardig aan hashlib.sha256(b"request_id=req_7f3a91bc&timestamp=1741614120&amount=4999").hexdigest()
Opmerking:.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.

Python 3.9+ — basis HMAC-SHA256
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 digest

Het 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.

Python 3.9+ — een webhook-handtekening verifiëren
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.

Python 3.9+ — een API-request ondertekenen met HMAC-SHA256
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.

Python 3.9+ — Base64-gecodeerde HMAC-SHA256
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).

Python 3.9+ — een datetime en UUID hashen
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:

Python 3.9+ — een aangepast object hashen
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 machines
Opmerking:Sorteer altijd dict-sleutels (sort_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.

Python 3.9+ — SHA-256-checksum van een bestand (in stukken)
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.

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())

Een gedownload bestand vergelijken met een bekende checksum

Python 3.9+ — checksumverificatie
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")
Opmerking:Gebruik altijd 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.

Python 3.9+ — Base64-gecodeerde SHA-256
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
Waarschuwing:De hex-string Base64-coderen in plaats van de ruwe bytes is een veelgemaakte fout die een uitvoer oplevert die twee keer zo lang is als verwacht. API's zullen dit weigeren, en de foutmelding geeft gewoonlijk geen aanwijzing over de oorzaak. Roep altijd .digest() aan, niet .hexdigest(), voor Base64-codering.

hashlib.sha256() referentie

De constructor en methoden op een SHA-256-hashobject:

Parameter / Methode
Type
Beschrijving
data (positioneel)
bytes
Begindata om te hashen — gelijkwaardig aan het direct aanroepen van update(data) na aanmaken
.update(data)
bytes
Voeg extra bytes toe aan de hashstatus — kan meerdere keren worden aangeroepen voor gedeeltelijke invoer
.digest()
→ bytes
Geeft de onbewerkte 32-byte binaire digest terug — gebruik voor HMAC-invoer, binaire protocollen en Base64-codering
.hexdigest()
→ str
Geeft de 64-tekens lange kleine-letter hexadecimale string terug — de standaardweergave voor checksums en verificatie
.copy()
→ hash-object
Geeft een kopie van de huidige hashstatus terug — hiermee kun je een digest vertakken zonder opnieuw te hashen
hashlib.sha256()
constructor
Maakt een nieuw SHA-256-hashobject aan, gebaseerd op OpenSSL in CPython — usedfips=True op 3.9+ beperkt tot FIPS-goedgekeurde algoritmen

hmac.new() parameters voor gesleuteld hashen:

Parameter
Type
Beschrijving
key
bytes
De geheime sleutel — moet bytes zijn, niet een str
msg
bytes | None
Eerste bericht om te authenticeren — standaard None, je kunt later update() aanroepen
digestmod
str | callable
Hash-algoritme: geef hashlib.sha256 of de string "sha256" mee

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.

Python 3.9+ — SHA-256 met de cryptography-bibliotheek
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
Waarschuwing:De 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

Python 3.9+ — een configuratie-backup hashen met foutafhandeling
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

Python 3.9+ — een API-respons hashen
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.

bash — een string hashen via de commandoregel
# 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
bash — een bestand hashen
# 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
Opmerking:Gebruik altijd 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:

bash — pycryptodome installeren
pip install pycryptodome
Python 3.9+ — SHA-256 met 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:

Python 3.9+ — bestanden in batch hashen met hashlib
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.

bash — rich installeren
pip install rich
Python 3.9+ — rich-uitvoer voor hashverificatie
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,
)
Opmerking:Rich-uitvoer is alleen voor terminalweergave. Schrijf geen ANSI-escapecodes naar logbestanden of API-reacties — verwijder ze met 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.

Python 3.9+ — grote bestanden hashen met voortgangsrapportage
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

Python 3.9+ — individuele records hashen in een NDJSON-stream
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")
Opmerking:Schakel over van de eenvoudige 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

Een str doorgeven in plaats van bytes aan hashlib.sha256()

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.

Before · Python
After · Python
import hashlib
digest = hashlib.sha256("deployment-v4.2.1").hexdigest()
# TypeError: Unicode-objects must be encoded before hashing
import hashlib
digest = hashlib.sha256("deployment-v4.2.1".encode("utf-8")).hexdigest()
# Werkt — geeft 64-tekens hexadecimale string terug
== gebruiken in plaats van hmac.compare_digest() voor handtekeningverificatie

Probleem: 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.

Before · Python
After · Python
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)
De hex-string Base64-coderen in plaats van ruwe bytes

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).

Before · Python
After · Python
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
Een groot bestand volledig in geheugen laden voor het hashen

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.

Before · Python
After · Python
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 geheugengebruik

hashlib vs hmac vs alternatieven — Snelle vergelijking

Methode
Uitvoer
Gesleuteld
Snelheid
Bestanden streamen
Installatie vereist
Aangepaste typen
hashlib.sha256()
hex / bytes
Snel (C/OpenSSL)
✓ via update()
Nee (stdlib)
Handmatig encode()
hmac.new()
hex / bytes
Snel (C/OpenSSL)
✓ via update()
Nee (stdlib)
Handmatig encode()
hashlib.file_digest()
hex / bytes
Snel (zero-copy)
✓ (ingebouwd)
Nee (3.11+)
Handmatig encode()
cryptography hashes.SHA256()
bytes
Snel (OpenSSL)
✓ via update()
pip install
Handmatig encode()
subprocess openssl dgst
hex string
✗ / ✓
Langzamer (fork)
✓ (OS-niveau)
System openssl
Handmatig encode()
pyhashcat / custom
varieert
GPU-versneld
pip install
Handmatig encode()

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:

Python 3.9+ — encryptie versus hashing
# 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.

Python 3.9+ — SHA-256-formaat valideren
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-tekens
Opmerking:Dit valideert alleen het formaat, niet of de hash werd berekend uit een bepaalde invoer. Er is geen manier om te bepalen of een 64-tekens lange hex-string een "echte" SHA-256-digest is of gewoon willekeurige hex — de uitvoer van SHA-256 is door ontwerp niet te onderscheiden van willekeurige data.

Veelgestelde 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.

Python
import hashlib

api_key = "sk_live_9f3a7b2e1d4c"
digest = hashlib.sha256(api_key.encode("utf-8")).hexdigest()
print(digest)
# e3b7c4a1f8d2...64 hex characters

Kun 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.

Python
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.

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"))

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.

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)  # 64-char hex HMAC

Hoe 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.

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

Gerelateerde tools

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 SantosTechnisch beoordelaar

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.